matchmethod_orb_akaze_brisk.cpp 8.04 KB
Newer Older
1 2 3 4
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/highgui.hpp>
5 6 7 8 9 10
#include <vector>
#include <iostream>

using namespace std;
using namespace cv;

11 12 13 14
static void help()
{
    cout << "\n This program demonstrates how to detect compute and match ORB BRISK and AKAZE descriptors \n"
        "Usage: \n"
ValeryTyumen's avatar
ValeryTyumen committed
15
        "  ./matchmethod_orb_akaze_brisk --image1=<image1(../data/basketball1.png as default)> --image2=<image2(../data/basketball2.png as default)>\n"
16 17 18
        "Press a key when image window is active to change algorithm or descriptor";
}

19

20 21

int main(int argc, char *argv[])
22
{
23
    vector<String> typeDesc;
24
    vector<String> typeAlgoMatch;
25
    vector<String> fileName;
26
    // This descriptor are going to be detect and compute
27
    typeDesc.push_back("AKAZE-DESCRIPTOR_KAZE_UPRIGHT");    // see http://docs.opencv.org/trunk/d8/d30/classcv_1_1AKAZE.html
28 29 30 31
    typeDesc.push_back("AKAZE");    // see http://docs.opencv.org/trunk/d8/d30/classcv_1_1AKAZE.html
    typeDesc.push_back("ORB");      // see http://docs.opencv.org/trunk/de/dbf/classcv_1_1BRISK.html
    typeDesc.push_back("BRISK");    // see http://docs.opencv.org/trunk/db/d95/classcv_1_1ORB.html
   // This algorithm would be used to match descriptors see http://docs.opencv.org/trunk/db/d39/classcv_1_1DescriptorMatcher.html#ab5dc5036569ecc8d47565007fa518257
32
    typeAlgoMatch.push_back("BruteForce");
33
    typeAlgoMatch.push_back("BruteForce-L1");
34 35
    typeAlgoMatch.push_back("BruteForce-Hamming");
    typeAlgoMatch.push_back("BruteForce-Hamming(2)");
ValeryTyumen's avatar
ValeryTyumen committed
36 37 38 39 40
    cv::CommandLineParser parser(argc, argv,
        "{ @image1 | ../data/basketball1.png | }"
        "{ @image2 | ../data/basketball2.png | }"
        "{help h ||}");
    if (parser.has("help"))
41 42
    {
        help();
ValeryTyumen's avatar
ValeryTyumen committed
43
        return 0;
44
    }
ValeryTyumen's avatar
ValeryTyumen committed
45 46
    fileName.push_back(parser.get<string>(0));
    fileName.push_back(parser.get<string>(1));
47 48 49 50 51 52 53 54 55 56 57 58
    Mat img1 = imread(fileName[0], IMREAD_GRAYSCALE);
    Mat img2 = imread(fileName[1], IMREAD_GRAYSCALE);
    if (img1.rows*img1.cols <= 0)
        {
        cout << "Image " << fileName[0] << " is empty or cannot be found\n";
        return(0);
        }
    if (img2.rows*img2.cols <= 0)
        {
        cout << "Image " << fileName[1] << " is empty or cannot be found\n";
        return(0);
        }
laurentBerger's avatar
laurentBerger committed
59

60
    vector<double> desMethCmp;
61 62
    Ptr<Feature2D> b;

63
    // Descriptor loop
64
    vector<String>::iterator itDesc;
65
    for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); ++itDesc)
