【问题标题】:count colored dots in image计算图像中的彩色点
【发布时间】:2017-11-10 09:28:58
【问题描述】:

首先,对不起,如果这个话题已经存在(我认为这是一个常见的任务,但找不到任何东西)。

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

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

关键是我很迷茫。我知道这可以用 OpenCV 完成,但不知道如何(也找不到任何好的教程)。

有什么想法吗?

【问题讨论】:

  • 使用 JPEG - 你不能让生活更轻松并使用 PNG 吗?
  • 然后对每种不同的颜色使用inRange(最终在HSV空间中)并计算连接组件的数量。可能再多做一点研究也不会受到伤害
  • 点不完整怎么办?他们算不算?
  • 你打算使用 Python 和 OpenCV 吗?可以用四行bash来完成,其中两行是for ... done循环,其中一行是echo来标注输出。
  • 欢迎来到 StackOverflow。请阅读并遵循帮助文档中的发布指南。 on topichow to ask 在这里申请。 StackOverflow 不是设计、编码、研究或教程服务。

标签: python opencv image-processing computer-vision


【解决方案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. 遍历每个检测到的圆圈以绘制其中心和围绕它的圆圈,并计算彩色点的数量。

检测到的点的示例图像:

红色 - 10 点

绿色 - 39 点

黄色 - 30 点

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

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    由于您似乎没有在 OpenCV/Python 解决方案方面获得太多帮助,我想我会以不同的方式发布 - 使用 bashImageMagick。我会先展示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 套件的一部分。让我们看看当colourred 时,该命令在第一次循环中是如何工作的。首先,让我们看看convert 命令的前两行:

    convert dots.jpg -fuzz 20%                          \
     -fill white -opaque red -fill black +opaque white intermediate.png
    

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

    convert 命令的其余部分通过 “连接组件分析” 将上面的图像放入并列出面积超过 800 像素的所有 blob - 这大约是 blob 平均大小的一半这就是为什么我在 cmets 部分询问有关部分 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% 的部分 blob,您可以将阈值更改为 1150(自然的完整 blob 大小)的 25% 或 287,而不是我估计的 800。

    脚本的其余部分只计算其中有白色斑点的行 (grep -c),并为您寻找的其他颜色重复该过程。请注意,您的 "green" 对应于 ImageMagick 使用的 X11 命名方案中的 "lime"

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

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

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

    【讨论】:

    • 非常详尽的解释,马克。您也可以通过简单地将除 3 种颜色以外的所有颜色都设为白色来避免循环,然后运行连接的组件,它会列出每种颜色的区域。但是,您必须对该列表进行后处理以计算每种颜色的数量。所以我认为你的方法可能更简单,更直接。
    【解决方案3】:

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

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

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

    【讨论】:

    • @Akiru 如果此处发布的任何答案有助于解决您的问题,请标记相应的答案已被接受。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 2020-08-21
    • 2020-03-07
    • 2017-11-04
    • 2015-10-22
    • 2022-12-06
    相关资源
    最近更新 更多