opencv之模板匹配及应用 归一化 寻找最值
1)模板匹配
模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术,模板匹配不是基于直方图的,而是通过在输入图像中滑动图像块(模板)同时比对相似度,来对模板和输入图像进行匹配的一种方法
应用:
1.目标查找定位
2.运动物体跟踪
3其他。。。
因为是模板匹配所以倒置倾斜 相似度会差好多
不适应角度和寻找
不适应尺度变换
matchTemplate(InputArray image,InputArray temp1,OutputArray result,int method);
&&image :待搜索图像(大图)
&&templ:搜索模板,需要和原图一样的数据类型且尺寸不能大于源图像
&&result:比较结果的映射图像,且必须为单通道,32位浮点型图像,如果原图(待搜索图像)尺寸为W*H,而templ尺寸为w*h,则result尺寸一定是(W-w+1)*(H-h+1) 有效搜索区域
&&method:指定的匹配方法,有如下6种
CV_TM_SQDIFF–平方差匹配法(最好匹配0)
利用平方差来进行匹配,最好匹配为0,匹配越差,匹配值越大
CV_TM_SQIFF_NORMED–归一化平方差匹配法(最好匹配0)
CV_TM_CCORR—–相关匹配法(最坏匹配0)
利用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的匹配结果
CV_TM——CCORR_NORMED—归一化相关匹配法(最坏匹配0)
CV_TM_CCOFF——系数匹配法(最好匹配1)
这类方法是将模板对齐均值的相关性与图像对齐均值的相关性进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)
CV_TM_CCOEFF_NORMED–化相关系数匹配法(最好匹配1)
ex1:
resultImg.create(resultImg_cols,resultImg_rows,CV_32FC1);
matchTemplate(srcImg,templateImg,resultimg,CV_TM_SQDIFF);
通常,随着从简单的测量(平方差)到更复杂的测量(相关系数)我们可以获得越来越准确的匹配(同时也意味着越来越大的计算代价)最好的方法就是对所有这些设置多做一些测试实验,同时兼顾速度和精度
矩阵归一化—mormalize()
void normalize(InuputArray src,OutputArray dst,double alpha,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 ;可以选择的掩码操作
ex1:
normalize(srcImg,resultImg,0,1,NORM_MINMAX,-1);
作用就是进行矩阵归一化
————————————————————————————-寻找最值 minMaxLoc()
void minMaxLoc(InputArray src,CV_OUT double * minVal,CV_OUT double *maxVal=0,CV_OUT Point*imLoc=0,CV_OUT Point *maxLoc=0,InputArray mask=noArrat())
&&src:输入原图像,单通道图像
&&minVal:返回最小值的指针,如果无需要返回,则设置0
&&maxVal:返回最大值的指针,如果无需要返回,则设置0
&&minLoc:返回最小位置的指针,如果无需要返回,则设置0
&&maxLoc:返回最大位置的指针,如果无需要返回,则设置0
&&mask:可以选择的掩码操作
ex1:
Mat resultImg;
double minValue,maxValue;
Point minLoc,maxLoc;
Point matchLoc;
minMaxLoc(resultImg,&minValue,&maxValue,&minLoc,&maxLoc);
函数作用就是在数组中找到全局最小值和最大值
#include "opencv2/opencv.hpp"
using namespace cv;
void mian()
{
//单模板匹配
Mat temp=imread("temp.png");//模板图像
Mat src=imread("src.png");//待搜索图像
Mat dst=src.clone();//原图的备份
int width=src.cols-temp.cols+1;//result 宽度
int height=src.rows-temp.rows+1;//result 高度
Mat result(height,width,CV_32FC1);//创建结果映射图像
matchTemplate(sarc,temp,resultCV_TM_CCOEDD_NORMED);//化相关系数匹配最佳值1
imshow("result",result);//预览映射图像
normalize(result,result,0,1,NORM_MINMAX,-1);//归一化0到1
double minValue,maxValue;
Point minLoc,maxLoc;
minMaxLoc(result,&minValue,&maxValue,&minLoc,&maxLoc,Mat());
rectangle(dst,maxLoc,Point(maxLoc.x+temp.cols,maxLoc.y+temp.rows),Scalar(0,255,0),2,8);
inshow("dst",dst);
waitKey(0);
}
//运动物体识别
Mat frame;
Mat templateImg=imread("blue,jpg");
Mat resulting;
VideoCapture cap("1.mp4");
if(!cap.isOpened())
return;
int resultImg_cols;
int resultImg_rows;
while(1)
{
//利用截图工具来截模板
cap>>frame;
if(frame.empty())
break;
Mat showImg.clone();
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);
normalize(resultImg,resultImg,0,1,NORM_MINMAX,-1);
double minValue,maxValue;
Point minLoc,maxLoc;
Point matchLoc;
minMaxLoc(resultImg,&minValue,&maxValue,&minLOc,&macLoc);
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(20))
break;
}
//多模板匹配
double matchValue;
int count0=0;
int tempW=0;tempH=0;
char matchRate[10];
for(int i=0;i<resultImg_rows;i++)
{
for(int j=0;j<resultImg_cols;j++)
{
matchValue=resultImg.at<float>(i,j);
sprintf(matchRate,"%0.2f",matchValue);
if(matchValue>=0.95&&(abs(j-tempW)>1)&&(abs(i-tempH)>1))
{
count0++;
putText(showImg,matchRate,Point(j-5,j-5),CV_FONT_HERSHEY_COMPLEX,1Scalar(0,0,255),1);
rectangle(showing,Point(j,i),Point(j+templateImg.cols,i+templateImg.rows),Scalar(0,255,0),2);
tempW=j;
tempH=i;
}
}
}
//多目标模板匹配
double minValue,maxValue;
Point minLoc,maxLoc;
Point matchLoc;
char matchRate[10];
minMaxLoc(resultImg,&minValue,&maxValue,&minLoc,&macLoc);
count<<"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);
rectanle(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-20;
int startY=maxLoc.y-20;
int endX=maxLoc.x+20;
int endY=maxLoc.y+20;
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);
temp.copyTo(resultImg(Rect(startx,starty,temp.cols,temp.rows));
minMaxLox(resultImg,&minValue,&maxValue,&minLoc,&maxLoc);
if(maxValue<0.5)
break;
snprintf(matchRate,"%0.2f",maxValue);
putText(showImg,matchRate,Point(maxLoc.x-5,maxLoc.y-5),CV_FONT_HERSHEY_COMPLEX,1,Scalar(0,255,0),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);
}
原文地址
http://www.bieryun.com/2893.html