计算图像中的彩色圆点

时间:2017-06-08 15:13:15

标签: python opencv image-processing computer-vision

首先,抱歉,如果这个话题已经存在(我认为这是一项常见任务,但无法找到任何内容)。

关键是,我有一个图像显示不同颜色的不同点。我需要一个脚本来计算有多少红色,绿色和黄色点。 颜色为纯红色(ff0000),绿色(00ff00)和黄色(ffff00)。这使得这更容易,形状也很明确。

enter image description here

我目前的做法是选择圆形(点)形状,选择它们,然后一旦我将所有点都远离背景图像,读取它的颜色来计算它们......

重点是我很失落。我知道这可以通过OpenCV完成,但不知道如何(并且无法找到任何好的教程)。

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

由于您已经知道要查找的颜色,我会根据颜色对图像进行分割。我将遵循的步骤是:

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图像。

此外,这假设红色,绿色和黄色点中的颜色不会出现在图像中的任何其他位置。

答案 1 :(得分:2)

由于您似乎没有获得OpenCV / Python解决方案的大量帮助,我想我会以不同的方式发布 - 使用bash ImageMagick 。我将首先显示bash脚本,然后稍后解释一下。

ImageMagick 安装在大多数Linux发行版上,可免费用于macOS和Windows。它还具有C / C ++,Perl,Python,PHP,Ruby,Java绑定。请注意,不需要为此编写代码,也不需要编译器。

#!/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

希望你能看到它在红色的20%范围内填充所有像素的白色,然后用纯黑色填充所有不是白色的像素。

enter image description here

convert命令的其余部分通过" Connected Components Analysis" 将图像放在上面,并列出面积超过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)

希望您可以看到第一行是描述列的标题,并且有10行是白色srgb(255,255,255),每行对应一个blob - 即您的一个红色磁盘(我们制作白色)。它们都是大约39x39像素(即方形框中的圆形),面积大约为1150像素 - 如果你想象的是半径为19像素,那么Pi * r ^ 2 = 1150。它们的尺寸(如宽度和高度)和位置(如左上角的x和y)位于第二列。

如果你想计算小到全尺寸blob的25%的部分斑点,你可以将阈值改为1150的25%(自然的,完整的斑点大小)或287,而不是我估计的800。

脚本的其余部分只计算其中包含白色斑点的线条(grep -c),并为您寻找的其他颜色重复该过程。请注意,您的&#34;绿色&#34; 对应于 ImageMagick 使用的X11命名方案中的&#34; lime&#34;

为了好玩,让我们用上面输出列表中用箭头标记的blob填充半透明的蓝色:

convert dots.jpg -fill "rgba(0,0,255,0.5)" -draw "rectangle 848,595 887,634" temp.png

enter image description here

我希望这有助于完成工作并显示一种方法,即使它不是您期望使用的工具。请注意,OpenCV具有Connected Components和类似的算法 - 我只是不会说Python,而C ++版本对您没有任何帮助!

答案 2 :(得分:1)

以下是基于OpenCV 3.2Python 2.7的示例解决方案。

要计算彩色点数,请在每种颜色类型下重复4次以下步骤。

  1. 应用中值滤波器以减少噪音 - cv2.medianBlur()
  2. 应用颜色阈值以分割彩色圆点 - 使用cv2.inRange()
  3. 使用Hough Circle Transform检测圈子 - 使用circles = cv2.HoughCircles(mask,cv2.HOUGH_GRADIENT,...)
  4. 遍历每个检测到的圆圈以绘制其中心及其周围的圆圈,并计算彩色圆点的数量。
  5. 检测到的点的样本图像:

    红色 - 10个点 enter image description here

    绿色 - 39点 enter image description here

    黄色 - 30点 enter image description here

    请注意,未检测到右侧最后一个小于半圈的黄点。这可能是霍夫圆变换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 = np.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)
    

    希望得到这个帮助。

相关问题