繁体   English   中英

计算图像中的彩色点

[英]count colored dots in image

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

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

在此处输入图片说明

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

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

有什么想法吗?

这是一个基于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)

希望这有帮助。

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

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

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

由于您似乎没有得到 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 平均大小的一半,这就是我在评论部分询问部分 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 ),并为您寻找的其他颜色重复该过程。 请注意,您的“绿色”对应于ImageMagick使用的 X11 命名方案中的“石灰”

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

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

在此处输入图片说明

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM