opencv的模板匹配(matchTemplate)做定位(加注释)
模板匹配实现定位的步骤:
St1 将模板图和搜索图从BGR转化为GRAY;
St2 对模板图和搜索图进⾏均衡化处理
St3 模板图和搜索图进⾏滤波
St4 模板图和搜索图分别求其梯度
St5 模板匹配,求其求其最佳和最差匹配位置,归⼀化处理
代码如下:
#include <opencv2/core/core.hpp>
#include "opencv2/opencv.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv2/imgproc/imgproc.hpp>
#include <vector>
using namespace std;
using namespace cv;
const char* sourceImage = "sourceImage";
Point pre_pt, cur_pt;
Mat ReserchImg,tmpImg;
Rect SquareRect,drawRect;
/*函数声明区*/
void drawing_image();
void Clean();
void Image_fileter(Mat resImg, Mat &output_img);
void matcher(Mat researchImg, Mat tmpImg, Mat DrawImg);
int Img_remap(Mat input, Mat &outout);
void on_mouse(int event, int x, int y, int flags, void *param)
{
Mat drawImage,remapImage;
if (event == CV_EVENT_LBUTTONDOWN)
{
pre_pt = cur_pt = Point(-1, -1);
pre_pt = cur_pt = Point(x, y);
//if (cur_pt == Point(-1, -1))
cout << "⿏标按下,当前坐标为:" << cur_pt << endl;
}
else if (event == CV_EVENT_MOUSEMOVE&&(flags == CV_EVENT_FLAG_LBUTTON))
{
cur_pt = Point(x, y);
}
else if (event == CV_EVENT_LBUTTONUP)
{
SquareRect = Rect(-1, -1, 1, 1);
cur_pt = Point(x, y);
int tmp_height = cur_pt.y - pre_pt.y;
int tmp_width = cur_pt.x - pre_pt.x;
SquareRect.x = pre_pt.x;
SquareRect.y = pre_pt.y;
SquareRect.width = tmp_width;
SquareRect.height = tmp_height;
cout << "⿏标按下之前坐标为:" << cur_pt << endl;
if (SquareRect.area() >125 || (SquareRect.width >15 && SquareRect.height > 15))
{
tmpImg = ReserchImg(SquareRect).clone();
if (pty())
{
return;
}
// Img_remap(tmpImg,remapImage);
matcher(ReserchImg, tmpImg, drawImage);
matcher(ReserchImg, tmpImg, drawImage);
}
}
}
int main(int argc, char *argv[])
{
ReserchImg = imread("C://花分割.jpg");
char tim = '0';
if (!ReserchImg.data)
{
cout << "loading image failed" << endl;
return 0;
}
/*⿏标事件*/
cv::namedWindow("sourceImage", CV_WINDOW_AUTOSIZE);
cvSetMouseCallback(sourceImage, on_mouse, NULL);
{
drawing_image();
//imshow(sourceImage, ReserchImg);
waitKey(0);
}
return 0;
}
char coord[20] = {'0'};
void drawing_image()
{
if (SquareRect.area() >125 || (SquareRect.width >15 && SquareRect.height > 15))
{
sprintf_s(coord, "(%d ,%d)", SquareRect.x, SquareRect.y);
putText(ReserchImg, coord, cur_pt, cv::FONT_HERSHEY_COMPLEX, 1, Scalar(0, 255, 0));
rectangle(ReserchImg, SquareRect, Scalar(0, 255, 255));
}
imshow(sourceImage, ReserchImg);
}
void Clean()
{
SquareRect.x = -1;
SquareRect.y = -1;
SquareRect.width = 0;
SquareRect.height = 0;
}
void Image_fileter(Mat resImg, Mat &output_img)
{
Mat _resImg;
if (resImg.channels() != 1) cvtColor(resImg, _resImg, CV_BGR2GRAY); //转为gray图
/*均衡化处理*/
equalizeHist(_resImg, output_img);//均衡化就是把直⽅图每个灰度级进⾏归⼀化处理,根据相应的灰度值修正原图的每个像素。
/*⾼斯滤波*/ //⾼斯滤波就是每⼀个像素点的值都有其本⾝和领域内的其他像素值经过加权平均后得到的
Mat Kernel = getStructuringElement(cv::MORPH_RECT, Size(5, 5), Point(-1, -1)); //getStructuringElement()可以⽣成形态学操作中⽤到的核矩形 5*5 个1 GaussianBlur(output_img, output_img, Size(5, 5),0); //⾼斯处理
/*求梯度*/
morphologyEx(output_img, output_img, cv::MORPH_GRADIENT, Kernel); // 形态学梯度保留物体的边缘轮廓膨胀与腐蚀之差
}
void matcher(Mat researchImg, Mat tmpImg,Mat DrawImg)
{
Mat Resch_img, tmp_img; //定义收索图模版图
double min = 0.0, max = 0.0;
Point minLoc = Point(-1, -1), maxLoc = Point(-1, -1); // 初试位置
rectangle函数opencvint tmp_w = ls - ls+1; //图像⼤⼩参考opencv3编程⼊门 367页
int tmp_h = ws - ws + 1;
Mat mat_mval = Mat(Size(tmp_w, tmp_h), CV_32FC1); //定义这么⼤空间的图像
//调⽤函数⼀系列操作转gray 均衡化然后⾼斯滤波然后形态学操作边缘轮廓
Image_fileter(researchImg, Resch_img);
Image_fileter(researchImg, Resch_img);
Image_fileter(tmpImg, tmp_img);
//matchTemplate()函数⽤于匹配出和模版重叠的图像区域
matchTemplate(Resch_img, tmp_img, mat_mval, TM_CCOEFF_NORMED); //第三个参数就是⽐较结果的映射图像⼤⼩也有了 ///normalize(mat_mval, mat_mval, 0, 1); //可以进⾏⼀步标准化
char mat_ch[50] = {0};
minMaxLoc(mat_mval, &min, &max, &minLoc,&maxLoc,Mat()); //通过minmaxloc函数定位最匹配的位置
drawRect = Rect(maxLoc, ls, ws)); //画矩形框
sprintf_s(mat_ch, "good match(%.1f)", max);
putText(DrawImg, mat_ch, drawRect.br(), cv::FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));
rectangle(DrawImg, drawRect, Scalar(255, 0, 0));
imshow("match", DrawImg);
}
/*图⽚的放射变化*/
int Img_remap(Mat input ,Mat &outout)
{
Mat image, imgx, imgy, remapdst;
char mode = '0';
image = input.clone();
if (pty())
{
cout << "Picture load error" << endl;
return -1;
}
for (int row = 0; row < ws; ++row)
{
for (int col = 0; col < ls; ++col)
{
imgx.at<float>(row, col) = saturate_cast<float>(ws - row);
imgy.at<float>(row, col) = saturate_cast<float>(ls - col);
}
}
remap(image, remapdst, imgx, imgy, INTER_LINEAR);
imshow("remap", remapdst);
}
注释没有全部都看完!
测试了⼀下 在原图上⽤⿏标随机圈⼀个矩形 match图上会显⽰匹配你画的位置,有时候准确度低,代表匹配的不好 0.9和1是⽐较完美的!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论