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

opencv学习——轮廓分析寻找近似圆_第1张图片

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

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

核心函数:

//对轮廓进行分析
float calculateCircularity(vector 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>contours;
	vectorhierarchy;
	findContours(binary,contours,hierarchy, RETR_LIST,CHAIN_APPROX_SIMPLE);
	drawContours(src, contours, -1, Scalar(255, 0, 0));

opencv学习——轮廓分析寻找近似圆_第2张图片

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

opencv学习——轮廓分析寻找近似圆_第3张图片

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

opencv学习——轮廓分析寻找近似圆_第4张图片

成功找到两个红灯

下面贴上整个工程代码

#include
#include

using namespace std;
using namespace cv;

//对轮廓进行分析
float calculateCircularity(vector 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;
	vectormatSplit;
	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>contours;
	vectorhierarchy;
	findContours(binary,contours,hierarchy, RETR_LIST,CHAIN_APPROX_SIMPLE);
	vector>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;
}

 

你可能感兴趣的:(opencv,C++,图像处理,新手)