利用特征点(Brief,ORB,SIFT)进行图像匹配,模板匹配

来源:互联网 发布:2017化妆品数据分析 编辑:程序博客网 时间:2024/06/10 03:53

http://blog.csdn.net/kingeasternsun/article/details/8279114

头文件

在VS2010+OpenCV2.3.1 
[cpp] view plaincopy
  1. #include "StdAfx.h"  
  2. #include "opencv2/core/core.hpp"  
  3. #include "opencv2/calib3d/calib3d.hpp"  
  4. #include "opencv2/features2d/features2d.hpp"  
  5. #include "opencv2/imgproc/imgproc.hpp"  
  6. #include "opencv2/highgui/highgui.hpp"  
  7. //#include <opencv2/legacy/legacy.hpp>  
  8. #include <vector>  
  9. #include <iostream>  
  10. #include <fstream>  
  11. #include <math.h>  
  12.   
  13. using namespace cv;  
  14. using namespace std;  
  15. void getMatchLR(string imgpath);  
  16. void getMatchDT(string imgpath);  
  17. //void getSURFFeature(string imgpath);  
  18. void getORBFeature(string imgpath);  
  19. void MatchTemplate(string imgname);  
  20. void MatchTemplateORB(string imgname);  
  21. void MatchTemplateSIFT(string imgname);  
  22. void testMatch();  
  23.   
  24. static string imgdir = "E:\\input_resize\\";  
  25. static string Matchsavedir = "E:\\macth_result\\";  
  26. static string TemplateDir = "E:\\template_resize\\";  
  27. //static string ORBsavedir = "ORB_result\\";  
  28. IplImage mat_src_lpl;  
  29. IplImage OutImage_lpl;  
  30. IplImage TemplateIpl;  
  31.   
  32. IplImage* dst_left;  
  33. IplImage* dst_right;  
  34. IplImage *src;  
  35. IplImage *TemplateIplPtr;  
  36.   
  37. Mat mat_src;  
  38. Mat OutImage;  
  39. Mat TemplateMat;  
在UBUNTU12.04UTL+opencv2.4.
[cpp] view plaincopy
  1. #include "opencv2/core/core.hpp"  
  2. #include "opencv2/calib3d/calib3d.hpp"  
  3. #include "opencv2/features2d/features2d.hpp"  
  4. #include "opencv2/imgproc/imgproc.hpp"  
  5. #include "opencv2/highgui/highgui.hpp"  
  6. #include <opencv2/legacy/legacy.hpp>  
  7. #include <vector>  
  8. #include <iostream>  
  9. #include <fstream>  
  10. #include <math.h>  

主函数

[cpp] view plaincopy
  1. int main()  
  2. {  
  3.   
  4.     string imgname = "07_in.jpg";  
  5.     //testMatch();  
  6.     MatchTemplateSIFT(imgname);  
  7.     //getMatchLR(imgname);  
  8.   
  9.     return 0;  
  10. }  


SIFT

利用SIFT特征进行模板匹配,template1为一个物体的小图,然后在一张含有多个同样物体的大图上进行匹配。

在大图上滑窗处理,得到每一个滑窗的特征,进行匹配,计算距离均值,作为一个灰度值,最后生成一个大图。

特征子,描述符,匹配方法分别为:

[cpp] view plaincopy
  1. new SiftFeatureDetector  
  2. new SiftDescriptorExtractor;  
  3. BruteForceMatcher<L2(float)>  

详细代码