66
    {
67
        Ptr<DescriptorMatcher> descriptorMatcher;
68
        // Match between img1 and img2
69 70
        vector<DMatch> matches;
        // keypoint  for img1 and img2
71
        vector<KeyPoint> keyImg1, keyImg2;
72 73
        // Descriptor for img1 and img2
        Mat descImg1, descImg2;
74
        vector<String>::iterator itMatcher = typeAlgoMatch.end();
75 76 77
        if (*itDesc == "AKAZE-DESCRIPTOR_KAZE_UPRIGHT"){
            b = AKAZE::create(AKAZE::DESCRIPTOR_KAZE_UPRIGHT);
            }
78 79
        if (*itDesc == "AKAZE"){
            b = AKAZE::create();
80
            }
81 82 83 84 85 86
        if (*itDesc == "ORB"){
            b = ORB::create();
        }
        else if (*itDesc == "BRISK"){
            b = BRISK::create();
        }
87 88
        try
        {
89
            // We can detect keypoint with detect method
90
            b->detect(img1, keyImg1, Mat());
91
            // and compute their descriptors with method  compute
92
            b->compute(img1, keyImg1, descImg1);
93
            // or detect and compute descriptors in one step
94
            b->detectAndCompute(img2, Mat(),keyImg2, descImg2,false);
95
            // Match method loop
96
            for (itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); ++itMatcher){
97
                descriptorMatcher = DescriptorMatcher::create(*itMatcher);
98
                if ((*itMatcher == "BruteForce-Hamming" || *itMatcher == "BruteForce-Hamming(2)") && (b->descriptorType() == CV_32F || b->defaultNorm() <= NORM_L2SQR))
99
                {
100 101 102
                    cout << "**************************************************************************\n";
                    cout << "It's strange. You should use Hamming distance only for a binary descriptor\n";
                    cout << "**************************************************************************\n";
103
                }
104 105 106 107 108 109
                if ((*itMatcher == "BruteForce" || *itMatcher == "BruteForce-L1") && (b->defaultNorm() >= NORM_HAMMING))
                {
                    cout << "**************************************************************************\n";
                    cout << "It's strange. You shouldn't use L1 or L2 distance for a binary descriptor\n";
                    cout << "**************************************************************************\n";
                }
laurentBerger's avatar
laurentBerger committed
110
                try
111
                {
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
                    descriptorMatcher->match(descImg1, descImg2, matches, Mat());
                    // Keep best matches only to have a nice drawing.
                    // We sort distance between descriptor matches
                    Mat index;
                    int nbMatch=int(matches.size());
                    Mat tab(nbMatch, 1, CV_32F);
                    for (int i = 0; i<nbMatch; i++)
                    {
                        tab.at<float>(i, 0) = matches[i].distance;
                    }
                    sortIdx(tab, index, SORT_EVERY_COLUMN + SORT_ASCENDING);
                    vector<DMatch> bestMatches;
                    for (int i = 0; i<30; i++)
                    {
                        bestMatches.push_back(matches[index.at<int>(i, 0)]);
                    }
                    Mat result;
                    drawMatches(img1, keyImg1, img2, keyImg2, bestMatches, result);
                    namedWindow(*itDesc+": "+*itMatcher, WINDOW_AUTOSIZE);
                    imshow(*itDesc + ": " + *itMatcher, result);
                    // Saved result could be wrong due to bug 4308
                    FileStorage fs(*itDesc + "_" + *itMatcher + ".yml", FileStorage::WRITE);
                    fs<<"Matches"<<matches;
                    vector<DMatch>::iterator it;
                    cout<<"**********Match results**********\n";
                    cout << "Index \tIndex \tdistance\n";
                    cout << "in img1\tin img2\n";
                    // Use to compute distance between keyPoint matches and to evaluate match algorithm
                    double cumSumDist2=0;
141
                    for (it = bestMatches.begin(); it != bestMatches.end(); ++it)
142 143 144 145 146 147 148
                    {
                        cout << it->queryIdx << "\t" <<  it->trainIdx << "\t"  <<  it->distance << "\n";
                        Point2d p=keyImg1[it->queryIdx].pt-keyImg2[it->trainIdx].pt;
                        cumSumDist2=p.x*p.x+p.y*p.y;
                    }
                    desMethCmp.push_back(cumSumDist2);
                    waitKey();
149
                }
150 151
                catch (const Exception& e)
                {
152 153
                    cout << e.msg << endl;
                    cout << "Cumulative distance cannot be computed." << endl;
154
                    desMethCmp.push_back(-1);
155
                }
156
            }
157
        }
158
        catch (const Exception& e)
159
        {
160 161
            cout << "Feature : " << *itDesc << "\n";
            if (itMatcher != typeAlgoMatch.end())
162
            {
163
                cout << "Matcher : " << *itMatcher << "\n";
164
            }
165
            cout << e.msg << endl;
166 167
        }
    }
168 169
    int i=0;
    cout << "Cumulative distance between keypoint match for different algorithm and feature detector \n\t";
luz.paz's avatar
luz.paz committed
170
    cout << "We cannot say which is the best but we can say results are different! \n\t";
171
    for (vector<String>::iterator itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); ++itMatcher)
172 173 174 175
    {
        cout<<*itMatcher<<"\t";
    }
    cout << "\n";
176
    for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); ++itDesc)
177 178
    {
        cout << *itDesc << "\t";
179
        for (vector<String>::iterator itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); ++itMatcher, ++i)
180 181 182 183 184
        {
            cout << desMethCmp[i]<<"\t";
        }
        cout<<"\n";
    }
185 186
    return 0;
}