我有一张由七种不同颜色组成的RGB图像。
我希望能够高效地统计每种像素类型在图像中出现的次数,而不是手动循环每个像素(如果可能的话,使用numpy操作是可以的,因为它速度更快)。
我尝试将其加载到numpy数组中,得到了一个大小为N*M*3的数组,但我无法找到一种方法来计算特定值的像素数量...
有什么想法吗?
谢谢!
我有一张由七种不同颜色组成的RGB图像。
我希望能够高效地统计每种像素类型在图像中出现的次数,而不是手动循环每个像素(如果可能的话,使用numpy操作是可以的,因为它速度更快)。
我尝试将其加载到numpy数组中,得到了一个大小为N*M*3的数组,但我无法找到一种方法来计算特定值的像素数量...
有什么想法吗?
谢谢!
np.unique
,并设置 return_counts = True
和 axis = 0
。flat_image = image.reshape(-1, 3) # makes one long line of pixels
colors, counts = np.unique(flat_image, return_counts = True, axis = 0)
或者写成一行:
colors, counts = np.unique(image.reshape(-1, 3),
return_counts = True,
axis = 0)
由于只有七种颜色,简单的掩码在合理的假设下将会相当竞争。以下时间是针对100x100x3 @ 8位随机图像的:
timings
np.unique 6.510251379047986
masking 0.2401340039796196
import numpy as np
def create(M, N, k=7):
while True:
colors = np.random.randint(0, 256**3, (k,), dtype=np.int32)
if np.unique(colors).size == k:
break
picture = colors[np.random.randint(0, k, (M, N))]
RGB = np.s_[..., :-1] if picture.dtype.str.startswith('<') else np.s_[..., 1:]
return picture.view(np.uint8).reshape(*picture.shape, 4)[RGB]
def f_df(image):
return np.unique(image.reshape(-1, 3),
return_counts = True,
axis = 0)
def f_pp(image, nmax=50):
iai32 = np.pad(image, ((0, 0), (0, 0), (0, 1)), mode='constant')
iai32 = iai32.view(np.uint32).ravel()
colors = np.empty((nmax+1,), np.uint32)
counts = np.empty((nmax+1,), int)
colors[0] = iai32[0]
counts[0] = 0
match = iai32 == colors[0]
for i in range(1, nmax+1):
counts[i] = np.count_nonzero(match)
if counts[i] == iai32.size:
return colors.view(np.uint8).reshape(-1, 4)[:i, :-1], np.diff(counts[:i+1])
colors[i] = iai32[match.argmin()]
match |= iai32 == colors[i]
raise ValueError('Too many colors')
image = create(100, 100, 7)
col_df, cnt_df = f_df(image)
col_pp, cnt_pp = f_pp(image)
#print(col_df)
#print(cnt_df)
#print(col_pp)
#print(cnt_pp)
idx_df = np.lexsort(col_df.T)
idx_pp = np.lexsort(col_pp.T)
assert np.all(cnt_df[idx_df] == cnt_pp[idx_pp])
from timeit import timeit
print('timings')
print('np.unique', timeit(lambda: f_df(image), number=1000))
print('masking ', timeit(lambda: f_pp(image), number=1000))