Home | History | Annotate | Download | only in cpp
      1 #include <opencv2/opencv.hpp>
      2 #include <vector>
      3 #include <iostream>
      4 
      5 using namespace std;
      6 using namespace cv;
      7 
      8 static void help()
      9 {
     10     cout << "\n This program demonstrates how to detect compute and match ORB BRISK and AKAZE descriptors \n"
     11         "Usage: \n"
     12         "  ./matchmethod_orb_akaze_brisk <image1(../data/basketball1.png as default)> <image2(../data/basketball2.png as default)>\n"
     13         "Press a key when image window is active to change algorithm or descriptor";
     14 }
     15 
     16 
     17 
     18 int main(int argc, char *argv[])
     19 {
     20     vector<String> typeDesc;
     21     vector<String> typeAlgoMatch;
     22     vector<String> fileName;
     23     help();
     24     // This descriptor are going to be detect and compute
     25     typeDesc.push_back("AKAZE-DESCRIPTOR_KAZE_UPRIGHT");    // see http://docs.opencv.org/trunk/d8/d30/classcv_1_1AKAZE.html
     26     typeDesc.push_back("AKAZE");    // see http://docs.opencv.org/trunk/d8/d30/classcv_1_1AKAZE.html
     27     typeDesc.push_back("ORB");      // see http://docs.opencv.org/trunk/de/dbf/classcv_1_1BRISK.html
     28     typeDesc.push_back("BRISK");    // see http://docs.opencv.org/trunk/db/d95/classcv_1_1ORB.html
     29    // This algorithm would be used to match descriptors see http://docs.opencv.org/trunk/db/d39/classcv_1_1DescriptorMatcher.html#ab5dc5036569ecc8d47565007fa518257
     30     typeAlgoMatch.push_back("BruteForce");
     31     typeAlgoMatch.push_back("BruteForce-L1");
     32     typeAlgoMatch.push_back("BruteForce-Hamming");
     33     typeAlgoMatch.push_back("BruteForce-Hamming(2)");
     34     if (argc==1)
     35     {
     36         fileName.push_back("../data/basketball1.png");
     37         fileName.push_back("../data/basketball2.png");
     38     }
     39     else if (argc==3)
     40     {
     41         fileName.push_back(argv[1]);
     42         fileName.push_back(argv[2]);
     43     }
     44     else
     45     {
     46         help();
     47         return(0);
     48     }
     49     Mat img1 = imread(fileName[0], IMREAD_GRAYSCALE);
     50     Mat img2 = imread(fileName[1], IMREAD_GRAYSCALE);
     51     if (img1.rows*img1.cols <= 0)
     52         {
     53         cout << "Image " << fileName[0] << " is empty or cannot be found\n";
     54         return(0);
     55         }
     56     if (img2.rows*img2.cols <= 0)
     57         {
     58         cout << "Image " << fileName[1] << " is empty or cannot be found\n";
     59         return(0);
     60         }
     61 
     62     vector<double> desMethCmp;
     63     Ptr<Feature2D> b;
     64 
     65     // Descriptor loop
     66     vector<String>::iterator itDesc;
     67     for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); itDesc++)
     68     {
     69         Ptr<DescriptorMatcher> descriptorMatcher;
     70         // Match between img1 and img2
     71         vector<DMatch> matches;
     72         // keypoint  for img1 and img2
     73         vector<KeyPoint> keyImg1, keyImg2;
     74         // Descriptor for img1 and img2
     75         Mat descImg1, descImg2;
     76         vector<String>::iterator itMatcher = typeAlgoMatch.end();
     77         if (*itDesc == "AKAZE-DESCRIPTOR_KAZE_UPRIGHT"){
     78             b = AKAZE::create(AKAZE::DESCRIPTOR_KAZE_UPRIGHT);
     79             }
     80         if (*itDesc == "AKAZE"){
     81             b = AKAZE::create();
     82             }
     83         if (*itDesc == "ORB"){
     84             b = ORB::create();
     85         }
     86         else if (*itDesc == "BRISK"){
     87             b = BRISK::create();
     88         }
     89         try
     90         {
     91             // We can detect keypoint with detect method
     92             b->detect(img1, keyImg1, Mat());
     93             // and compute their descriptors with method  compute
     94             b->compute(img1, keyImg1, descImg1);
     95             // or detect and compute descriptors in one step
     96             b->detectAndCompute(img2, Mat(),keyImg2, descImg2,false);
     97             // Match method loop
     98             for (itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); itMatcher++){
     99                 descriptorMatcher = DescriptorMatcher::create(*itMatcher);
    100                 if ((*itMatcher == "BruteForce-Hamming" || *itMatcher == "BruteForce-Hamming(2)") && (b->descriptorType() == CV_32F || b->defaultNorm() <= NORM_L2SQR))
    101                 {
    102                     cout << "**************************************************************************\n";
    103                     cout << "It's strange. You should use Hamming distance only for a binary descriptor\n";
    104                     cout << "**************************************************************************\n";
    105                 }
    106                 if ((*itMatcher == "BruteForce" || *itMatcher == "BruteForce-L1") && (b->defaultNorm() >= NORM_HAMMING))
    107                 {
    108                     cout << "**************************************************************************\n";
    109                     cout << "It's strange. You shouldn't use L1 or L2 distance for a binary descriptor\n";
    110                     cout << "**************************************************************************\n";
    111                 }
    112                 try
    113                 {
    114                     descriptorMatcher->match(descImg1, descImg2, matches, Mat());
    115                     // Keep best matches only to have a nice drawing.
    116                     // We sort distance between descriptor matches
    117                     Mat index;
    118                     int nbMatch=int(matches.size());
    119                     Mat tab(nbMatch, 1, CV_32F);
    120                     for (int i = 0; i<nbMatch; i++)
    121                     {
    122                         tab.at<float>(i, 0) = matches[i].distance;
    123                     }
    124                     sortIdx(tab, index, SORT_EVERY_COLUMN + SORT_ASCENDING);
    125                     vector<DMatch> bestMatches;
    126                     for (int i = 0; i<30; i++)
    127                     {
    128                         bestMatches.push_back(matches[index.at<int>(i, 0)]);
    129                     }
    130                     Mat result;
    131                     drawMatches(img1, keyImg1, img2, keyImg2, bestMatches, result);
    132                     namedWindow(*itDesc+": "+*itMatcher, WINDOW_AUTOSIZE);
    133                     imshow(*itDesc + ": " + *itMatcher, result);
    134                     // Saved result could be wrong due to bug 4308
    135                     FileStorage fs(*itDesc + "_" + *itMatcher + ".yml", FileStorage::WRITE);
    136                     fs<<"Matches"<<matches;
    137                     vector<DMatch>::iterator it;
    138                     cout<<"**********Match results**********\n";
    139                     cout << "Index \tIndex \tdistance\n";
    140                     cout << "in img1\tin img2\n";
    141                     // Use to compute distance between keyPoint matches and to evaluate match algorithm
    142                     double cumSumDist2=0;
    143                     for (it = bestMatches.begin(); it != bestMatches.end(); it++)
    144                     {
    145                         cout << it->queryIdx << "\t" <<  it->trainIdx << "\t"  <<  it->distance << "\n";
    146                         Point2d p=keyImg1[it->queryIdx].pt-keyImg2[it->trainIdx].pt;
    147                         cumSumDist2=p.x*p.x+p.y*p.y;
    148                     }
    149                     desMethCmp.push_back(cumSumDist2);
    150                     waitKey();
    151                 }
    152                 catch (Exception& e)
    153                     {
    154                     cout << e.msg << endl;
    155                     cout << "Cumulative distance cannot be computed." << endl;
    156                     desMethCmp.push_back(-1);
    157                     }
    158                 }
    159         }
    160         catch (Exception& e)
    161         {
    162             cout << "Feature : " << *itDesc << "\n";
    163             if (itMatcher != typeAlgoMatch.end())
    164             {
    165                 cout << "Matcher : " << *itMatcher << "\n";
    166             }
    167             cout << e.msg << endl;
    168         }
    169     }
    170     int i=0;
    171     cout << "Cumulative distance between keypoint match for different algorithm and feature detector \n\t";
    172     cout << "We cannot say which is the best but we can say results are differents! \n\t";
    173     for (vector<String>::iterator itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); itMatcher++)
    174     {
    175         cout<<*itMatcher<<"\t";
    176     }
    177     cout << "\n";
    178     for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); itDesc++)
    179     {
    180         cout << *itDesc << "\t";
    181         for (vector<String>::iterator itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); itMatcher++, i++)
    182         {
    183             cout << desMethCmp[i]<<"\t";
    184         }
    185         cout<<"\n";
    186     }
    187     return 0;
    188 }
    189