OpenCV 中SURF +SIFT+RANSAC算法

看到OpenCV2.4.6里面ORB特征提取算法也在里面了,套用给的SURF特征例子程序改为ORB特征一直提示错误,类型不匹配神马的,由于没有找到示例程序,只能自己找答案。

经过查找发现:

描述符数据类型有是float的,比如说SIFT,SURF描述符,还有是uchar的,比如说有ORB,BRIEF

对于float 匹配方式有:

FlannBased

BruteForce<L2<float> >

BruteForce<SL2<float> >

BruteForce<L1<float> >

对于uchar有:

BruteForce<Hammin>

BruteForce<HammingLUT>

BruteForceMatcher< L2<float> > matcher;//改动的地方

BruteForceMatcher< L2<float> > matcher;//改动的地方

完整代码如下:

经过查找发现:

描述符数据类型有是float的,比如说SIFT,SURF描述符,还有是uchar的,比如说有ORB,BRIEF

对于float 匹配方式有:

FlannBased

BruteForce<L2<float> >

BruteForce<SL2<float> >

BruteForce<L1<float> >

对于uchar有:

BruteForce<Hammin>

BruteForce<HammingLUT>

BruteForceMatcher< L2<float> > matcher;//改动的地方

BruteForceMatcher< L2<float> > matcher;//改动的地方

完整代码如下:

