OpenCV根据模板、圆和轮廓查找标识物

#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;



void templateMatching(const Mat& srcImage, const Mat& templateImage,Mat& mask)
{
	Mat result;
	int result_cols = srcImage.cols - templateImage.cols + 1;
	int result_rows = srcImage.rows - templateImage.rows + 1;
	if (result_cols < 0 || result_rows < 0)
	{
		std::cout << "Please input correct image!";
		return;
	}
	result.create(result_cols, result_rows, CV_32FC1);
	//    enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
	matchTemplate(srcImage, templateImage, result, TM_CCOEFF_NORMED);   //最好匹配为1,值越小匹配越差
	double minVal = -1;
	double maxVal;
	Point minLoc;
	Point maxLoc;
	Point matchLoc;
	minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());

	//取大值(视匹配方法而定)
   //    matchLoc = minLoc;
	matchLoc = maxLoc;

	//取大值,值越小表示越匹配
	char buff[128];
	sprintf(buff, "Similarity:%.2f%,x:%d,y:%d\n", minVal * 100, minLoc.x, minLoc.y);
	std::cout << buff;
	sprintf(buff, "Similarity:%.2f%,x:%d,y:%d\n", maxVal*100, maxLoc.x, maxLoc.y);
	//QString str = "Similarity:" + QString::number((maxVal) * 100, 'f', 2) + "%";
	std::cout<< buff;

	mask = srcImage.clone();
	//绘制最匹配的区域
	rectangle(mask, matchLoc, Point(matchLoc.x + templateImage.cols, matchLoc.y + templateImage.rows), Scalar(0, 255, 0), 2, 8, 0);
	//imshow("mask", mask);
}

