Opencv 模板匹配 Template Matching
模板匹配不同于直方图中的反向投影,它将模板图片在感兴趣图片中滑动,并用相应匹配方法度量相似性。
void cv::matchTemplate(
cv::InputArray image, // Input image to be searched, 8U or 32F, size W-by-H
cv::InputArray templ, // Template to use, same type as 'image', size w-by-h
cv::OutputArray result, // Result image, type 32F, size (W-w+1)-by(H-h+1)
int method // Comparison method to use
);
匹配方法
- Square Difference Matching Method (cv::TM_SQDIFF),最佳匹配为 0,越不匹配越大
- Normalized Square Difference Matching Method (cv::TM_SQDIFF_NORMED),最佳匹配为 0,越不匹配越大
- Correlation Matching Methods (cv::TM_CCORR),最不匹配为 0,越大越匹配
- Normalized Cross-Correlation Matching Method (cv::TM_CCORR_NORMED),最不匹配为 0,越大越匹配
- Correlation Coefficient Matching Methods (cv::TM_CCOEFF),最匹配为 1,最不匹配为 -1,无关为 0
- Normalized Correlation Coefficient Matching Method (cv::TM_CCOEFF_NORMED),匹配为正数,不匹配为负数
其中直接平方差值的最快,取相关系数的最慢,不过速度快效果也差。应该通过比较选择一个最合适的。
enum TemplateMatchModes {
TM_SQDIFF = 0, //!< \f[R(x,y)= \sum _{x',y'} (T(x',y')-I(x+x',y+y'))^2\f]
TM_SQDIFF_NORMED = 1, //!< \f[R(x,y)= \frac{\sum_{x',y'} (T(x',y')-I(x+x',y+y'))^2}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f]
TM_CCORR = 2, //!< \f[R(x,y)= \sum _{x',y'} (T(x',y') \cdot I(x+x',y+y'))\f]
TM_CCORR_NORMED = 3, //!< \f[R(x,y)= \frac{\sum_{x',y'} (T(x',y') \cdot I(x+x',y+y'))}{\sqrt{\sum_{x',y'}T(x',y')^2 \cdot \sum_{x',y'} I(x+x',y+y')^2}}\f]
TM_CCOEFF = 4, //!< \f[R(x,y)= \sum _{x',y'} (T'(x',y') \cdot I'(x+x',y+y'))\f]
//!< where
//!< \f[\begin{array}{l} T'(x',y')=T(x',y') - 1/(w \cdot h) \cdot \sum _{x'',y''} T(x'',y'') \\ I'(x+x',y+y')=I(x+x',y+y') - 1/(w \cdot h) \cdot \sum _{x'',y''} I(x+x'',y+y'') \end{array}\f]
TM_CCOEFF_NORMED = 5 //!< \f[R(x,y)= \frac{ \sum_{x',y'} (T'(x',y') \cdot I'(x+x',y+y')) }{ \sqrt{\sum_{x',y'}T'(x',y')^2 \cdot \sum_{x',y'} I'(x+x',y+y')^2} }\f]
};
Opencv 范例程序
// Example 13-3. Template matching
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
void help( char** argv ){
cout << "\n"
<<"\nExample 13-3: using matchTemplate(). The call is:\n"
<<"\n"
<<argv[0] <<" <template> <image_to_be_searched?\n"
<< "\nExample:\n" << argv[0] << "../BlueCup.jpg ../adrian.jpg"
<<"\n"
<<" This routine will search using all methods:\n"
<<" cv::TM_SQDIFF 0\n"
<<" cv::TM_SQDIFF_NORMED 1\n"
<<" cv::TM_CCORR 2\n"
<<" cv::TM_CCORR_NORMED 3\n"
<<" cv::TM_CCOEFF 4\n"
<<" cv::TM_CCOEFF_NORMED 5\n"
<<"\n" << endl;
}
// Display the results of the matches
//
int main( int argc, char** argv ) {
if( argc != 3) {
help( argv );
return -1;
}
cv::Mat src, templ, ftmp[6]; // ftmp is what to display on
// Read in the template to be used for matching:
//
if((templ=cv::imread(argv[1], 1)).empty()) {
cout << "Error on reading template " << argv[1] << endl;
help( argv );return -1;
}
// Read in the source image to be searched:
//
if((src=cv::imread(argv[2], 1)).empty()) {
cout << "Error on reading src image " << argv[2] << endl;
help( argv );return -1;
}
// Do the matching of the template with the image
for(int i=0; i<6; ++i){
cv::matchTemplate( src, templ, ftmp[i], i);
cv::normalize(ftmp[i],ftmp[i],1,0,cv::NORM_MINMAX);
}
// Display
//
cv::imshow( "Template", templ );
cv::imshow( "Image", src );
cv::imshow("SQDIFF", ftmp[0] );
cv::imshow("SQDIFF_NORMED", ftmp[1] );
cv::imshow("CCORR", ftmp[2] );
cv::imshow("CCORR_NORMED", ftmp[3] );
cv::imshow("CCOEFF", ftmp[4] );
cv::imshow("CCOEFF_NORMED", ftmp[5] );
// Let user view results:
//
cv::waitKey(0);
}