[cpp] view plaincopy
  1. void MatchTemplateSIFT(string imgname)  
  2. {  
  3.     vector<KeyPoint> LeftKey;  
  4.     vector<KeyPoint> RightKey;  
  5.     Mat LeftDescriptor;  
  6.     Mat RightDescriptor;  
  7.     vector<DMatch> Matches;  
  8.     //vector<double> meanDisances;  
  9.     IplImage* dst;  
  10.   
  11.     ofstream fout("E:\\picin\\rBRIEF_Test\\templateCompareResult.txt");  
  12.     int xstep = 2;  
  13.     int ystep = 2;  
  14.     string TemplateName = "template1.jpg";  
  15.     string TemplateImgPath = TemplateDir + TemplateName;  
  16.   
  17.     string imgpath = imgdir + imgname;  
  18.     string resultPath = Matchsavedir+imgname;  
  19.   
  20.     TemplateMat = imread(TemplateImgPath,CV_LOAD_IMAGE_GRAYSCALE);  
  21.     if(!TemplateMat.data){  
  22.         cout<<"no template exist";  
  23.         return ;  
  24.     }  
  25.     int TemplateWidth = TemplateMat.cols;  
  26.     int TemplateHeight = TemplateMat.rows;  
  27.     std::cout<<"TemplateWidth "<<TemplateWidth<<endl;  
  28.     std::cout<<"TemplateHeight "<<TemplateHeight<<endl;  
  29.   
  30.     FeatureDetector *pDetector = new SiftFeatureDetector;   pDetector->detect(TemplateMat, LeftKey);  
  31.     DescriptorExtractor *pExtractor = new SiftDescriptorExtractor;   
  32.     pExtractor->compute(TemplateMat, LeftKey, LeftDescriptor);  
  33.   
  34.     DescriptorMatcher *pMatcher = new BruteForceMatcher<L2<float>>;  
  35.   
  36.       
  37.   
  38.     mat_src = imread(imgpath, CV_LOAD_IMAGE_GRAYSCALE );  
  39.     if(!mat_src.data) {  
  40.         cout<<"no src img";  
  41.         return ;  
  42.       } mat_src_lpl = IplImage(mat_src);  
  43.     src  = &mat_src_lpl;  
  44.     long ImgWidth = src->width;  
  45.     long ImgHeight = src->height;  
  46.     std::cout<<"ImgWidth "<<ImgWidth<<endl;  
  47.     std::cout<<"ImgHeight "<<ImgHeight<<endl;  
  48.   
  49.     int x;  
  50.     int y;  
  51.   
  52.   
  53.     //Mat R = Mat(ImgHeight - TemplateHeight, ImgWidth - TemplateWidth, CV_8UC1,255);  
  54.     //namedWindow("result", CV_WINDOW_NORMAL );  
  55.     //imshow("result",mat_src);  
  56.     //uchar *p;  
  57.     //while(start_x < ImgWidth - TemplateWidth){  
  58.     for(long start_y = 0;start_y <ImgHeight - TemplateHeight;start_y = start_y+ystep){  
  59.         for(long start_x = 0;start_x < ImgWidth - TemplateWidth;start_x = start_x+xstep){  
  60.           
  61.             x = start_x;  
  62.             y = start_y;  
  63.               
  64.   
  65.             cvSetImageROI(src,cvRect(x,y,TemplateWidth,TemplateHeight));  
  66.             dst = cvCreateImage(cvSize(TemplateWidth,TemplateHeight),  
  67.                     IPL_DEPTH_8U,  
  68.                     src->nChannels);  
  69.             cvCopy(src,dst,0);  
  70.             cvResetImageROI(src);  
  71.   
  72.             Mat DstImage = Mat(dst, false); // Do not copy  
  73.             pDetector->detect(DstImage, RightKey);  
  74.   
  75.             pExtractor->compute(DstImage, RightKey, RightDescriptor);  
  76.   
  77.             pMatcher->match(LeftDescriptor, RightDescriptor, Matches);  
  78.             //double sum = 0;  
  79.             double sum = 0;  
  80.             //int i = 0;  
  81.             for(vector<DMatch>::iterator dite = Matches.begin();dite <Matches.end(); dite++ )  
  82.               {  
  83.                   sum += dite->distance;  
  84.               }  
  85.             int matchSize = Matches.size()*10;  
  86.   
  87.             if(matchSize>1){  
  88.   
  89.                 fout<<exp(-sum/matchSize)<<" ";  
  90.   
  91.             }else{  
  92.                 fout<<exp(-100.0)<<" ";  
  93.   
  94.             }  
  95.   
  96.         }  
  97.     }  
  98.     //  
  99.     std::cout<<"finish";  
  100.     fout.close();  
  101.   
  102.     //destroyWindow("result" );  
  103.     //imwrite(resultPath,R);  
  104.   
  105.     delete pDetector;  
  106.     delete pExtractor;  
  107.     delete pMatcher;  
  108.   
  109. }  

