简体   繁体   中英

numpy: unique list of colors in the image

I have an image img :

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

On pixel (100, 100) I have a nice color:

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

Now my question is: How many different colors are there in this image, and how do I enumerate them?

My first idea was numpy.unique() , but somehow I am using this wrong.

Your initial idea to use numpy.unique() actually can do the job perfectly with the best performance:

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

At first, we flatten rows and columns of matrix. Now the matrix has as much rows as there're pixels in the image. Columns are color components of each pixels.

Then we count unique rows of flattened matrix.

你可以这样做:

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

One straightforward way to do this is to leverage the de-duplication that occurs when casting a list of all pixels as a set:

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

Another way that might be of practical use, depending on your reasons for extracting unique pixels, would be to use Numpy's histogramdd function to bin image pixels to some pre-specified fidelity as follows (where it is assumed pixel values range from 0 to 1 for a given image channel):

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))

If for any reason you will need to count the number of times each unique color appears, you can use this:

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

The question about unique colors (or more generally unique values along a given axis) has been also asked here (in particular, see this answer ). If you're seeking for the fastest available option then "void view" would be your weapon of choice:

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

For any questions related to what the script actually does, I refer the reader to the links above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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