opencv(19)---模板匹配及应用
来源:互联网 发布:楠木鞋架淘宝 编辑:程序博客网 时间:2024/05/17 03:07
基本概念
模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术。模板匹配不是基于直方图的, 而是通过在输入图像上滑动图像块(模板)同时比对相似度, 来对模板和输入图像进行匹配的一种方法。
缺点
(1)不适应角度变换和旋转
(2)不适应尺度变换
应用
①目标查找定位
②运动物体跟踪
③其他…
模板匹配—matchTemplate()
函数原型
void matchTemplate( InputArray image, InputArray templ, OutputArray result, int method, InputArray mask = noArray() );
- image: 待搜索图像(大图)
- templ: 搜索模板, 需和原图一样的数据类型且尺寸不能大于源图像
- result: 比较结果的映射图像, 其必须为单通道, 32位浮点型图像, 如果原图(待搜索图像)尺寸为W x H, 而templ尺寸为 w x h, 则result尺寸一定是(W-w+1)x(H-h+1)
- method: 指定的匹配方法, 有如下6种:
CV_TM_SQDIFF——平方差匹配法(最好匹配0)
CV_TM_SQDIFF_NORMED——归一化平方差匹配法(最好匹配0)
CV_TM_CCORR——相关匹配法(最坏匹配0)
CV_TM_CCORR_NORMED——归一化相关匹配法(最坏匹配0)
CV_TM_CCOEFF——系数匹配法(最好匹配1)
CV_TM_CCOEFF_NORMED——化相关系数匹配法(最好匹配1)
通常,随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价). 最好的办法是对所有这些设置多做一些测试实验,以便为自己的应用选择同时兼顾速度和精度的最佳方案.
矩阵归一化—normalize()
函数原型
void normalize( InputArray src, InputOutputArray dst, double alpha = 1, double beta = 0, int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray());
- src: 输入原图像, Mat类型
- dst: 输出结果图像, 需要和原图一样的尺寸和类型
- alpha: 归一化后的最小值, 默认值1
- beta:归一化后的最大值, 默认值0
- norm_type: 归一化类型, 可选NORM_INF, NORM_L1, NORM_L2(默认)等
- dtype: 默认值-1, 此参数为负值时, 输出矩阵和src有同样类型
- mask: 可选的掩码操作
寻找最值—minMaxLoc()
函数原型
void minMaxLoc(InputArray src, CV_OUT double* minVal, CV_OUT double* maxVal = 0, CV_OUT Point* minLoc = 0, CV_OUT Point* maxLoc = 0, InputArray mask = noArray());
作用是:在数组中找到全局最大值和最小值
- src: 输入原图像, 单通道图像
- minVal: 返回最小值的指针, 若无需返回, 则设置0
- maxVal: 返回最大值的指针, 若无需返回, 则设置0
- minLoc: 返回最小位置的指针,若无需返回, 则设置0
- maxLoc:返回最大位置的指针,若无需返回, 则设置0
- mask: 可选的掩码操作
单模版匹配
步骤
1.创建结果映射图片
需要计算出结果映射图片的行和列数
(1)结果映射图片的宽
int width=src.cols-temp.cols+1;//result宽度
(2)结果映射图片的高
int height=src.rows-temp.rows+1;//result高度
(3)创建结果映射图片
Mat result(height,width,CV_32FC1);
Mat的构造函数
Mat(int rows, int cols, int type);
2.化相关系数匹配
matchTemplate(src,temp,result,CV_TM_CCOEFF_NORMED);//化相关系数匹配最佳值
3.归一化系数
normalize(result,result,0,1,NORM_MINMAX,-1);//归一化0到1
4.获得矩阵中的最大最小值
minMaxLoc(result,&minValue,&maxValue,&minLoc,&maxLoc);//获得矩阵中的最大值和最小值及其位置
代码
Mat temp=imread("D:\\1\\temp.png");Mat src=imread("D:\\1\\src.png");Mat dst=src.clone();//对原图的备份imshow("temp",temp);imshow("src",src);int width=src.cols-temp.cols+1;//result宽度int height=src.rows-temp.rows+1;//result高度Mat result(height,width,CV_32FC1);//创建结果映射图像matchTemplate(src,temp,result,CV_TM_CCOEFF_NORMED);//化相关系数匹配最佳值imshow("result",result);normalize(result,result,0,1,NORM_MINMAX,-1);//归一化0到1double minValue,maxValue;Point minLoc,maxLoc;minMaxLoc(result,&minValue,&maxValue,&minLoc,&maxLoc);//获得矩阵中的最大值和最小值及其位置cout<<"minValue:"<<minValue<<endl;cout<<"maxValue:"<<maxValue<<endl;rectangle(dst,maxLoc,Point(maxLoc.x+temp.cols,maxLoc.y+temp.rows),Scalar(0,255,0),2,8);imshow("dst",dst);waitKey(0);
视频模版匹配
代码
Mat frame;Mat templateImg = imread("D:\\1\\green.jpg");Mat resultImg;VideoCapture cap("D:\\1\\1.mp4");if(!cap.isOpened())return;int resultImg_cols;int resultImg_rows;while(1){cap>>frame;//判断视频有没有读完if(frame.empty()) break;Mat showImg = frame.clone();//设置result图像resultImg_cols = frame.cols - templateImg.cols + 1;resultImg_rows = frame.rows - templateImg.rows + 1;resultImg.create(resultImg_cols, resultImg_rows, CV_32FC1);//模版匹配matchTemplate(frame, templateImg, resultImg, CV_TM_CCOEFF_NORMED); //化相关系数匹配法(最好匹配1)//归一化normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1);double minValue, maxValue;Point minLoc, maxLoc;Point matchLoc;//寻找最大最小minMaxLoc(resultImg, &minValue, &maxValue, &minLoc, &maxLoc);//cout<<"max_value= "<<maxValue<<endl;//cout<<"min_value= "<<minValue<<endl;//设定匹配程度if(maxValue>=0.7) rectangle(showImg, maxLoc, Point(maxLoc.x + templateImg.cols, maxLoc.y + templateImg.rows), Scalar(0, 255, 0), 2);imshow("frame", frame);imshow("result", showImg);if(27 == waitKey(10)) break;}destroyAllWindows();
运行结果
多模版匹配–方式1
代码
Mat srcImg = imread("D:\\1\\src.png");Mat templateImg = imread("D:\\1\\temp.png");Mat resultImg;Mat showImg = srcImg.clone();int resultImg_cols = srcImg.cols - templateImg.cols + 1;int resultImg_rows = srcImg.rows - templateImg.rows + 1;resultImg.create(resultImg_cols, resultImg_rows, CV_32FC1);matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCOEFF_NORMED); //化相关系数匹配法(最好匹配1)normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1);Mat midImg = resultImg.clone();//多目标模板匹配---方法一double matchValue;int count0=0;int tempW=0, tempH=0;char matchRate[10];//将resultImage中的像素进行逐个判断for(int i=0; i<resultImg_rows; i++){ for(int j=0; j<resultImg_cols; j++) { //获取匹配系数 matchValue = resultImg.at<float>(i, j); //往matchRate中输入此像素的matchValue sprintf(matchRate, "%0.2f", matchValue); //设置满足条件 if(matchValue>=0.85 && (abs(j - tempW)>5) && (abs(i - tempH)>5) ) { count0++; putText(showImg, matchRate, Point(j-5, i-5), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 1); rectangle(showImg, Point(j, i), Point(j + templateImg.cols, i + templateImg.rows), Scalar(0, 255, 0), 2); tempW = j; tempH = i; } }}cout<<"count="<<count0<<endl;imshow("resultImg", resultImg);imshow("dst", showImg);
运行结果
知识点讲解
1.
if(matchValue>=0.85 && (abs(j - tempW)>5) && (abs(i - tempH)>5) )
用于限制条件。如果对后面的abs不加限制,出来的效果如下
多模板匹配–方式2
代码
Mat srcImg = imread("D:\\1\\src.png"); Mat templateImg = imread("D:\\1\\temp.png"); Mat resultImg; Mat showImg = srcImg.clone(); int resultImg_cols = srcImg.cols - templateImg.cols + 1; int resultImg_rows = srcImg.rows - templateImg.rows + 1; resultImg.create(resultImg_cols, resultImg_rows, CV_32FC1); matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCOEFF_NORMED); //化相关系数匹配法(最好匹配1) normalize(resultImg, resultImg, 0, 1, NORM_MINMAX, -1); Mat midImg = resultImg.clone(); //多目标模板匹配---方法二 double minValue, maxValue; Point minLoc, maxLoc; Point matchLoc; char matchRate[10]; minMaxLoc(resultImg, &minValue, &maxValue, &minLoc, &maxLoc); cout<<"max_value= "<<maxValue<<endl; sprintf(matchRate, "%0.2f", maxValue); putText(showImg, matchRate, Point(maxLoc.x - 5, maxLoc.y - 5), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 1); rectangle(showImg, maxLoc, Point(maxLoc.x + templateImg.cols, maxLoc.y + templateImg.rows), Scalar(0, 255, 0), 2); for(int i=0; i<100; i++) { int startX = maxLoc.x - 4; int startY = maxLoc.y - 4; int endX = maxLoc.x + 4; int endY = maxLoc.y + 4; if(startX<0 || startY<0) { startX = 0; startY = 0; } if(endX > resultImg.cols - 1 || endY > resultImg.rows - 1) { endX = resultImg.cols - 1; endY = resultImg.rows- 1; } Mat temp = Mat::zeros(endX - startX, endY - startY, CV_32FC1); //Mat ROI = resultImg(Rect(Point(startX, startY), temp.cols, temp.rows)); temp.copyTo(resultImg(Rect(startX, startY, temp.cols, temp.rows))); minMaxLoc(resultImg, &minValue, &maxValue, &minLoc, &maxLoc); if(maxValue<0.8) break; cout<<"max_value= "<<maxValue<<endl; sprintf(matchRate, "%0.2f", maxValue); putText(showImg, matchRate, Point(maxLoc.x - 5, maxLoc.y - 5), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 1); rectangle(showImg, maxLoc, Point(maxLoc.x + templateImg.cols, maxLoc.y + templateImg.rows), Scalar(0, 255, 0), 2); } imshow("midImg", midImg); imshow("resultImg", resultImg); imshow("dst", showImg); waitKey(0);
运行结果
阅读全文
0 0
- opencv(19)---模板匹配及应用
- opencv之模板匹配及应用 归一化 寻找最值
- OpenCV中的模板匹配方法及其应用
- OpenCV中的模板匹配方法及其应用
- OpenCV中的模板匹配方法及其应用
- OpenCV中的模板匹配方法及其应用
- OpenCV中的模板匹配方法及其应用
- opencv-模板匹配
- OpenCV模板匹配
- opencv的模板匹配
- OpenCV编程->模板匹配
- opencv模板匹配
- opencv 模板匹配(cvMatchTemplate)
- Opencv模板匹配运用
- 【OpenCV】模板匹配
- openCV实现模板匹配
- opencv-模板匹配
- OpenCV 模板匹配
- ThreadLocal和InheritableThreadLocal的区别
- c语言中结构体对齐详解
- 史上最最简单的登录注册方法(Bomb后端云)
- 线程的让步(礼让)
- redis源码阅读笔记(一):sds
- opencv(19)---模板匹配及应用
- JVM 垃圾回收
- skewness以及数据去偏度
- c++第六次实验-项目一
- android studio混淆
- 我走过最长的路是你的套路——Android端微信支付填坑之路
- POJ1251 Jungle Roads
- spark中saveAsTextFile如何最终生成一个文件
- 【水】1021: Tom数-----ZZUOJ