模板匹配: 模板匹配实际上就是模板图在源图中的平移,所以只能匹配到一模一样(形态和方向都一致)的局部图像
demo1:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace cv;
int main()
{
//加载源图像和模板图像
cv::Mat image_source = cv::imread("1.bmp", cv::IMREAD_GRAYSCALE);
cv::Mat image_template = cv::imread("7.png", cv::IMREAD_GRAYSCALE);
//cv::Mat image_source = cv::imread("lena.jpg", cv::IMREAD_GRAYSCALE);
//cv::Mat image_template = cv::imread("template.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat image_matched;
//模板匹配方法
cv::matchTemplate(image_source, image_template, image_matched, cv::TM_CCOEFF_NORMED);//归一化的平方差
//cv::matchTemplate(image_source, image_template, image_matched, cv::TM_SQDIFF);//平方差
//cv::matchTemplate(image_source, image_template, image_matched, cv::TM_CCORR); //相关性匹配
//cv::matchTemplate(image_source, image_template, image_matched, cv::TM_CCORR_NORMED);//归一化的相关性匹配
//cv::matchTemplate(image_source, image_template, image_matched, cv::TM_CCOEFF);//相关性系数匹配
//cv::matchTemplate(image_source, image_template, image_matched, cv::TM_CCOEFF_NORMED);//归一化的相关性系数匹配
double minVal, maxVal;
cv::Point minLoc, maxLoc;
//寻找最佳匹配位置 //参数:单通道阵列、最小值的指针、最大值的指针、最小位置的指针、最大位置的指针
cv::minMaxLoc(image_matched, &minVal, &maxVal, &minLoc, &maxLoc);
cv::Mat image_color;
cv::cvtColor(image_source, image_color, CV_GRAY2BGR);
//circle()参数:图像(单通道或多通道)
cv::circle(image_color, //将匹配到的用圆圈绘制出
cv::Point(maxLoc.x + image_template.cols/2, maxLoc.y + image_template.rows/2), //圆心坐标
100, //圆半径
cv::Scalar(0, 0, 255), //圆的颜色
2, //线条粗细
8,
0);
namedWindow("source image",CV_WINDOW_NORMAL); //可调节窗口大小
namedWindow("match result",CV_WINDOW_NORMAL); //可调节窗口大小
namedWindow("target",CV_WINDOW_NORMAL); //可调节窗口大小
cv::imshow("source image", image_source);
cv::imshow("match result", image_matched);
cv::imshow("target", image_color);
cv::waitKey(0);
return 0;
}
demo2:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<string>
using namespace cv;
using namespace std;
int max_track = 5;
int match_method = CV_TM_SQDIFF;
String Source_path = "1.bmp";
String Temp_path = "3.png";
String src_window = "Source Window";
String temp_window = "Temp Window";
String Output_window = "Output Window";
Mat src, temp;
void Match_Demo(int, void*);
int main()
{
src = imread(Source_path, IMREAD_COLOR);
temp = imread(Temp_path, IMREAD_COLOR);
if (!src.data || !temp.data)
{
printf("Could not load the src image or temp image...");
return false;
}
//namedWindow(src_window, CV_WINDOW_AUTOSIZE);
//imshow(src_window, src);
namedWindow(temp_window, CV_WINDOW_NORMAL);
imshow(temp_window, temp);
const char* trackbar_title = "Match Algo Type";
namedWindow(Output_window, CV_WINDOW_NORMAL);
createTrackbar(trackbar_title, Output_window, &match_method, max_track, Match_Demo);//创建滑动条并进行初始化
Match_Demo(0, 0); //参数为0,表示进行一次初始化
waitKey(0);
return 0;
}
void Match_Demo(int, void*) //响应滑动条的回调函数
{
int height = src.rows - temp.rows + 1;
int width = src.cols - temp.cols + 1;
Mat result(width, height, CV_32FC1);
matchTemplate(src, temp, result, match_method, Mat());//匹配
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());//标准化
Point minLoc;
Point maxLoc;
double min, max;
Mat dst;
src.copyTo(dst);
Point tempLoc;
minMaxLoc(result, &min, &max, &minLoc, &maxLoc,Mat()); //通过函数minMaxLoc定位最匹配的位置
if (match_method== CV_TM_SQDIFF||match_method==CV_TM_SQDIFF_NORMED) //越小的数值有着更高的匹配结果
{
tempLoc = minLoc;
}
else //其余方法,数值越大匹配效果越好
{
tempLoc = maxLoc;
}
rectangle(dst, Rect(tempLoc.x, tempLoc.y, temp.cols, temp.rows),Scalar(0,0,255),2,8,0);//绘制出矩形,并显示最终结果
rectangle(result, Rect(tempLoc.x, tempLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8, 0);
namedWindow("Output window2", CV_WINDOW_NORMAL);
imshow("Output window2", dst);
namedWindow(Output_window, CV_WINDOW_NORMAL);
imshow(Output_window, result);
return;
}