检测红色和绿色圆圈

Stu*_*Guy 2 python opencv image-processing

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

图片

我正在使用opencv和python.

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

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

Nej*_*ejc 7

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

TL; DR这样做:

  1. 创建典型的圆形图像 - 模板图像.
  2. 使用模板匹配来获取所有圆圈位置.
  3. 检查每个圆圈的颜色.

现在,让我们开始吧!

第1步 - 模板图像

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

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

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

在此输入图像描述

第2步 - 模板匹配

加载图像和模板图像并将其转换为HSV颜色空间.然后拆分通道,以便您只能使用饱和通道:

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);
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述 在此输入图像描述

接下来,您必须获取包含有关圆边框信息的图像.无论您如何实现这一目标,都必须在图像和模板饱和度通道上应用完全相同的操作.我用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);
Run Code Online (Sandbox Code Playgroud)

这就是获得的图像和模板上的圆圈的样子: 在此输入图像描述 在此输入图像描述

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

Mat match_result;
matchTemplate(image_input, template_input, match_result, CV_TM_CCOEFF_NORMED);
Run Code Online (Sandbox Code Playgroud)

这是模板匹配结果:

在此输入图像描述

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

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

Mat thresholded;
threshold(match_result, thresholded, 0.8, 1.0, CV_THRESH_BINARY);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

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

在此输入图像描述

第3步:圆圈的颜色

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

在此输入图像描述

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

Point circ_center_on_image = template_position + circ_center_on_template;
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述