利用opencv进行圆形标志提取和质心计算

利用opencv进行圆形标志提取和质心计算

最近跟着老师做项目,需要对图片中拍摄的圆形标志点进行检测和提取,查了一些资料和博客,记录一下过程。实际拍摄的图片如图所示:
利用opencv进行圆形标志提取和质心计算_第1张图片
图片处理过程的大概思路是:
1、进行双边滤波处理(可以较好的保留圆形标志的边缘信息)

CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,
                                   double sigmaColor, double sigmaSpace,
                                   int borderType = BORDER_DEFAULT );

利用opencv进行圆形标志提取和质心计算_第2张图片
2、利用Mean shift区域分割算法分割圆形标志(分割次数可以根据图片具体情况而定)

CV_EXPORTS_W void pyrMeanShiftFiltering( InputArray src, OutputArray dst,
                                         double sp, double sr, int maxLevel = 1,
                                         TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) );

利用opencv进行圆形标志提取和质心计算_第3张图片
double sp—滑动空间的窗口半径
double sr—颜色窗口半径
termcrit:迭代算法终止条件(可以选择迭代次数或者迭代精度作为终止条件)
利用opencv进行圆形标志提取和质心计算_第4张图片
3、将分割出圆形标志进行Canny算子边缘检测
利用opencv进行圆形标志提取和质心计算_第5张图片
4、利用findContours函数获取轮廓信息并填充区域轮廓内部
findContours函数的定义:

CV_EXPORTS_W void findContours( InputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method, Point offset = Point());
Mat draw00 = Mat(resultCanny.size(), CV_8UC3, Scalar(255, 255, 255));
		findContours(resultCanny, Contours, Hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//轮廓检测
		for (int i = 0; i < Contours.size(); i++)
		{
			//Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
			drawContours(draw00, Contours, i, (0, 0, 0), -1, 8, Hierarchy, 0, Point());//填充内部区域
			//circle(drawing_0, mc[i], 4, color, -1, 8, 0);
		}

利用opencv进行圆形标志提取和质心计算_第6张图片
6、再次使用轮廓提取函数findContours获取轮廓信息并计算轮廓矩和提取轮廓质心

findContours(dst_2, Contours, Hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//轮廓检测
		vector<Moments> mu(Contours.size());
		vector<Point2f> mc(Contours.size());
		for (int i = 0; i < Contours.size(); i++) {
			mu[i] = moments(Contours[i], false);
		}
			for (int i = 0; i < Contours.size(); i++)
			{
				
				mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);//质心计算	
			}

利用opencv进行圆形标志提取和质心计算_第7张图片
实验的源代码:

Mat src1 = imread("E:/标志检测/image/2/DMcameraTest-Snapshot-20161101081515-560083999222.BMP");
	Mat dst = src1.clone();//原图像深拷贝到目标图像
	Mat src2 = src1.clone();
	Mat blur_deal;
	int ksizes = 5;
	//medianBlur(src1, blur_deal, ksizes);//中值滤波处理
	bilateralFilter(src1, blur_deal,10,50,50);//双边滤波
	Mat result1, result2;
	TermCriteria T10 = TermCriteria(TermCriteria::COUNT | TermCriteria::EPS, 10, 0.1);
	pyrMeanShiftFiltering(blur_deal, result1, 5, 25, 2, T10);
	pyrMeanShiftFiltering(result1, result2, 5, 25, 2, T10);
	//pyrMeanShiftFiltering(result2, result2, 5, 25, 2, T10);
	namedWindow("分割结果", WINDOW_AUTOSIZE);
	imshow("分割结果", result1);
	//对图像进行Canny边缘检测
	Mat imgCanny, resultCanny;
	Canny(src1, imgCanny, 50, 100);
	Canny(result2, resultCanny,50,100);
	vector<vector<Point>> Contours;
	vector<Vec4i> Hierarchy;
	vector<Vec3f> circles;
	Mat gray_src;
	cvtColor(result2, gray_src, COLOR_BGR2GRAY);//转为灰度图像
	Mat draw00 = Mat(resultCanny.size(), CV_8UC3, Scalar(255,255,255));
	findContours(resultCanny, Contours, Hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//轮廓检测
	for (int i = 0; i < Contours.size(); i++)
	{
		drawContours(draw00, Contours, i, (0,0,0), -1, 8, Hierarchy, 0, Point());
	}
	Mat test00;
	cvtColor(draw00, test00,COLOR_BGR2GRAY);
	threshold(test00, test00, 100, 255, THRESH_BINARY_INV);//二值化
	findContours(test00, Contours, Hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//轮廓检测
	vector<Moments> mu(Contours.size());
	vector<Point2f> mc(Contours.size());
	for (int i = 0; i < Contours.size(); i++) {
		mu[i] = moments(Contours[i], false);
	}
	for (int i = 0; i < Contours.size(); i++) {
		cout << "mu[].m10: " << mu[i].m10 << " mu[].m00: " << mu[i].m00 << " mu[].m01: " << mu[i].m01 << endl;
		cout << "轮廓大小:" << contourArea(Contours[i]) << endl;
		mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);//质心计算
		
	waitKey(0);
	return 0;
	}


你可能感兴趣的:(计算机视觉,opencv)