• 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 }
  • 相关阅读:
    数据库的未来:ORM+LINQ+RX
    工具论-科学是实用工具
    事务、锁与原子性
    ORM-面向对象&关系数据库
    swift Class的内存布局
    使用phpexcel导出到xls文件的时候出现乱码解决
    苹果CMS
    js网页如何获取手机屏幕宽度
    常用正则说明
    php中的线程、进程和并发区别
  • 原文地址:https://www.cnblogs.com/Long-w/p/9667324.html
Copyright © 2020-2023  润新知