0

I have images with only 4 colors. The colors are described in a numpy array.

self.colors = np.array([[255,255,255], [0,0,255], [255, 0, 0], [0,255,0]])

I want to count the occurence of the color in every image. For example, in one image, i have 5550 pixels with color [255,255,255], 3521 with colors [0,0,255] and so on.

I've tried different thing by looking at stackoverflow or opencv forum, but nothing seems to work.

I somehow managed to do something, but it's slow.

def countColors(self, image): 
    start_time = time.time()

    colors_Count = {}
    for color in self.colors:
        colors_Count[str(color)] = 0   
    for y in range(0, image.shape[1]):
        for x in range(0, image.shape[0]):
            try:
                colors_Count[str(image[x][y])] = colors_Count[str(image[x][y])] + 1
            except:
                print('Error at pixel :', x, y)  
                return
    print(time.time() - start_time, "seconds")
    return colors_Count

It returns me a dict, which is perfect.

{'[255 255 255]': 35741,
'[  0   0 255]': 5020,
'[255   0   0]': 3869,
'[  0 255   0]': 5616}

The problem is.. it takes like 3-4 seconds per image on a big CPU. It's such a waste of time.

What could I use to improve this ?

3
  • 1
    you can try to use inRange for each of your color and then count them using countNonZero function. It could be faster Commented Mar 8, 2022 at 17:56
  • Simple and easy ! It works, I'm about to benchmark your solution to tell you the improvement. Commented Mar 8, 2022 at 18:14
  • I'm not joking, I was at 4 seconds, I'm now at 0.0010013580322265625 seconds ahah ! this is awesome. Many thanks ! Commented Mar 8, 2022 at 18:17

2 Answers 2

1

With the help of crackanddie, I was able to improve my solution.

If anybody is looking to count pixel like me very fast, here is my new code :

    def countColors(self, image): 
    start_time = time.time()
    colors_Count = {}

    for i in range(len(self.colors)):
        tmp = cv.inRange(image, self.colors[i], self.colors[i])
        count = cv.countNonZero(tmp)
        colors_Count[str(self.colors[i])] = count
        
    print(time.time() - start_time, "seconds")
    return colors_Count

Thank you again crackanddie, I was so stuck ahah

Sign up to request clarification or add additional context in comments.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0

PIL package has a function that counts all colors really fast. if you care only to count specific colors, just filter the response. As for run time, on small images both function (PIL and yours) are almost the same but on big images (I checked 1000,1000,3) PIL is a bit faster. The big advantage of using PIL is that there's no need to specify colors.

def count_colors_2(cv_img: np.array) -> list:  # no need to give colors
    from PIL import Image
    start_time = time.time()
    pil_image = Image.fromarray(cv_img)
    colors_count_list = pil_image.getcolors()
    print('count_colors_2 time elapsed: {:.10f}s'.format(time.time() - start_time))
    for count, c_bgr in colors_count_list:
        print('\tcolor {} appeared {} times'.format(c_bgr, count))
    return colors_count_list

time and output check (yours is count_colors_1 and PIL is 2)

image dims (1000, 1000, 3)
count_colors_1 time elapsed: 0.0039894581s
    color [0 0 0] appeared 500000 times
    color [255 255 255] appeared 250000 times
    color [  0   0 255] appeared 250000 times
count_colors_2 time elapsed: 0.0029892921s
    color (255, 255, 255) appeared 250000 times
    color (0, 0, 0) appeared 500000 times
    color (0, 0, 255) appeared 250000 times

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.