zoukankan      html  css  js  c++  java
  • 学习OpenCV——BOW特征提取函数(特征点篇)

    没日没夜的改论文生活终于要告一段落了,比起改论文,学OpenCV就是一件幸福的事情。OpenCV的发展越来越完善了,已经可以直接使用BOW函数来进行对象分类了。

    简单的通过特征点分类的方法:                                                                      

    一、train

    1.提取+/- sample的feature,每幅图提取出的sift特征个数不定(假设每个feature有128维)

    2.利用聚类方法(e.g K-means)将不定数量的feature聚类为固定数量的(比如10个)words即BOW(bag of word)

    (本篇文章主要完成以上的工作!)

    3.normalize,并作这10个类的直方图e.g [0.1,0.2,0.7,0...0];

    4.将each image的这10个word作为feature_instance 和 (手工标记的) label(+/-)进入SVM训练



    二、predict

    1. 提取test_img的feature(如137个)

    2. 分别求each feature与10个类的距离(e.g. 128维欧氏距离),确定该feature属于哪个类

    3. normalize,并作这10个类的直方图e.g [0,0.2,0.2,0.6,0...0];

    4. 应用SVM_predict进行结果预测

    通过OpenCV实现feature聚类 BOW                                                             

    首先在此介绍一下OpenCV的特征描述符与BOW的通用函数。

    主要的通用接口有:

     

    1.特征点提取

    Ptr<FeatureDetector> FeatureDetector::create(const string& detectorType)

    [cpp] view plain copy
     
     print?
    1.     Ptr<FeatureDetector> FeatureDetector::create(const string& detectorType)  
    2. //  "FAST" – FastFeatureDetector   
    3. //  "STAR" – StarFeatureDetector   
    4. //  "SIFT" – SIFT (nonfree module)//必须使用 initModule_nonfree()初始化  
    5. //  "SURF" – SURF (nonfree module)//同上;   
    6. //  "ORB" – ORB   
    7. //  "MSER" – MSER   
    8. //  "GFTT" – GoodFeaturesToTrackDetector   
    9. //  "HARRIS" – GoodFeaturesToTrackDetector with Harris detector enabled   
    10. //  "Dense" – DenseFeatureDetector   
    11. //  "SimpleBlob" – SimpleBlobDetector   

    根据以上接口,测试不同的特征点:

    对同一幅图像进行水平翻转前后的两幅图像检测特征点检测结果,

    检测到的特征点的坐标类型为:pt: int / float(与keyPoint的性质有关)

    数量分别为num1, num2,

     "FAST" – FastFeatureDetector           pt:int (num1:615  num2:618)
     "STAR" – StarFeatureDetector           pt:int (num1:43   num2:42 )
     "SIFT" – SIFT (nonfree module)          pt:float(num1:155  num2:135)            //必须使用 initModule_nonfree()初始化
     "SURF" – SURF (nonfree module)     pt:float(num1:344  num2:342)           //同上; 
     "ORB" – ORB                                        pt:float(num1:496  num2:497)
     "MSER" – MSER                                 pt:float(num1:51   num2:45 )
     "GFTT" – GoodFeaturesToTrackDetector        pt:int (num1:744  num2:771)
     "HARRIS" – GoodFeaturesToTrackDetector with Harris detector enabled         pt:float(num1:162  num2:160)
     "Dense" – DenseFeatureDetector          pt:int (num1:3350 num2:3350)


    2.特征描述符提取

    Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)

    [cpp] view plain copy
     
     print?
    1. //  Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)     
    2. //  "SIFT" – SIFT   
    3. //  "SURF" – SURF   
    4. //  "ORB" – ORB   
    5. //  "BRIEF" – BriefDescriptorExtractor   

    3.描述符匹配

    Ptr<DescriptorMatcher> descriptorMatcher = DescriptorMatcher::create(const string& descriptorMatcherType)

    [cpp] view plain copy
     
     print?
    1. //  descriptorMatcherType – Descriptor matcher type.   
    2. //  Now the following matcher types are supported:   
    3. //      BruteForce (it uses L2 )   
    4. //      BruteForce-L1   
    5. //      BruteForce-Hamming   
    6. //      BruteForce-Hamming(2)   
    7. //      FlannBased   
    8.     Ptr<DescriptorMatcher> descriptorMatcher = DescriptorMatcher::create( "BruteForce" );  

    4.class BOWTrainer

    class BOWKmeansTrainer::public BOWTrainer:Kmeans算法训练

    BOWKMeansTrainer ::BOWKmeansTrainer(int clusterCount, const TermCriteria& termcrit=TermCriteria(), int attempts=3, int flags=KMEANS_PP_CENTERS)

    parameter same as Kmeans

    代码实现:                                                                                                                    

    1.画特征点。

    2.特征点Kmeans聚类,每一种颜色代表一个类别。

    [cpp] view plain copy
     
     print?
    1. #include "opencv2/highgui/highgui.hpp"  
    2. #include "opencv2/calib3d/calib3d.hpp"  
    3. #include "opencv2/imgproc/imgproc.hpp"  
    4. #include "opencv2/features2d/features2d.hpp"  
    5. #include "opencv2/nonfree/nonfree.hpp"  
    6.   
    7. #include <iostream>  
    8.   
    9. using namespace cv;  
    10. using namespace std;  
    11.   
    12. #define ClusterNum 10  
    13.   
    14. void DrawAndMatchKeypoints(const Mat& Img1,const Mat& Img2,const vector<KeyPoint>& Keypoints1,  
    15.     const vector<KeyPoint>& Keypoints2,const Mat& Descriptors1,const Mat& Descriptors2)  
    16. {  
    17.     Mat keyP1,keyP2;  
    18.     drawKeypoints(Img1,Keypoints1,keyP1,Scalar::all(-1),0);  
    19.     drawKeypoints(Img2,Keypoints2,keyP2,Scalar::all(-1),0);  
    20.     putText(keyP1, "drawKeyPoints", cvPoint(10,30), FONT_HERSHEY_SIMPLEX, 1 ,Scalar :: all(-1));  
    21.     putText(keyP2, "drawKeyPoints", cvPoint(10,30), FONT_HERSHEY_SIMPLEX, 1 ,Scalar :: all(-1));  
    22.     imshow("img1 keyPoints",keyP1);  
    23.     imshow("img2 keyPoints",keyP2);  
    24.   
    25.     Ptr<DescriptorMatcher> descriptorMatcher = DescriptorMatcher::create( "BruteForce" );  
    26.     vector<DMatch> matches;  
    27.     descriptorMatcher->match( Descriptors1, Descriptors2, matches );  
    28.     Mat show;  
    29.     drawMatches(Img1,Keypoints1,Img2,Keypoints2,matches,show,Scalar::all(-1),CV_RGB(255,255,255),Mat(),4);  
    30.     putText(show, "drawMatchKeyPoints", cvPoint(10,30), FONT_HERSHEY_SIMPLEX, 1 ,Scalar :: all(-1));    
    31.     imshow("match",show);  
    32. }  
    33.   
    34. //测试OpenCV:class BOWTrainer  
    35. void BOWKeams(const Mat& img, const vector<KeyPoint>& Keypoints,   
    36.     const Mat& Descriptors, Mat& centers)  
    37. {  
    38.     //BOW的kmeans算法聚类;  
    39.     BOWKMeansTrainer bowK(ClusterNum,   
    40.         cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 0.1),3,2);  
    41.     centers = bowK.cluster(Descriptors);  
    42.     cout<<endl<<"< cluster num: "<<centers.rows<<" >"<<endl;  
    43.       
    44.     Ptr<DescriptorMatcher> descriptorMatcher = DescriptorMatcher::create( "BruteForce" );  
    45.     vector<DMatch> matches;  
    46.     descriptorMatcher->match(Descriptors,centers,matches);//const Mat& queryDescriptors, const Mat& trainDescriptors第一个参数是待分类节点,第二个参数是聚类中心;  
    47.     Mat demoCluster;  
    48.     img.copyTo(demoCluster);  
    49.       
    50.     //为每一类keyPoint定义一种颜色  
    51.     Scalar color[]={CV_RGB(255,255,255),  
    52.      CV_RGB(255,0,0),CV_RGB(0,255,0),CV_RGB(0,0,255),  
    53.      CV_RGB(255,255,0),CV_RGB(255,0,255),CV_RGB(0,255,255),  
    54.      CV_RGB(123,123,0),CV_RGB(0,123,123),CV_RGB(123,0,123)};  
    55.   
    56.   
    57.     for (vector<DMatch>::iterator iter=matches.begin();iter!=matches.end();iter++)  
    58.     {  
    59.         cout<<"< descriptorsIdx:"<<iter->queryIdx<<"  centersIdx:"<<iter->trainIdx  
    60.             <<" distincs:"<<iter->distance<<" >"<<endl;  
    61.         Point center= Keypoints[iter->queryIdx].pt;  
    62.         circle(demoCluster,center,2,color[iter->trainIdx],-1);  
    63.     }  
    64.     putText(demoCluster, "KeyPoints Clustering: 一种颜色代表一种类型",  
    65.         cvPoint(10,30), FONT_HERSHEY_SIMPLEX, 1 ,Scalar :: all(-1));  
    66.     imshow("KeyPoints Clusrtering",demoCluster);  
    67.       
    68. }  
    69.   
    70.   
    71.   
    72.   
    73. int main()  
    74. {  
    75.     cv::initModule_nonfree();//使用SIFT/SURF create之前,必须先initModule_<modulename>();   
    76.   
    77.     cout << "< Creating detector, descriptor extractor and descriptor matcher ...";  
    78.     Ptr<FeatureDetector> detector = FeatureDetector::create( "SIFT" );  
    79.   
    80.     Ptr<DescriptorExtractor> descriptorExtractor = DescriptorExtractor::create( "SIFT" );  
    81.   
    82.     Ptr<DescriptorMatcher> descriptorMatcher = DescriptorMatcher::create( "BruteForce" );  
    83.   
    84.   
    85.   
    86.     cout << ">" << endl;  
    87.   
    88.     if( detector.empty() || descriptorExtractor.empty() )  
    89.     {  
    90.         cout << "Can not create detector or descriptor exstractor or descriptor matcher of given types" << endl;  
    91.         return -1;  
    92.     }  
    93.     cout << endl << "< Reading images..." << endl;  
    94.     Mat img1 = imread("D:/demo0.jpg");  
    95.     Mat img2 = imread("D:/demo1.jpg");  
    96.     cout<<endl<<">"<<endl;  
    97.   
    98.   
    99.     //detect keypoints;  
    100.     cout << endl << "< Extracting keypoints from images..." << endl;  
    101.     vector<KeyPoint> keypoints1,keypoints2;  
    102.     detector->detect( img1, keypoints1 );  
    103.     detector->detect( img2, keypoints2 );  
    104.     cout <<"img1:"<< keypoints1.size() << " points  img2:" <<keypoints2.size()   
    105.         << " points" << endl << ">" << endl;  
    106.       
    107.     //compute descriptors for keypoints;  
    108.     cout << "< Computing descriptors for keypoints from images..." << endl;  
    109.     Mat descriptors1,descriptors2;  
    110.     descriptorExtractor->compute( img1, keypoints1, descriptors1 );  
    111.     descriptorExtractor->compute( img2, keypoints2, descriptors2 );  
    112.   
    113.     cout<<endl<<"< Descriptoers Size: "<<descriptors2.size()<<" >"<<endl;  
    114.     cout<<endl<<"descriptor's col: "<<descriptors2.cols<<endl  
    115.         <<"descriptor's row: "<<descriptors2.rows<<endl;  
    116.     cout << ">" << endl;  
    117.   
    118.     //Draw And Match img1,img2 keypoints  
    119.     //匹配的过程是对特征点的descriptors进行match;  
    120.     DrawAndMatchKeypoints(img1,img2,keypoints1,keypoints2,descriptors1,descriptors2);  
    121.   
    122.     Mat center;  
    123.     //对img1提取特征点,并聚类  
    124.     //测试OpenCV:class BOWTrainer  
    125.     BOWKeams(img1,keypoints1,descriptors1,center);  
    126.   
    127.   
    128.     waitKey();  
    129.   
    130. }  

    通过Qt实现DrawKeypoints:

    [cpp] view plain copy
     
     print?
    1. void Qt_test1::on_DrawKeypoints_clicked()  
    2. {  
    3.     //initModule_nonfree();  
    4.     Ptr<FeatureDetector> detector = FeatureDetector::create( "FAST" );  
    5.     vector<KeyPoint> keypoints;  
    6.     detector->detect( src, keypoints );  
    7.   
    8.     Mat DrawKeyP;  
    9.     drawKeypoints(src,keypoints,DrawKeyP,Scalar::all(-1),0);  
    10.     putText(DrawKeyP, "drawKeyPoints", cvPoint(10,30),   
    11.         FONT_HERSHEY_SIMPLEX, 0.5 ,Scalar :: all(255));  
    12.     cvtColor(DrawKeyP, image, CV_RGB2RGBA);  
    13.     QImage img = QImage((const unsigned char*)(image.data),   
    14.         image.cols, image.rows, QImage::Format_RGB32);  
    15.     QLabel *label = new QLabel(this);  
    16.     label->move(50, 50);//图像在窗口中所处的位置;  
    17.     label->setPixmap(QPixmap::fromImage(img));  
    18.     label->resize(label->pixmap()->size());      
    19.     label->show();  
    20. }  

    由于initModule_nonfree()总是出错,无法对SIFT与SURF特征点提取,

    而且无法实现聚类因为运行/BOW的kmeans算法聚类:BOWKMeansTrainer bowK(ClusterNum, cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 0.1),3,2);总是出错,不知道咋解决~~~~~(>_<)~~~~ 需要继续学习

    from: http://blog.csdn.net/yangtrees/article/details/8456237

  • 相关阅读:
    装饰器函数
    二分查找
    jmter 二次开发 IDEA 项目5.1
    python 测试框架nose
    pycharm 参数、快捷键、调试模式
    IDea 工具debug模式详细使用说明
    MySQL zip安装
    adb 设备命令
    兰亭集序 王羲之
    adb 命令实用
  • 原文地址:https://www.cnblogs.com/GarfieldEr007/p/5401859.html
Copyright © 2011-2022 走看看