Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

count colored dots in image

First of all, sorry if this topic already exists (I think this is a common task, but couldn't find anything).

The point, is that I have an image who shows different dots of different colors. And I need an script to count how many red, green and yellow dots are. The colors are pure red(ff0000), green(00ff00) and yellow(ffff00). Which makes this easier, and the shape is well defined.

enter image description here

My current approach is to select the round(dot) shape, select them and then once I have all dots away from background image, read its color to count them...

The point is that I'm so lost with this. I know that this can be done with OpenCV but don't know how (and couldn't find any nice tutorial).

Any idea?

like image 842
Akiru Avatar asked Jun 08 '17 15:06

Akiru


1 Answers

Here is a sample solution based on OpenCV 3.2 and Python 2.7.

To count the colored dots, repeat below 4 steps once per color type.

  1. Apply median filter to reduce noise - cv2.medianBlur().
  2. Apply color threshold to segment the colored dots - use cv2.inRange().
  3. Use Hough Circle Transform to detect the circles - use circles = cv2.HoughCircles(mask,cv2.HOUGH_GRADIENT,...)
  4. Loop through each detected circles to draw its center and a circle around it, and count the numbers of colored dots.

Sample images of dots detected:

Red - 10 dots enter image description here

Green - 39 dots enter image description here

Yellow - 30 dots enter image description here

Take note that the last yellow dots at the right side with less than half a circle hasn't been detected. This is likely a limitation of the Hough Circle Transform cv2.HoughCircles(). So you need to decide how to handle this type of issue if it happens.

Here is the sample code:

import cv2
import numpy

red = [(0,0,240),(10,10,255)] # lower and upper 
green = [(0,240,0),(10,255,10)]
yellow = [(0,240,250),(10,255,255)]
dot_colors = [red, green, yellow]
    
img = cv2.imread('./imagesStackoverflow/count_colored_dots.jpg')   
# apply medianBlur to smooth image before threshholding
blur= cv2.medianBlur(img, 7) # smooth image by 7x7 pixels, may need to adjust a bit

for lower, upper in dot_colors:
    output = img.copy()
    # apply threshhold color to white (255,255, 255) and the rest to black(0,0,0)
    mask = cv2.inRange(blur,lower,upper) 

    circles = cv2.HoughCircles(mask,cv2.HOUGH_GRADIENT,1,20,param1=20,param2=8,
                               minRadius=0,maxRadius=60)    
    index = 0
    if circles is not None:
        # convert the (x, y) coordinates and radius of the circles to integers
        circles = numpy.round(circles[0, :]).astype("int")

        # loop over the (x, y) coordinates and radius of the circles
        for (x, y, r) in circles:
            # draw the circle in the output image, 
            #   then draw a rectangle corresponding to the center of the circle
            cv2.circle(output, (x, y), r, (255, 0, 255), 2)
            cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (255, 0, 255), -1)

            index = index + 1
            #print str(index) + " : " + str(r) + ", (x,y) = " + str(x) + ', ' + str(y)
        print 'No. of circles detected = {}'.format(index)

Hope this help.

like image 113
thewaywewere Avatar answered Sep 21 '22 06:09

thewaywewere