繁体   English   中英

numpy.ndarray中的值计数

[英]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.uniquenp.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)

这是我的解决方案:

  • 使用dtype = uint32将图像转换为一维数组
  • 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM