#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();
}
运行后的结果如下图: