22、【opencv入门】模板匹配

一、模板匹配概念

  模板匹配是一项在一副图像中寻找与另一幅模板图像最匹配(相似)部分的技术。模板匹配不是基于直方图的,而是通过在输入图像上滑动图像块(模板)同时对比相似度,来对模板和输入图像进行匹配的一种方法。

应用:

  (1)目标查找定位

  (2)运动物体跟踪

1、模板匹配 --- matchTemplate()

1 CV_EXPORTS_W void matchTemplate(InputArray image, InputArray temp1, OutputArray result, int method);

  image:待搜索图像(大图)

  temp1:搜索模板,需和原图一样数据类型且尺寸大小不能大于源图像

  reuslt:比较结果的映射图像,其必须为单通道的,32位浮点型图像,如果原图(待搜索图像)尺寸为W*H,二temp1的尺寸为w*h,则result的尺寸一定是(W-w+1)*(H-h+1)

  method:指定的匹配方法,有如下六种:

1     CV_TM_SQDIFF --- 平方差匹配法(最好匹配0)
2     CV_TM_SQDIFF_NORMED --- 归一化平方差匹配法(最好匹配0)
3     CV_TM_CCORR --- 相关匹配法(最坏匹配0)
4     CV_TM_CCORR_NORMED ---归一化相关匹配法(最坏匹配0)
5     CV_TM_CCOEFF --- 系数匹配法(最好匹配1)
6     CV_TM_CCOEFF_NORMED --- 归一化系数匹配法(最好匹配1)

2、矩阵归一化 --- normalize()