int main()
{
	cv::Mat image_source = cv::imread("4.jpg");
	cv::Mat img_shape = image_source.clone();

	cv::Mat img_template = image_source(Rect(85,85,380,125));

	//将模板简单模糊处理
	cv::Mat img_template_median;
	blur(img_template, img_template_median, Size(5, 5));

	//调用模板匹配,查看相似度
	cv::Mat img_mask;
	templateMatching(image_source, img_template_median, img_mask);

	cv::Mat img_result = cv::Mat(img_shape.rows, img_shape.cols, CV_8UC3,cv::Scalar(255, 255, 255));

	circle(img_shape, cv::Point(60, 125), 30, cv::Scalar(0, 0, 255));
	circle(img_shape, cv::Point(485, 170), 30, cv::Scalar(0, 0, 255));

	circle(img_shape, cv::Point(150, 110), 15, cv::Scalar(0, 0, 255));
	//高斯滤波,目前测试均值滤波适合查找圆
	//cv::Mat img_gaussian;
	//GaussianBlur(img_shape, img_gaussian, Size(3, 3), 0, 0);
	cv::Mat img_median;                                                  
	//中值滤波
	//medianBlur(img, img_median, 3);
	//均值滤波
	blur(img_shape, img_median, Size(3, 3));
	cv::Mat img_gray;
	cvtColor(img_median, img_gray, CV_RGB2GRAY);

	//轮廓查找处理
	cv::Mat img_canny, img_contour;
	std::vector<std::vector<Point>> contour_vec;
	std::vector<Vec4i> hierarchy_vec;
	Canny(img_gray, img_canny, 20, 100, 3);

	img_contour = Mat::zeros(img_canny.rows, img_canny.cols, CV_8UC3);
	findContours(img_canny, contour_vec, hierarchy_vec, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
	for (int i = 0; i < hierarchy_vec.size(); i++)
	{
		Scalar color = Scalar(255, 0, 0);
		drawContours(img_contour, contour_vec, i, color, 2, 8, hierarchy_vec, 0, Point(0, 0));
	}

	//根据特征圆定位标识物
	std::vector<cv::Vec3f> circles;
	for (int i=100;i>0;i--)
	{
		//这里根据i的值来确定圆的位置,i值越小,查找到的圆越多;
		HoughCircles(img_gray, circles, cv::HOUGH_GRADIENT, 1, 10, 110, i, 0, 0);
		//总共绘制了三个圆,全部找到后退出循环
		if (3==circles.size())
		{
			printf("i:%d\n", i);
			printf("circles 1---x:%.2f,y:%.2f-r:%.2f\n", circles[0][0], circles[0][1], circles[0][2]);
			printf("circles 2---x:%.2f,y:%.2f-r:%.2f\n", circles[1][0], circles[1][1], circles[1][2]);
			printf("circles 3---x:%.2f,y:%.2f-r:%.2f\n", circles[2][0], circles[2][1], circles[2][2]);
			break;
		}
	}
	int circle_index = -1;
	std::vector<int> rule_index_vec;
	for (int i = 0; i < circles.size(); i++) {
		if (circles[i][2]<20)//根据圆半径判断标志物的位置和需要移动的圆位置
		{
			circle_index = i;
		}
		else
		{
			rule_index_vec.push_back(i);
		}
		circle(img_result, Point(circles[i][0], circles[i][1]), circles[i][2], Scalar(0, 0, 255), 1);
	}
	if (2 == rule_index_vec.size())
	{
		int circle_x = (circles[rule_index_vec.at(0)][0] + circles[rule_index_vec.at(1)][0]) / 2;
		int circle_y = (circles[rule_index_vec.at(0)][1] + circles[rule_index_vec.at(1)][1]) / 2;
		circle(img_result, Point(circle_x, circle_y), circles[circle_index][2], Scalar(255, 0, 0), 1);
		circle(img_shape, Point(circle_x, circle_y), circles[circle_index][2], Scalar(255, 0, 0), 1);
		line(img_result, Point(circles[rule_index_vec.at(0)][0], circles[rule_index_vec.at(0)][1]), 
			Point(circles[rule_index_vec.at(1)][0], circles[rule_index_vec.at(1)][1]), cv::Scalar(0, 255, 0));//绘制尺子线
	}
	//cv::Mat img_gray_dst;
	//threshold(img_gray, img_gray_dst, 0, 220, THRESH_TOZERO);
	//std::vector<cv::Point>	pts_vec;
	/*cvNamedWindow("image");
	cvNamedWindow("img_gaussian");
	cvNamedWindow("img_median");
	cvNamedWindow("image_gray");
	cvNamedWindow("image_result");

	cvNamedWindow("img_canny");
	cvNamedWindow("img_contour");
	cvNamedWindow("img_gray_dst");*/

	cv::imshow("image_source", image_source);
	cv::imshow("img_shape", img_shape);
	cv::imshow("img_median", img_median);
	cv::imshow("image_gray", img_gray);
	cv::imshow("image_result", img_result);
	cv::imshow("img_canny", img_canny);
	cv::imshow("img_contour", img_contour);

	cv::imshow("img_template", img_template_median);
	cv::imshow("img_mask", img_mask);

	int inter_dis = 50;
	moveWindow("image_source", inter_dis, inter_dis);
	moveWindow("img_shape", inter_dis+ image_source.cols+ inter_dis, inter_dis);
	moveWindow("img_median", inter_dis + image_source.cols + inter_dis + img_shape.cols + inter_dis, inter_dis);

	moveWindow("image_gray", inter_dis, inter_dis + image_source.rows+ inter_dis);
	moveWindow("image_result", inter_dis + img_gray.cols + inter_dis, inter_dis + image_source.rows+ inter_dis);
	moveWindow("img_template", inter_dis + img_gray.cols + inter_dis + img_result.cols + inter_dis, inter_dis + image_source.rows + inter_dis);

	moveWindow("img_canny", inter_dis, inter_dis + image_source.rows + inter_dis + img_gray.rows+inter_dis);
	moveWindow("img_contour", inter_dis + img_gray.cols + inter_dis, inter_dis + image_source.rows + inter_dis + img_gray.rows + inter_dis);
	moveWindow("img_mask", inter_dis + img_canny.cols + inter_dis + img_contour.cols + inter_dis, inter_dis + image_source.rows + inter_dis + img_gray.rows + inter_dis);

	cv::waitKey();
}

运行后的结果如下图:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值