OpenCV 3.2
和Python 2.7
的示例解决方案。cv2.medianBlur()
。cv2.inRange()
。circles = cv2.HoughCircles(mask,cv2.HOUGH_GRADIENT,...)
请注意,最右侧带有不到半个圆的黄点未被检测到。这可能是Hough圆变换cv2.HoughCircles()
的限制。因此,如果发生此类问题,您需要决定如何处理它。
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)
#!/bin/bash
for colour in red yellow lime ; do
echo -n "Colour: $colour "
convert dots.jpg -fuzz 20% \
-fill white -opaque $colour -fill black +opaque white \
-define connected-components:verbose=true \
-define connected-components:area-threshold=800 \
-connected-components 8 output.png | grep -c "rgb(255,255,255)"
done
输出结果如下:
Colour: red 10
Colour: yellow 30
Colour: lime 37
convert
命令是 ImageMagick 套件的一部分。让我们来看看当 colour
是 red
时,第一次循环中该命令如何工作。最初,我们只看 convert
命令的前两行:
convert dots.jpg -fuzz 20% \
-fill white -opaque red -fill black +opaque white intermediate.png
convert
命令的其余部分对上面的图像执行“连接组件分析”,并列出所有面积超过800像素的 blob - 这大约是您的 blob 平均大小的一半,这就是我在评论部分询问部分 blob 的原因。让我们看看运行时会发生什么:
convert intermediate.png \
-define connected-components:verbose=true \
-define connected-components:area-threshold=800 \
-connected-components 8 -auto-level output.png
输出
Objects (id: bounding-box centroid area mean-color):
0: 1342x858+0+0 670.0,426.9 1140186 srgb(0,0,0)
191: 39x39+848+595 866.9,614.1 1165 srgb(255,255,255) <--- DRAW THIS ONE
192: 39x39+482+664 500.9,682.9 1165 srgb(255,255,255)
117: 38x39+4+292 22.5,311.0 1155 srgb(255,255,255)
194: 39x38+1250+732 1268.9,750.5 1154 srgb(255,255,255)
178: 39x38+824+512 843.0,530.1 1154 srgb(255,255,255)
186: 39x38+647+549 666.0,567.5 1152 srgb(255,255,255)
197: 38x39+1270+796 1288.5,815.0 1150 srgb(255,255,255)
173: 38x38+811+444 829.5,462.5 1143 srgb(255,255,255)
195: 38x39+711+783 729.6,801.5 1138 srgb(255,255,255)
107: 27x39+0+223 11.5,242.0 874 srgb(255,255,255)
convert dots.jpg -fill "rgba(0,0,255,0.5)" -draw "rectangle 848,595 887,634" temp.png
我希望这有助于完成工作并展示一种方法,即使它不是你期望使用的工具。请注意,OpenCV
具有Connected Components
和类似的算法-我只是不会说Python,而C++版本对你也没有更多的帮助!既然您已经知道要寻找的颜色,我会根据颜色对图像进行分割。我会按照以下步骤进行:
red_dot_count = 0
yellow_dot_count = 0
green_dot_count = 0
For each pixel in the image:
if pixel color is red:
floodfill using this pixel as seed pixel and target_color as black
red_dot_count++
if pixel color is green:
floodfill using this pixel as seed pixel and target_color as black
green_dot_count++
if pixel is yellow:
floodfill using this pixel as seed pixel and target_color as black
yellow_dot_count++
正如 @Mark 指出的那样,您的图像必须是 PNG 格式。
此外,这也假设红色、绿色和黄色圆点中的颜色不会在图像的其他部分出现。
inRange
函数,并计算连通组件的数量。可能再进行一些研究也无妨。 - Mikibash
代码实现,其中两行是for ... done
循环,另一行是echo
输出标签。 - Mark Setchell