1 C++: void normalize(InputArray src,OutputArray 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:可选的掩码操作

normallize()函数的作用是进行矩阵归一化。

3、寻找最值 --- minMaxLoc()

1 CV_EXPORTS_W 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:可选的掩码操作

minMaxLoc()函数的作用是在数组中找到全局最小值和最大值

二、单模板匹配

【示例】

 1 //模板匹配
 2 #include "opencv2/opencv.hpp"
 3 #include <iostream>
 4 
 5 using namespace std;
 6 using namespace cv;
 7 
 8 int main()
 9 {
10     Mat temp=imread("mu.jpg");
11     Mat src=imread("1.jpg");
12     Mat dst=src.clone();
13     imshow("temp",temp);
14 
15     int width=src.cols-temp.cols+1;//result宽度
16     int height=src.rows-temp.rows+1;//result高度
17 
18     Mat result(height,width,CV_32FC1);//创建结果映射图像
19     //matchTemplate(srcImg, templateImg, resultImg, CV_TM_SQDIFF); //平方差匹配法(最好匹配0)
20     //matchTemplate(srcImg, templateImg, resultImg, CV_TM_SQDIFF_NORMED); //归一化平方差匹配法(最好匹配0)
21     //matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCORR); //相关匹配法(最坏匹配0)
22     //matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCORR_NORMED); //归一化相关匹配法(最坏匹配0)
23     //matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCOEFF); //系数匹配法(最好匹配1)
24     matchTemplate(src,temp,result,CV_TM_CCOEFF_NORMED);//化相关系数匹配,最佳值1
25     imshow("result",result);
26     normalize(result,result,0,1,NORM_MINMAX,-1);//归一化到0-1范围
27 
28     double minValue,maxValue;
29     Point minLoc,maxLoc;
30     minMaxLoc(result,&minValue,&maxValue,&minLoc,&maxLoc);
31     cout<<"minValue="<<minValue<<endl;
32     cout<<"maxValue="<<maxValue<<endl;
33 
34     rectangle(dst,maxLoc,Point(maxLoc.x+temp.cols,maxLoc.y+temp.rows),Scalar(0,255,0),2,8);
35     imshow("dst",dst);
36 
37     waitKey(0);
38     return 0;
39 }

注意:result的长宽正好是(原图-模板图)的长宽,result图中白亮程度表示匹配程度

三、视频模板匹配

【示例】

 1 //视频模板匹配
 2 #include "opencv2/opencv.hpp"
 3 #include <iostream>
 4 
 5 using namespace std;
 6 using namespace cv;
 7 
 8 int main()
 9 {
10     Mat frame,resultImg;
11     Mat templateImg = imread("green.jpg");
12     VideoCapture cap("1.mp4");
13     if(!cap.isOpened())
14         return;
15     int resultImg_cols,resultImg_rows;
16 
17     while(1)
18     {
19         cap>>frame;
20         if(frame.empty())    break;
21         Mat showImg = frame.clone();
22         resultImg_cols = frame.cols -  templateImg.cols + 1;
23         resultImg_rows = frame.rows -  templateImg.rows + 1;
24         resultImg.create(resultImg_cols, resultImg_rows, CV_32FC1);
25         matchTemplate(frame, templateImg, resultImg, CV_TM_CCOEFF_NORMED); //归一化相关系数匹配法(最好匹配1)
26         normalize(resultImg, resultImg, 0, 1, NORM_MINMAX);
27 
28         double minValue, maxValue;
29         Point minLoc, maxLoc;
30         Point matchLoc;
31 
32         minMaxLoc(resultImg, &minValue, &maxValue, &minLoc, &maxLoc);
33         cout<<"max_value= "<<maxValue<<endl;
34         //cout<<"min_value= "<<minValue<<endl;
35         if(maxValue>=0.7)
36             rectangle(showImg, maxLoc, Point(maxLoc.x + templateImg.cols, maxLoc.y + templateImg.rows), Scalar(0, 255, 0), 2);
37         imshow("frame", frame);
38         imshow("result", showImg);
39         if(27 == waitKey(10))
40             break;
41     }
42     destroyAllWindows();
43 
44     waitKey(0);
45     return 0;
46 }

四、多模板匹配

【示例】

 1 //多模板匹配
 2 #include "opencv2/opencv.hpp"
 3 #include <iostream>
 4 #include <stdio.h>
 5 
 6 using namespace std;
 7 using namespace cv;
 8 
 9 int main()
10 {
11     Mat srcImg = imread("E://src.png");
12     Mat templateImg = imread("E://temp.png");
13     Mat resultImg;
14     Mat showImg = srcImg.clone();
15 
16     int resultImg_cols = srcImg.cols -  templateImg.cols + 1;
17     int resultImg_rows = srcImg.rows -  templateImg.rows + 1;
18 
19     resultImg.create(resultImg_cols, resultImg_rows, CV_32FC1);
20     matchTemplate(srcImg, templateImg, resultImg, CV_TM_CCOEFF_NORMED); //化相关系数匹配法(最好匹配1)
21     normalize(resultImg, resultImg, 0, 1, NORM_MINMAX);
22     Mat midImg = resultImg.clone();
23 
24     //多目标模板匹配---方法一
25     /*double matchValue;
26     int count0=0;
27     int tempW=0, tempH=0;
28     char matchRate[10];
29 
30     for(int i=0; i<resultImg_rows; i++)
31     {
32         for(int j=0; j<resultImg_cols; j++)
33         {
34             matchValue = resultImg.at<float>(i, j);
35             sprintf(matchRate, "%0.2f", matchValue);
36             if(matchValue>=0.85 && (abs(j - tempW)>5) && (abs(i - tempH)>5) )
37             {
38                 count0++;
39                 putText(showImg, matchRate, Point(j-5, i-5), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 1);
40                 rectangle(showImg, Point(j, i), Point(j + templateImg.cols, i + templateImg.rows), Scalar(0, 255, 0), 2);
41                 tempW = j;
42                 tempH = i;
43             }
44         }
45     }
46     cout<<"count="<<count0<<endl;
47     imshow("resultImg", resultImg);
48     imshow("dst", showImg);*/
49 
50     //多目标模板匹配---方法二
51     double minValue, maxValue;
52     Point minLoc, maxLoc;
53     Point matchLoc;
54     char matchRate[10];
55 
56     for(int i=0; i<100; i++)
57     {
58         int startX = maxLoc.x - 4;
59         int startY = maxLoc.y - 4;
60         int endX = maxLoc.x + 4;
61         int endY = maxLoc.y + 4;
62         if(startX<0 || startY<0)
63         {
64             startX = 0;
65             startY = 0;
66         }
67          if(endX > resultImg.cols - 1 || endY > resultImg.rows - 1)
68         {
69             endX = resultImg.cols - 1;
70             endY = resultImg.rows- 1;
71         }
72          Mat temp = Mat::zeros(endX - startX, endY - startY, CV_32FC1);
73          //Mat ROI = resultImg(Rect(Point(startX, startY), temp.cols, temp.rows));
74          temp.copyTo(resultImg(Rect(startX, startY, temp.cols, temp.rows)));
75          minMaxLoc(resultImg, &minValue, &maxValue, &minLoc, &maxLoc);
76          if(maxValue<0.8)    break;
77 
78          cout<<"max_value= "<<maxValue<<endl;
79          sprintf(matchRate, "%0.2f", maxValue);
80          putText(showImg, matchRate, Point(maxLoc.x - 5, maxLoc.y - 5), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 1);
81          rectangle(showImg, maxLoc, Point(maxLoc.x + templateImg.cols, maxLoc.y + templateImg.rows), Scalar(0, 255, 0), 2);
82 
83     }
84     imshow("midImg", midImg);
85     imshow("resultImg", resultImg);
86     imshow("dst", showImg);
87 
88     waitKey(0);
89     return 0;
90 }

猜你喜欢

转载自www.cnblogs.com/Long-w/p/9667324.html