检测红色和绿色圆圈

时间:2017-02-18 13:48:06

标签: python opencv image-processing

我想在下面的图像中分别检测红色和绿色圆圈(以及一些其他类似的图像)

image

我使用的是opencv和python。

我尝试过使用houghcircles,但即使更改了params之后也没有任何帮助。

任何建议如何做到这一点真的会有很大帮助。 如果有人发送代码,我将不胜感激

1 个答案:

答案 0 :(得分:7)

您在评论中提到圈子的大小始终相同。 让我们利用这个事实。我的代码片段是用C ++语言编写的,但这不应该是一个问题,因为它们只是为了显示要使用的OpenCV函数(以及如何)...

<强> TL; DR 执行此操作:

  1. 创建典型的圆形图像 - 模板图像。
  2. 使用template matching获取所有圈子位置。
  3. 检查每个圆圈的颜色。
  4. 现在,让我们开始吧!

    第1步 - 模板图片

    您需要一张图片,显示与背景明显分开的圆圈。你有两个选择(两者都同样好):

    • 自己制作这样的图像(如果你知道半径就计算它),或者
    • 只需从您正在处理的图像中拍摄一张图像,然后裁剪一个清晰可见的圆圈并将其保存为单独的图像(这是我所做的,因为它是一个更快的选项)

    圆圈可以是任何颜色 - 重要的是它与背景不同。

    enter image description here

    第2步 - 模板匹配

    加载图片和模板图片并将其转换为HSV color space。然后拆分通道,以便您只能使用饱和通道:

    using namespace std;
    using namespace cv;
    
    Mat im_rgb = imread("circles.jpg");
    Mat tm_rgb = imread("template.jpg");
    
    Mat im_hsv, tm_hsv;
    cvtColor(im_rgb, im_hsv, CV_RGB2HSV);
    cvtColor(tm_rgb, tm_hsv, CV_RGB2HSV);
    vector<Mat> im_channels, tm_channels;
    split(im_hsv, im_channels);
    split(tm_hsv, tm_channels);
    

    这就是圈子和模板现在的样子:

    enter image description here enter image description here

    接下来,您必须获取包含圈子边框信息的图片。无论您如何实现这一目标,都必须在图像和模板饱和度通道上应用完全相同的操作。 我用sobel算子来完成工作。代码示例仅显示我在图像饱和通道上执行的操作;模板饱和通道经历了完全相同的过程:

    Mat im_f;
    im_channels[1].convertTo(im_f, CV_32FC1);
    GaussianBlur(im_f, im_f, Size(3, 3), 1, 1);
    Mat sx, sy;
    Sobel(im_f, sx, -1, 1, 0);
    Sobel(im_f, sy, -1, 0, 1);
    
    Mat image_input = abs(sx) + abs(sy);
    

    获取的图像和模板上的圆圈如何显示: enter image description here enter image description here

    现在,执行模板匹配。我建议您选择模板匹配的类型来计算归一化的相关系数:

    Mat match_result;
    matchTemplate(image_input, template_input, match_result, CV_TM_CCOEFF_NORMED);
    

    这是模板匹配结果:

    enter image description here

    如果将模板放置在图像上的不同位置,此图像会告诉您模板与基础图像的关联程度。例如,像素(0,0)处的结果值对应于放置在输入图像上的(0,0)处的模板。

    当模板放置在与底层图像匹配良好的位置时,相关系数很高。使用阈值方法丢弃除信号峰值以外的所有内容(模板匹配的值将位于[-1,1]区间内,并且您只对接近1的值感兴趣):

    Mat thresholded;
    threshold(match_result, thresholded, 0.8, 1.0, CV_THRESH_BINARY);
    

    enter image description here

    接下来,确定每个隔离区域内模板结果最大值的位置。为此,我建议您使用阈值图像作为掩码。每个区域内只需要选择一个最大值。

    这些位置会告诉您必须放置模板的位置,以使其与圆圈最匹配。我绘制了从这些点开始并具有与模板图像相同的宽度/高度的矩形:

    enter image description here

    第3步:圆圈的颜色

    现在你知道模板应该放在哪里,以便它们很好地覆盖圆圈。但您仍需要找出圆心位于模板图像上的位置。您可以通过计算模板饱和度通道的质量中心来实现:

    enter image description here

    在图像上,圆心位于以下点:

    Point circ_center_on_image = template_position + circ_center_on_template;
    

    现在您只需要检查这些点的红色通道强度是否大于绿色通道强度。如果是,则圆圈为红色,否则为绿色:

    enter image description here