SURF

SURF特征同SIFT特征。


ORB

描述子和描述符,匹配代码如下
[cpp] view plaincopy
  1. ORB orb;  
  2. orb(TemplateMat,Mat(),LeftKey,LeftDescriptor);  
  3. DescriptorMatcher *pMatcher = new BruteForceMatcher<HammingLUT>;  

详细代码如下

[cpp] view plaincopy
  1. void MatchTemplateORB(string imgname)  
  2. {  
  3.     vector<KeyPoint> LeftKey;  
  4.     vector<KeyPoint> RightKey;  
  5.     Mat LeftDescriptor;  
  6.     Mat RightDescriptor;  
  7.     vector<DMatch> Matches;  
  8.     //vector<double> meanDisances;  
  9.     IplImage* dst;  
  10.   
  11.     ofstream fout("E:\\picin\\rBRIEF_Test\\templateCompareResult.txt");  
  12.     int xstep = 2;  
  13.     int ystep = 2;  
  14.     string TemplateName = "template2.jpg";  
  15.     string TemplateImgPath = TemplateDir + TemplateName;  
  16.   
  17.     string imgpath = imgdir + imgname;  
  18.     string resultPath = Matchsavedir+imgname;  
  19.   
  20.         TemplateMat = imread(TemplateImgPath,CV_LOAD_IMAGE_GRAYSCALE);  
  21.     if(!TemplateMat.data){  
  22.         cout<<"no template exist";  
  23.         return ;  
  24.     }  
  25.     int TemplateWidth = TemplateMat.cols;  
  26.     int TemplateHeight = TemplateMat.rows;  
  27.     std::cout<<"TemplateWidth "<<TemplateWidth<<endl;  
  28.     std::cout<<"TemplateHeight "<<TemplateHeight<<endl;  
  29.     ORB orb;  
  30.     orb(TemplateMat,Mat(),LeftKey,LeftDescriptor);  
  31.   
  32.     DescriptorMatcher *pMatcher = new BruteForceMatcher<HammingLUT>;  
  33.   
  34.       
  35.   
  36.     mat_src = imread(imgpath, CV_LOAD_IMAGE_GRAYSCALE );  
  37.     if(!mat_src.data) {  
  38.         cout<<"no src img";  
  39.         return ;  
  40.       }  
  41.     mat_src_lpl = IplImage(mat_src);  
  42.     src  = &mat_src_lpl;  
  43.     long ImgWidth = src->width;  
  44.     long ImgHeight = src->height;  
  45.     std::cout<<"ImgWidth "<<ImgWidth<<endl;  
  46.     std::cout<<"ImgHeight "<<ImgHeight<<endl;  
  47.   
  48.   
  49.   
  50.     int x;  
  51.     int y;  
  52.   
  53.   
  54.     //Mat R = Mat(ImgHeight - TemplateHeight, ImgWidth - TemplateWidth, CV_8UC1,255);  
  55.     //namedWindow("result", CV_WINDOW_NORMAL );  
  56.     //imshow("result",mat_src);  
  57.     //uchar *p;  
  58.     //while(start_x < ImgWidth - TemplateWidth){  
  59.     for(long start_y = 0;start_y <ImgHeight - TemplateHeight;start_y = start_y+ystep){  
  60.         for(long start_x = 0;start_x < ImgWidth - TemplateWidth;start_x = start_x+xstep){  
  61.           
  62.             x = start_x;  
  63.             y = start_y;  
  64.             //std::cout<<"<"<<x<<","<<y<<">"<<" ";  
  65.   
  66.             cvSetImageROI(src,cvRect(x,y,TemplateWidth,TemplateHeight));  
  67.             dst = cvCreateImage(cvSize(TemplateWidth,TemplateHeight),  
  68.                     IPL_DEPTH_8U,  
  69.                     src->nChannels);  
  70.             cvCopy(src,dst,0);  
  71.             cvResetImageROI(src);  
  72.   
  73.             Mat DstImage = Mat(dst, false); // Do not copy  
  74.             orb(DstImage,Mat(),RightKey,RightDescriptor);  
  75.             //std::cout<<RightDescriptor.size();  
  76.             pMatcher->match(LeftDescriptor, RightDescriptor, Matches);  
  77.             //double sum = 0;  
  78.             double sum = 0;  
  79.             //int i = 0;  
  80.             for(vector<DMatch>::iterator dite = Matches.begin();dite <Matches.end(); dite++ )  
  81.               {  
  82.                   sum += dite->distance;  
  83.               }  
  84.             int matchSize = Matches.size()*10;  
  85.             //std::cout<<matchSize<<" ";  
  86.             if(matchSize>1){  
  87.                 //int meanDis = sum/matchSize;  
  88.                 fout<<exp(-sum/matchSize)<<" ";  
  89.                 //std::cout<<"meanDis"<<meanDis<<" ";  
  90.                 //R.at<uchar>(x,y) = meanDis;  
  91.             }else{  
  92.                 fout<<exp(-100.0)<<" ";  
  93.                 //fout<<255<<" ";  
  94.                 //std::cout<<"meanDis"<<255<<" ";  
  95.             }  
  96.   
  97.         }  
  98.         //std::cout<<endl;  
  99.         fout<<"\n";  
  100.         //start_x += step;  
  101.     }  
  102.     //  
  103.     std::cout<<"finish";  
  104.     fout.close();  
  105.   
  106.     //destroyWindow("result" );  
  107.     //imwrite(resultPath,R);  
  108.   
  109.     //delete pDetector;  
  110.     //delete pExtractor;  
  111.     delete pMatcher;  
  112.   
  113. }  

