1.模板匹配基本原理概述

  当我们比较两幅图像的时候,首先面对的基本问题是:什么时候两幅图像才是一样或比较相似的,这两幅图像的相似程度如何衡量?当然,比较一般的方法是,当两幅图像的所有像素灰度值一样的时候,我们认为这样幅图是一样的。这种比较方法在某些特定的应用领域是可行的,比如在恒定光照环境和相机内部环境下,检测连续两帧图像的变化。简单的比较像素之间的差值在大多数应用场合下是不太合适的。噪声、量化误差、微小的光照变化、极小的平移或旋转在两幅图像像素简单差值的时候将产生较大的像素差值,但是人眼观察看来,两幅图像仍然是一样的。显然,人类知觉能够感应更为广泛的相似性内容,即使在单个像素差值较大的情况下,也能够利用诸如结构和图像内容来识别两幅图像的相似性。在结构或语义层面比较图像是一个比较困难的问题,同时也是一个比较有趣的研究领域。在这我们介绍的是一种在像素层面相对简单的图像比较方法。即在一幅较大图像定位一幅给定的子图像-----模板图像,即通常所说的模板匹配。这种情况经常发生,比如在一个图像场景中定位一个特定的物体,或者是在图像序列中追踪最某些特定模式。模板匹配的基本原理很简单:在待搜寻的图像中,移动模板图像,在每一个位置测量待搜寻图像的子图像和模板图像的差值,当相似度达到最大时,记录其相应的位置。但实际情况却不是这么简单,如何选取合适的距离测量方法?当亮度或对比度改变时应该如何处理?匹配中总的距离差值为多少才可以被认为是相似度比较高?这些问题都需要根据实用情况加以考虑。

java调用opencv比较两张图片人脸相似度 opencv对比两张图片是否一样_相似度

  以上图像都“相同”吗?在原始图像(a)和其他五幅图像(b-f)中,简单的比较图像像素间的差值将会得到较大的距离值。

java调用opencv比较两张图片人脸相似度 opencv对比两张图片是否一样_相似度_02

  模板匹配的基本原理。以两幅图像的原点为参考点,参考图像R在待搜寻的图像I中平移(r,s)个单位,待搜寻图像的大小和模板图像的大小确定的最大的搜寻区域。

  2. 各种求距离公式  

3.  应用

1 //  各种模板匹配 
 2   
 3 #include "stdafx.h"  
 4 #include <opencv2\core\core.hpp>
 5 #include <opencv2\imgproc\imgproc.hpp>
 6 #include <opencv2\highgui\highgui.hpp>
 7 #include <iostream>
 8 
 9 using namespace std;
10 using namespace cv;
11 
12 Mat g_srcImage, g_templateImage, g_resultImage;
13 int g_nMatchMethod;
14 int g_nMaxTrackbarNum = 5;
15 
16 
17 void on_matching(int, void* )
18 {
19     Mat srcImage;
20     g_srcImage.copyTo(srcImage);
21     int resultImage_cols = g_srcImage.cols - g_templateImage.cols + 1;
22     int resultImage_rows = g_srcImage.rows - g_templateImage.rows + 1;
23     g_resultImage.create(resultImage_cols, resultImage_rows, CV_32FC1);
24 
25     matchTemplate(g_srcImage, g_templateImage, g_resultImage, g_nMatchMethod);
26     normalize(g_resultImage, g_resultImage, 0, 2, NORM_MINMAX, -1, Mat());
27     double minValue, maxValue;
28     Point minLocation, maxLocation, matchLocation;
29     minMaxLoc(g_resultImage, &minValue, &maxValue, &minLocation, &maxLocation);
30 
31     if (g_nMatchMethod == TM_SQDIFF || g_nMatchMethod == CV_TM_SQDIFF_NORMED)
32     {
33         matchLocation = minLocation;
34     }
35     else
36     {
37         matchLocation = maxLocation;
38     }
39 
40     rectangle(srcImage, matchLocation, Point(matchLocation.x + g_templateImage.cols, matchLocation.y + g_templateImage.rows), Scalar(0, 0, 255), 2, 8, 0);
41     rectangle(g_resultImage, matchLocation, Point(matchLocation.x + g_templateImage.cols, matchLocation.y + g_templateImage.rows), Scalar(0, 0, 255), 2, 8, 0);
42 
43     imshow("原始图", srcImage);
44     imshow("模板图",g_templateImage);
45     imshow("效果图", g_resultImage);
46 
47 }
48 
49 
50 int main()
51 {
52     g_srcImage = imread("04.jpg");
53     if (!g_srcImage.data)
54     {
55         cout << "原始图读取失败" << endl;
56         return -1;
57     }
58     g_templateImage = imread("moban.jpg");
59     if (!g_templateImage.data)
60     {
61         cout << "模板图读取失败" << endl;
62         return -1;
63     }
64 
65     namedWindow("原始图", CV_WINDOW_AUTOSIZE);
66     namedWindow("效果图", CV_WINDOW_AUTOSIZE);
67     createTrackbar("方法", "原始图", &g_nMatchMethod, g_nMaxTrackbarNum, on_matching);
68 
69     on_matching(0, NULL);
70 
71     waitKey(0);
72     return 0;
73 
74 }