[英]Count of values in numpy.ndarray
有什么辦法可以在純粹的numpy(或opencv)中執行以下操作?
img = cv2.imread("test.jpg")
counts = defaultdict(int)
for row in img:
for val in row:
counts[tuple(val)] += 1
問題在於, tuple(val)
顯然可以是2 ^ 24個不同值之一,因此不可能為每個可能的值都擁有一個數組,因為它將是巨大的,並且大多為零,所以我需要一個更有效的數據結構。
解決此問題的最快方法是:如果圖像以“塊狀”格式存儲,即顏色平面維是最后一個,並且該維是連續的,則對每個24位像素采取np.void
視圖,然后運行結果通過np.unique
和np.bincount
:
>>> arr = np.random.randint(256, size=(10, 10, 3)).astype(np.uint8)
>>> dt = np.dtype((np.void, arr.shape[-1]*arr.dtype.itemsize))
>>> if arr.strides[-1] != arr.dtype.itemsize:
... arr = np.ascontiguousarray(arr)
...
>>> arr_view = arr.view(dt)
arr_view
的內容看起來像垃圾:
>>> arr_view [0, 0]
array([Â],
dtype='|V3')
但這不是我們必須理解的內容:
>>> unq, _ = np.unique(arr_view, return_inverse=True)
>>> unq_cnts = np.bincount(_)
>>> unq = unq.view(arr.dtype).reshape(-1, arr.shape[-1])
現在,您在這兩個數組中具有唯一的像素及其數量:
>>> unq[:5]
array([[ 0, 82, 78],
[ 6, 221, 188],
[ 9, 209, 85],
[ 14, 210, 24],
[ 14, 254, 88]], dtype=uint8)
>>> unq_cnts[:5]
array([1, 1, 1, 1, 1], dtype=int64)
這是我的解決方案:
sort()
數組 diff()
查找顏色改變的所有位置。 diff()
查找每種顏色的計數。 編碼:
In [50]:
from collections import defaultdict
import cv2
import numpy as np
img = cv2.imread("test.jpg")
In [51]:
%%time
counts = defaultdict(int)
for row in img:
for val in row:
counts[tuple(val)] += 1
Wall time: 1.29 s
In [53]:
%%time
img2 = np.concatenate((img, np.zeros_like(img[:, :, :1])), axis=2).view(np.uint32).ravel()
img2.sort()
pos = np.r_[0, np.where(np.diff(img2) != 0)[0] + 1]
count = np.r_[np.diff(pos), len(img2) - pos[-1]]
r, g, b, _ = img2[pos].view(np.uint8).reshape(-1, 4).T
colors = zip(r, g, b)
result = dict(zip(colors, count))
Wall time: 177 ms
In [49]:
counts == result
Out[49]:
True
如果可以使用pandas,則可以調用pandas.value_counts()
,它是在帶有哈希表的cython中實現的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.