#include &quot;StdAfx.h&quot;
#include &lt;windows.h&gt;
#include &lt;iostream&gt;
#include &lt;opencv2/core/core.hpp&gt;
#include &lt;opencv2/highgui/highgui.hpp&gt;
#include &lt;opencv2/features2d/features2d.hpp&gt;
#include &lt;opencv2/nonfree/features2d.hpp&gt;
#include &lt;opencv2/calib3d/calib3d.hpp&gt;
#include &lt;opencv2/legacy/legacy.hpp&gt;
#include&lt;opencv2/nonfree/nonfree.hpp&gt;

  1. int main(int argc, char** argv)   
  2. {  
  3.     initModule_nonfree();//初始化模块,使用SIFT或SURF时用到      
  4.     Ptr<FeatureDetector> detector = FeatureDetector::create( "SURF" );//创建SIFT特征检测器,可改成SURF/ORB     
  5.     Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SURF" );//创建特征向量生成器,可改成SURF/ORB     
  6.     Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//创建特征匹配器       
  7.     if( detector.empty() || descriptor_extractor.empty() )      
  8.         cout<<"fail to create detector!";      
  9.   
  10.     //读入图像       
  11.     Mat img1 = imread("E:/Book/3.jpg");      
  12.     Mat img2 = imread("E:/Book/4.jpg");      
  13.   
  14.     Size imgSize(320,240);  
  15.     resize(img1, img1, imgSize);  
  16.     resize(img2, img2, imgSize);  
  17.   
  18.     //特征点检测       
  19.     double t = getTickCount();//当前滴答数       
  20.     vector<KeyPoint> m_LeftKey,m_RightKey;      
  21.     detector->detect( img1, m_LeftKey );//检测img1中的SIFT特征点,存储到m_LeftKey中       
  22.     detector->detect( img2, m_RightKey );      
  23.     cout<<"图像1特征点个数:"<<m_LeftKey.size()<<endl;      
  24.     cout<<"图像2特征点个数:"<<m_RightKey.size()<<endl;      
  25.   
  26.     //根据特征点计算特征描述子矩阵,即特征向量矩阵       
  27.     Mat descriptors1,descriptors2;      
  28.     descriptor_extractor->compute( img1, m_LeftKey, descriptors1 );      
  29.     descriptor_extractor->compute( img2, m_RightKey, descriptors2 );      
  30.     t = ((double)getTickCount() - t)/getTickFrequency();      
  31.     cout<<"SIFT算法用时:"<<t<<"秒"<<endl;      
  32.   
  33.     cout<<"图像1特征描述矩阵大小:"<<descriptors1.size()      
  34.         <<",特征向量个数:"<<descriptors1.rows<<",维数:"<<descriptors1.cols<<endl;      
  35.     cout<<"图像2特征描述矩阵大小:"<<descriptors2.size()      
  36.         <<",特征向量个数:"<<descriptors2.rows<<",维数:"<<descriptors2.cols<<endl;      
  37.   
  38.     //画出特征点       
  39.     Mat img_m_LeftKey,img_m_RightKey;      
  40.     drawKeypoints(img1,m_LeftKey,img_m_LeftKey,Scalar::all(-1),0);      
  41.     drawKeypoints(img2,m_RightKey,img_m_RightKey,Scalar::all(-1),0);      
  42.     //imshow("Src1",img_m_LeftKey);       
  43.     //imshow("Src2",img_m_RightKey);       
  44.   
  45.     //特征匹配       
  46.     vector<DMatch> matches;//匹配结果       
  47.     descriptor_matcher->match( descriptors1, descriptors2, matches );//匹配两个图像的特征矩阵       
  48.     cout<<"Match个数:"<<matches.size()<<endl;      
  49.   
  50.     //计算匹配结果中距离的最大和最小值       
  51.     //距离是指两个特征向量间的欧式距离,表明两个特征的差异,值越小表明两个特征点越接近       
  52.     double max_dist = 0;      
  53.     double min_dist = 100;      
  54.     for(int i=0; i<matches.size(); i++)      
  55.     {      
  56.         double dist = matches[i].distance;      
  57.         if(dist < min_dist) min_dist = dist;      
  58.         if(dist > max_dist) max_dist = dist;      
  59.     }      
  60.     cout<<"最大距离:"<<max_dist<<endl;      
  61.     cout<<"最小距离:"<<min_dist<<endl;      
  62.   
  63.     //筛选出较好的匹配点       
  64.     vector<DMatch> goodMatches;      
  65.     for(int i=0; i<matches.size(); i++)      
  66.     {      
  67.         if(matches[i].distance < 0.6 * max_dist)      
  68.         {      
  69.             goodMatches.push_back(matches[i]);      
  70.         }      
  71.     }      
  72.     cout<<"goodMatch个数:"<<goodMatches.size()<<endl;      
  73.   
  74.     //画出匹配结果       
  75.     Mat img_matches;      
  76.     //红色连接的是匹配的特征点对,绿色是未匹配的特征点       
  77.     drawMatches(img1,m_LeftKey,img2,m_RightKey,goodMatches,img_matches,      
  78.         Scalar::all(-1)/*CV_RGB(255,0,0)*/,CV_RGB(0,255,0),Mat(),2);      
  79.   
  80.     imshow("MatchSIFT",img_matches);      
  81.     IplImage result=img_matches;    
  82.   
  83.     waitKey(10);    
  84.   
  85.   
  86.     //RANSAC匹配过程     
  87.     vector<DMatch> m_Matches=goodMatches;    
  88.     // 分配空间     
  89.     int ptCount = (int)m_Matches.size();    
  90.   
  91.     if ( ptCount<100)  
  92.     {         
  93.         cout<<"没有找到足够的匹配点"<<endl;  
  94.         waitKey(0);  
  95.         return 0;  
  96.     }  
  97.     Mat p1(ptCount, 2, CV_32F);    
  98.     Mat p2(ptCount, 2, CV_32F);    
  99.   
  100.     // 把Keypoint转换为Mat     
  101.     Point2f pt;    
  102.     for (int i=0; i<ptCount; i++)    
  103.     {    
  104.         pt = m_LeftKey[m_Matches[i].queryIdx].pt;    
  105.         p1.at<float>(i, 0) = pt.x;    
  106.         p1.at<float>(i, 1) = pt.y;    
  107.   
  108.         pt = m_RightKey[m_Matches[i].trainIdx].pt;    
  109.         p2.at<float>(i, 0) = pt.x;    
  110.         p2.at<float>(i, 1) = pt.y;    
  111.     }    
  112.   
  113.     // 用RANSAC方法计算F     
  114.     Mat m_Fundamental;    
  115.     vector<uchar> m_RANSACStatus;       // 这个变量用于存储RANSAC后每个点的状态     
  116.     findFundamentalMat(p1, p2, m_RANSACStatus, FM_RANSAC);    
  117.   
  118.     // 计算野点个数     
  119.   
  120.     int OutlinerCount = 0;    
  121.     for (int i=0; i<ptCount; i++)    
  122.     {    
  123.         if (m_RANSACStatus[i] == 0)    // 状态为0表示野点     
  124.         {    
  125.             OutlinerCount++;    
  126.         }    
  127.     }    
  128.     int InlinerCount = ptCount - OutlinerCount;   // 计算内点     
  129.     cout<<"内点数为:"<<InlinerCount<<endl;    
  130.   
  131.   
  132.     // 这三个变量用于保存内点和匹配关系     
  133.     vector<Point2f> m_LeftInlier;    
  134.     vector<Point2f> m_RightInlier;    
  135.     vector<DMatch> m_InlierMatches;    
  136.   
  137.     m_InlierMatches.resize(InlinerCount);    
  138.     m_LeftInlier.resize(InlinerCount);    
  139.     m_RightInlier.resize(InlinerCount);    
  140.     InlinerCount=0;    
  141.     float inlier_minRx=img1.cols;        //用于存储内点中右图最小横坐标,以便后续融合     
  142.   
  143.     for (int i=0; i<ptCount; i++)    
  144.     {    
  145.         if (m_RANSACStatus[i] != 0)    
  146.         {    
  147.             m_LeftInlier[InlinerCount].x = p1.at<float>(i, 0);    
  148.             m_LeftInlier[InlinerCount].y = p1.at<float>(i, 1);    
  149.             m_RightInlier[InlinerCount].x = p2.at<float>(i, 0);    
  150.             m_RightInlier[InlinerCount].y = p2.at<float>(i, 1);    
  151.             m_InlierMatches[InlinerCount].queryIdx = InlinerCount;    
  152.             m_InlierMatches[InlinerCount].trainIdx = InlinerCount;    
  153.   
  154.             if(m_RightInlier[InlinerCount].x<inlier_minRx) inlier_minRx=m_RightInlier[InlinerCount].x;   //存储内点中右图最小横坐标     
  155.   
  156.             InlinerCount++;    
  157.         }    
  158.     }    
  159.   
  160.     // 把内点转换为drawMatches可以使用的格式     
  161.     vector<KeyPoint> key1(InlinerCount);    
  162.     vector<KeyPoint> key2(InlinerCount);    
  163.     KeyPoint::convert(m_LeftInlier, key1);    
  164.     KeyPoint::convert(m_RightInlier, key2);    
  165.   
  166.     // 显示计算F过后的内点匹配     
  167.     Mat OutImage;    
  168.     drawMatches(img1, key1, img2, key2, m_InlierMatches, OutImage);    
  169.     cvNamedWindow( "Match features", 1);    
  170.     cvShowImage("Match features", &IplImage(OutImage));    
  171.     waitKey(10);    
  172.   
  173.     cvDestroyAllWindows();    
  174.   
  175.     //矩阵H用以存储RANSAC得到的单应矩阵     
  176.     Mat H = findHomography( m_LeftInlier, m_RightInlier, RANSAC );    
  177.   
  178.     //存储左图四角,及其变换到右图位置     
  179.     std::vector<Point2f> obj_corners(4);    
  180.     obj_corners[0] = Point(0,0); obj_corners[1] = Point( img1.cols, 0 );    
  181.     obj_corners[2] = Point( img1.cols, img1.rows ); obj_corners[3] = Point( 0, img1.rows );    
  182.     std::vector<Point2f> scene_corners(4);    
  183.     perspectiveTransform( obj_corners, scene_corners, H);    
  184.   
  185.     //画出变换后图像位置     
  186.     Point2f offset( (float)img1.cols, 0);      
  187.     line( OutImage, scene_corners[0]+offset, scene_corners[1]+offset, Scalar( 0, 255, 0), 4 );    
  188.     line( OutImage, scene_corners[1]+offset, scene_corners[2]+offset, Scalar( 0, 255, 0), 4 );    
  189.     line( OutImage, scene_corners[2]+offset, scene_corners[3]+offset, Scalar( 0, 255, 0), 4 );    
  190.     line( OutImage, scene_corners[3]+offset, scene_corners[0]+offset, Scalar( 0, 255, 0), 4 );    
  191.     imshow( "Good Matches & Object detection", OutImage );    
  192.   
  193.     waitKey(10);    
  194.     imwrite("warp_position.jpg",OutImage);    
  195.   
  196.   
  197.     int drift = scene_corners[1].x;                                                        //储存偏移量     
  198.   
  199.     //新建一个矩阵存储配准后四角的位置     
  200.     int width = int(max(abs(scene_corners[1].x), abs(scene_corners[2].x)));    
  201.     int height= img1.rows;                                                                  //或者:int height = int(max(abs(scene_corners[2].y), abs(scene_corners[3].y)));     
  202.     float origin_x=0,origin_y=0;    
  203.     if(scene_corners[0].x<0) {    
  204.         if (scene_corners[3].x<0) origin_x+=min(scene_corners[0].x,scene_corners[3].x);    
  205.         else origin_x+=scene_corners[0].x;}    
  206.     width-=int(origin_x);    
  207.     if(scene_corners[0].y<0) {    
  208.         if (scene_corners[1].y) origin_y+=min(scene_corners[0].y,scene_corners[1].y);    
  209.         else origin_y+=scene_corners[0].y;}    
  210.     //可选:height-=int(origin_y);     
  211.     Mat imageturn=Mat::zeros(width,height,img1.type());    
  212.   
  213.     //获取新的变换矩阵,使图像完整显示     
  214.     for (int i=0;i<4;i++) {scene_corners[i].x -= origin_x; }     //可选:scene_corners[i].y -= (float)origin_y; }     
  215.     Mat H1=getPerspectiveTransform(obj_corners, scene_corners);    
  216.   
  217.     //进行图像变换,显示效果     
  218.     warpPerspective(img1,imageturn,H1,Size(width,height));      
  219.     imshow("image_Perspective", imageturn);    
  220.     waitKey(10);    
  221.   
  222.   
  223.     //图像融合     
  224.     int width_ol=width-int(inlier_minRx-origin_x);    
  225.     int start_x=int(inlier_minRx-origin_x);    
  226.     cout<<"width: "<<width<<endl;    
  227.     cout<<"img1.width: "<<img1.cols<<endl;    
  228.     cout<<"start_x: "<<start_x<<endl;    
  229.     cout<<"width_ol: "<<width_ol<<endl;    
  230.   
  231.     uchar* ptr=imageturn.data;    
  232.     double alpha=0, beta=1;    
  233.     for (int row=0;row<height;row++)  
  234.     {    
  235.         ptr=imageturn.data+row*imageturn.step+(start_x)*imageturn.elemSize();    
  236.         for(int col=0;col<width_ol;col++)    
  237.         {    
  238.             uchar* ptr_c1=ptr+imageturn.elemSize1();   
  239.             uchar*  ptr_c2=ptr_c1+imageturn.elemSize1();    
  240.             uchar* ptr2=img2.data+row*img2.step+(col+int(inlier_minRx))*img2.elemSize();    
  241.             uchar* ptr2_c1=ptr2+img2.elemSize1();   
  242.             uchar* ptr2_c2=ptr2_c1+img2.elemSize1();    
  243.   
  244.             alpha=double(col)/double(width_ol); beta=1-alpha;    
  245.   
  246.             if (*ptr==0&&*ptr_c1==0&&*ptr_c2==0)   
  247.             {    
  248.                 *ptr=(*ptr2);    
  249.                 *ptr_c1=(*ptr2_c1);    
  250.                 *ptr_c2=(*ptr2_c2);    
  251.             }    
  252.   
  253.             *ptr=(*ptr)*beta+(*ptr2)*alpha;    
  254.             *ptr_c1=(*ptr_c1)*beta+(*ptr2_c1)*alpha;    
  255.             *ptr_c2=(*ptr_c2)*beta+(*ptr2_c2)*alpha;    
  256.   
  257.             ptr+=imageturn.elemSize();    
  258.     }   }    
  259.   
  260.     //imshow("image_overlap", imageturn);     
  261.     //waitKey(0);     
  262.   
  263.     Mat img_result=Mat::zeros(height,width+img2.cols-drift,img1.type());    
  264.     uchar* ptr_r=imageturn.data;    
  265.   
  266.     for (int row=0;row<height;row++)   
  267.     {    
  268.         ptr_r=img_result.data+row*img_result.step;    
  269.   
  270.         for(int col=0;col<img_result.cols;col++)    
  271.         {    
  272.             uchar* ptr_rc1=ptr_r+imageturn.elemSize1();   
  273.             uchar* ptr_rc2=ptr_rc1+imageturn.elemSize1();    
  274.   
  275.             uchar* ptr=imageturn.data+row*imageturn.step+col*imageturn.elemSize();    
  276.             uchar* ptr_c1=ptr+imageturn.elemSize1();  
  277.             uchar* ptr_c2=ptr_c1+imageturn.elemSize1();    
  278.   
  279.             *ptr_r=*ptr;    
  280.             *ptr_rc1=*ptr_c1;    
  281.             *ptr_rc2=*ptr_c2;    
  282.   
  283.             ptr_r+=img_result.elemSize();    
  284.         }       
  285.   
  286.         ptr_r=img_result.data+row*img_result.step+imageturn.cols*img_result.elemSize();    
  287.         for(int col=imageturn.cols;col<img_result.cols;col++)    
  288.         {    
  289.             uchar* ptr_rc1=ptr_r+imageturn.elemSize1();  
  290.             uchar*  ptr_rc2=ptr_rc1+imageturn.elemSize1();    
  291.   
  292.             uchar* ptr2=img2.data+row*img2.step+(col-imageturn.cols+drift)*img2.elemSize();    
  293.             uchar* ptr2_c1=ptr2+img2.elemSize1();   
  294.             uchar* ptr2_c2=ptr2_c1+img2.elemSize1();    
  295.   
  296.             *ptr_r=*ptr2;    
  297.             *ptr_rc1=*ptr2_c1;    
  298.             *ptr_rc2=*ptr2_c2;    
  299.   
  300.             ptr_r+=img_result.elemSize();    
  301.         }       
  302.     }    
  303.   
  304.     //imshow("image_result", img_result);    
  305.     //imwrite("final_result.jpg",img_result);    
  306.     waitKey(0);  
  307.   
  308.     return 0;  
  309. }  
原文出自http://blog.csdn.net/kezunhai/article/details/47438595
  • 0
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值