OpenCV根据轮廓查找精准定位圆形

经过多次试验,发现利用OpenCV的霍夫圆变换查找出来的圆,其圆心位置并不准确,而且参数调节较为麻烦。于是想到利用轮廓查找的方式来进行圆检测,我们可以通过判断轮廓的外接矩形的横纵比来判断该轮廓是否为圆形。一般而言,圆的外接矩形肯定近似于一个正方形,因此宽高比接近1.0 。总体思路如下:阈值分割->形态学/滤波降噪->轮廓查找->范围过滤->圆形拟合。代码如下,仅供参考。

	int MinR = 100; int MaxR = 300;
		Mat src_img, binary_img, dst_img;
		src_img = imread("test.bmp", IMREAD_GRAYSCALE);//灰度图读入
		threshold(src_img, binary_img, 158, 255, THRESH_BINARY );
		imshow("trs", binary_img);
		//imwrite("trs.bmp", binary_img);
//可以根据实际需求选择使用的滤波进行降噪
		//GaussianBlur(binary_img, binary_img, Size(3, 3), 0, 0);
		//boxFilter(binary_img, binary_img,-1, Size(3, 3));
		//blur(binary_img, binary_img, Size(3, 3));
		vector<vector<Point>> contours;	
		vector<Vec4i> hireachy;
		// 形态学操作	
		Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
		// 构建形态学操作的结构元	
		morphologyEx(binary_img, binary_img, MORPH_CLOSE, kernel, Point(-1, -1));
		//闭操作	
		kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
		// 构建形态学操作的结构元
		morphologyEx(binary_img, binary_img, MORPH_OPEN, kernel, Point(-1, -1));
		//开操作	
		//imshow("开操作", dst_img);
		findContours(binary_img, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
		imshow("bf", binary_img);
		//imwrite("bf.bmp", binary_img);
		Mat result_img = src_img.clone();
		cvtColor(result_img, result_img, COLOR_GRAY2BGR);
		//灰度图转为彩色图    
		for (int i = 0; i < hireachy.size(); i++)
		{
	//		drawContours(src_img, contours, i, Scalar(0, 0, 255), -1, 8, Mat(), 0, Point());
			if (contours[i].size() < 5)continue;
			double area = contourArea(contours[i]);
			if (area < 2000)continue;
				//晒选出轮廓面积大于2000的轮廓	
			double arc_length = arcLength(contours[i], true);
			double radius = arc_length / (2 * PI);
	
			if (!(MinR < radius && radius < MaxR))
			{
				continue;
			}
		
			RotatedRect rect = fitEllipse(contours[i]);
			float ratio = float(rect.size.width) / float(rect.size.height);
		
			if (ratio < 1.1 && ratio > 0.9)
				//因为圆的外接直立矩形肯定近似于一个正方形,因此宽高比接近1.0	
			{
                                printf("X: %f\n", rect.center.x);
				printf("Y: %f\n", rect.center.y);
				printf("圆的面积: %f\n", area);
				printf("圆的半径: %f\n", radius);
				ellipse(result_img, rect, Scalar(0,255, 255),2);
				circle(result_img, rect.center, 2, Scalar(0,255,0), 2, 8, 0);
			}
			}
		imshow("dst", result_img);
		imwrite("dst.bmp", result_img);
		waitKey();

       测试图如下:

       算法检测出的圆形较为准确,且参数易调。主要根据调节阈值筛选轮廓,也可以采用自适应阈值。根据用户的需求进行半径与圆面积的筛选,最后得到想要的圆。如有不足,还请指正。转载请标明出处。希望能对各位有所帮助。

 

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值