numpy:图像中独特颜色列表

27 投票
5 回答
21619 浏览
提问于 2025-04-18 13:32

我有一张图片 img

>>> img.shape
(200, 200, 3)

在像素点 (100, 100) 上,我有一个很好看的颜色:

>>> img[100,100]
array([ 0.90980393,  0.27450982,  0.27450982], dtype=float32)

现在我想问的是:这张图片里有多少种不同的颜色?我该怎么把它们列出来呢?

我最开始的想法是用 numpy.unique(),但我好像用错了。

5 个回答

1

关于独特颜色(或者更一般来说,在某个方向上独特的值)的问题,之前也有人在这里提过,特别是可以看看这个回答。如果你想要最快的解决方案,那么“void view”就是你最好的选择:

axis=2
np.unique(
        img.view(np.dtype((np.void, img.dtype.itemsize*img.shape[axis])))
        ).view(img.dtype).reshape(-1, img.shape[axis])

至于这个脚本到底做了什么,有关的问题可以参考上面的链接。

1

如果你需要统计每种颜色出现的次数,可以使用下面的代码:

from collections import Counter
Counter([tuple(colors) for i in img for colors in i])
2

一种简单的方法是利用将所有像素放入一个集合时会自动去重的特性:

unique_pixels = np.vstack({tuple(r) for r in img.reshape(-1,3)})

另一种可能更实用的方法,具体取决于你提取独特像素的原因,是使用Numpy的 histogramdd 函数,将图像像素分组到一些预先设定的精度,如下所示(假设某个图像通道的像素值范围是从0到1):

n_bins = 10
bin_edges = np.linspace(0, 1, n_bins + 1)
bin_centres = (bin_edges[0:-1] + bin_edges[1::]) / 2.
hist, _ = np.histogramdd(img.reshape(-1, 3), bins=np.vstack(3 * [bin_edges]))
unique_pixels = np.column_stack(bin_centres[dim] for dim in np.where(hist))
60

你最开始的想法是用 numpy.unique(),这个方法其实可以很好地完成这个任务,而且效率很高:

numpy.unique(img.reshape(-1, img.shape[2]), axis=0)

首先,我们把矩阵的行和列都展开。现在这个矩阵的行数和图像中的像素数量一样多。每一列则代表每个像素的颜色成分。

接着,我们统计展开后矩阵中独特的行数。

5

你可以这样做:

set( tuple(v) for m2d in img for v in m2d )

撰写回答