对利用特征点对图片左右部分进行匹配

[cpp] view plaincopy
  1. void getMatchLR(string imgname)  
  2. {  
  3.   
  4.     string imgpath = imgdir + imgname;  
  5.     mat_src = imread(imgpath, CV_LOAD_IMAGE_GRAYSCALE );  
  6.     if(!mat_src.data) {  
  7.         cout<<"no img";  
  8.         return ;  
  9.       }  
  10.     mat_src_lpl = IplImage(mat_src);  
  11.     src  = &mat_src_lpl;  
  12.   
  13.   
  14.     //  
  15.     cvSetImageROI(src,cvRect(0,0,0.5*src->width,src->height));  
  16.     dst_left = cvCreateImage(cvSize(0.5*src->width,src->height),  
  17.             IPL_DEPTH_8U,  
  18.             src->nChannels);  
  19.     cvCopy(src,dst_left,0);  
  20.     cvResetImageROI(src);  
  21.   
  22.     cvSetImageROI(src,cvRect(0.5*src->width,0,0.5*src->width,src->height));  
  23.     dst_right = cvCreateImage(cvSize(0.5*src->width,src->height),  
  24.             IPL_DEPTH_8U,  
  25.             src->nChannels);  
  26.     cvCopy(src,dst_right,0);  
  27.     cvResetImageROI(src);  
  28.   
  29.   
  30.      // Convert IplImage to cv::Mat  
  31.     Mat matLeftImage = Mat(dst_left, false); // Do not copy  
  32.     Mat matRightImage = Mat(dst_right, false);  
  33.   
  34.     // Key point and its descriptor  
  35.     vector<KeyPoint> LeftKey;  
  36.     vector<KeyPoint> RightKey;  
  37.     Mat LeftDescriptor;  
  38.     Mat RightDescriptor;  
  39.     vector<DMatch> Matches;  
  40.   
  41.     /* 
  42.     // Detect key points from image 
  43.     FeatureDetector *pDetector = new FastFeatureDetector; //  
  44.     pDetector->detect(matLeftImage, LeftKey); 
  45.     pDetector->detect(matRightImage, RightKey); 
  46.     delete pDetector; 
  47.  
  48.     // Extract descriptors 
  49.     DescriptorExtractor *pExtractor = new BriefDescriptorExtractor; //  
  50.     pExtractor->compute(matLeftImage, LeftKey, LeftDescriptor); 
  51.     pExtractor->compute(matRightImage, RightKey, RightDescriptor); 
  52.     delete pExtractor; 
  53.     */  
  54.       
  55.       
  56.     ORB orb;  
  57.     orb(matLeftImage,Mat(),LeftKey,LeftDescriptor);  
  58.     orb(matRightImage,Mat(),RightKey,RightDescriptor);  
  59.       
  60.   
  61.     // Matching features  
  62.     //DescriptorMatcher *pMatcher = new FlannBasedMatcher; //   
  63.     DescriptorMatcher *pMatcher = new BruteForceMatcher<HammingLUT>; //   
  64.     pMatcher->match(LeftDescriptor, RightDescriptor, Matches);  
  65.     delete pMatcher;  
  66.   
  67.   
  68.     double max_dist = 0; double min_dist = 200;  
  69.   
  70.       //-- Quick calculation of max and min distances between keypoints  
  71.       forint i = 0; i < LeftDescriptor.rows; i++ )  
  72.       { double dist = Matches[i].distance;  
  73.         if( dist < min_dist ) min_dist = dist;  
  74.         if( dist > max_dist ) max_dist = dist;  
  75.       }  
  76.   
  77.       //printf("-- Max dist : %f \n", max_dist );  
  78.       //printf("-- Min dist : %f \n", min_dist );  
  79.   
  80.       //-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist )  
  81.       //-- PS.- radiusMatch can also be used here.  
  82.       std::vector< DMatch > good_matches;  
  83.   
  84.       forint i = 0; i < LeftDescriptor.rows; i++ )  
  85.       { if( Matches[i].distance < 0.5*max_dist )  
  86.         { good_matches.push_back( Matches[i]); }  
  87.       }  
  88.   
  89.     // Show result  
  90.     //drawMatches(matLeftImage, LeftKey, matRightImage, RightKey, Matches, OutImage);  
  91.     drawMatches( matLeftImage, LeftKey, matRightImage, RightKey,  
  92.                    good_matches, OutImage, Scalar::all(-1), Scalar::all(-1),  
  93.                    vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );  
  94.     OutImage_lpl = IplImage(OutImage);  
  95.     cvNamedWindow( "Match features", 1);  
  96.     cvShowImage("Match features", &(OutImage_lpl));  
  97.     cvWaitKey( 0 );  
  98.     cvDestroyWindow( "Match features" );  
  99.   
  100.     string savepath = Matchsavedir + imgname;  
  101.       //-- Show detected (drawn) keypoints  
  102.     imwrite(savepath, OutImage );//  
  103. }  

以上代码中被注释的部分
[cpp] view plaincopy
  1. // Detect key points from image  
  2. FeatureDetector *pDetector = new FastFeatureDetector; //   
  3. pDetector->detect(matLeftImage, LeftKey);  
  4. pDetector->detect(matRightImage, RightKey);  
  5. delete pDetector;  
  6.   
  7. // Extract descriptors  
  8. DescriptorExtractor *pExtractor = new BriefDescriptorExtractor; //   
  9. pExtractor->compute(matLeftImage, LeftKey, LeftDescriptor);  
  10. pExtractor->compute(matRightImage, RightKey, RightDescriptor);  

是利用的BRIEF特征,进行左右匹配