Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ranking pixels by colour with OpenCV

Tags:

c++

opencv

I begin a project about the detection. My idea is to rank every pixels of an image (Mat). Then, I will be able to exit which colour is dominant.

The difficulty is a colour is not unic. For exemple, Green is rgb(0, 255, 0) but is almost rgb(10, 240, 20) too.

The goal of my ranking is to exit pixels which are almost same colour. Then, with a pourcentage, I think I can locate my object.

So, my question: Is it a way to ranking pixels by colour ?

Thx a lot in advance for your answers.

like image 534
Stalyon Avatar asked Sep 29 '22 03:09

Stalyon


2 Answers

There isn't a straight method of ranking as you say of pixels in colours. However, you can find an approximation to the most dominant one.

There are several way in which you can do it:

  1. You can calculate the histogram for each colour channel - split it into the R,G,B and compute the histogram. Then you can see where the peaks of the resulting graphs are - e.g.
  2. If you k-means cluster the pixels at the image - in other words, represent each pixel as a 3D point with coordinated (R, G, B). Then you can segment the pixels into k most occurring colours.
  3. If you resize the image to a 1x1 pixel image, you'll find the average of all pixel values. If there is a dominant colour, where the majority of the pixels are in close proximity, it will give a good approximation.

There however, are all approximations. Your best choice would be to use k-means and to find the cluster that either has the most elements, or is the most dense.

In case you are looking for way to locate an object with a specific colour, you can use a maximum likelihood estimation. Something like this, which was used to classify different objects, such as grass, cars, building and pavement from satellite images. You can use it with a single colour and get a heat-map of where the object is in terms of likelihood (the percentage of probability) of that pixel belonging to your object.

like image 155
23pointsNorth Avatar answered Oct 06 '22 19:10

23pointsNorth


In an ordinary image, there's always a number of colors involved. To best average the pixels carrying almost the same colors is done by color quantization which is reducing number of colors in an image using techniques like K-mean clustering. This is best explained here with Python code:

https://www.pyimagesearch.com/2014/07/07/color-quantization-opencv-using-k-means-clustering/

After successful quantization, you can just try the following code to rank the colors based on their frequencies in the image.

top_n_colors = []
n = 3
colors_count = {}
(channel_b, channel_g, channel_r) = cv2.split(_processed_image)

# Flattens the 2D single channel array so as to make it easier to iterate over it
channel_b = channel_b.flatten()
channel_g = channel_g.flatten()
channel_r = channel_r.flatten()

for i in range(len(channel_b)):
    RGB = str(channel_r[i]) + " " + str(channel_g[i]) + " " + str(channel_b[i])
    if RGB in colors_count:
        colors_count[RGB] += 1
    else:
        colors_count[RGB] = 1

# taking the top n colors from the dictionary objects
_top_colors = sorted(colors_count.items(), key=lambda x: x[1], reverse=True)[0:n]
for _color in _top_colors:
    _rgb = tuple([int(value) for value in _color[0].split()])
    top_n_colors.append(_rgb)

print(top_n_colors)
like image 29
Nouman Ahsan Avatar answered Oct 06 '22 19:10

Nouman Ahsan