opencv学习——轮廓分析寻找近似圆

19 篇文章 0 订阅
18 篇文章 1 订阅

这是一张经过处理后的红灯的图像,我们需要找到其中的红灯,可以看到是两个圆,用霍夫圆之后发现其中调参非常麻烦,于是写了一个根据轮廓来分析圆的算法。

算法思想:findContours()找到图像的轮廓,使用minEnclosingCircle()找到轮廓的最小包围矩形,计算轮廓上的每个点到圆心的距离和半径的差值,进行累加(简单来说就是求轮廓中每个点到圆心距离和半径的方差),当累加和小于某个值时,我们认为它是一个圆。

核心函数:

//对轮廓进行分析
float calculateCircularity(vector<Point> contours)
{
	Point2f center;
	float radius = 0;
	minEnclosingCircle((Mat)contours, center, radius);
	float fsum = 0;
	float fcompare = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		Point2f ptmp = contours[i];
		//计算距离
		float fdistance = sqrt(((float)ptmp.x - center.x)*((float)ptmp.x - center.x) + ((float)ptmp.y - center.y)*((float)ptmp.y - center.y));
               //累加距离到圆心的差值
		float fdiff = abs(fdistance - radius);
		fsum = fsum + fdiff;
	}
	fcompare = fsum / (float)contours.size();
	return fcompare;
}

 首先找到轮廓,并且对绘制出轮廓,蓝色为轮廓,其中包含了我们需要的红灯和不需要的数字

vector<vector<Point>>contours;
	vector<Vec4i>hierarchy;
	findContours(binary,contours,hierarchy, RETR_LIST,CHAIN_APPROX_SIMPLE);
	drawContours(src, contours, -1, Scalar(255, 0, 0));

 我们对提取的每个轮廓进行圆的特性分析,并且输出得到的差值累加和

可以看到有两个累加和比较小的,不确定是否是两个红灯,暂时设置阈值为0.6,将轮廓分析后累加和小于阈值的用绿色进行绘制

成功找到两个红灯

下面贴上整个工程代码

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

//对轮廓进行分析
float calculateCircularity(vector<Point> contours)
{
	Point2f center;
	float radius = 0;
	minEnclosingCircle((Mat)contours, center, radius);
	float fsum = 0;
	float fcompare = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		Point2f ptmp = contours[i];
		//计算距离
		float fdistance = sqrt(((float)ptmp.x - center.x)*((float)ptmp.x - center.x) + ((float)ptmp.y - center.y)*((float)ptmp.y - center.y));
        //累加距离到圆心的差值
		float fdiff = abs(fdistance - radius);
		fsum = fsum + fdiff;
	}
	fcompare = fsum / (float)contours.size();
	return fcompare;
}
int main()
{
	Mat src = imread("cc.png");//读入有圆的图片
	imwrite("src.jpg", src);
        //红绿灯在图像上方,可以选择只分析上半部分图像
	Mat src_copy = src(Rect(0, 0, src.cols, src.rows / 2));
	Mat gray;
	Mat binary;
	vector<Mat>matSplit;
	cvtColor(src_copy, gray, COLOR_BGR2GRAY);
	
	//二值化
	threshold(gray, binary, 100, 255, THRESH_OTSU);
	//闭操作
	Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
	morphologyEx(binary, binary, MORPH_CLOSE, kernel);
	//找轮廓
	vector<vector<Point>>contours;
	vector<Vec4i>hierarchy;
	findContours(binary,contours,hierarchy, RETR_LIST,CHAIN_APPROX_SIMPLE);
	vector<vector<Point>>DrawContour;
	for (int i = 0; i < contours.size(); i++)
	{
                //对每个轮廓进行分析
		float fCircle = calculateCircularity(contours[i]);
		cout << fCircle << endl;
		//符合圆的特性,则加入vector
		if(fCircle<0.6)
		DrawContour.push_back(contours[i]);
	}


	drawContours(src, DrawContour, -1, Scalar(0, 255, 0), 3);
	imwrite("circle.jpg", src);
	waitKey(0);
	return 0;
}

 

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值