From 09e9e8ad9fa4253fae623db21dd7df397421074c Mon Sep 17 00:00:00 2001 From: laurentBerger Date: Mon, 4 May 2015 10:36:24 +0200 Subject: [PATCH] I have modified source file and add a chart to have distance between keypoint for decriptor function og matching algorithm My english is not good so you can change some words in my comment --- samples/cpp/matchmethod_orb_akaze_brisk.cpp | 126 +++++++++++++++----- 1 file changed, 98 insertions(+), 28 deletions(-) diff --git a/samples/cpp/matchmethod_orb_akaze_brisk.cpp b/samples/cpp/matchmethod_orb_akaze_brisk.cpp index 6711ba34b4..be6bf3553c 100644 --- a/samples/cpp/matchmethod_orb_akaze_brisk.cpp +++ b/samples/cpp/matchmethod_orb_akaze_brisk.cpp @@ -5,37 +5,73 @@ using namespace std; using namespace cv; +static void help() +{ + cout << "\n This program demonstrates how to detect compute and match ORB BRISK and AKAZE descriptors \n" + "Usage: \n" + " ./matchmethod_orb_akaze_brisk \n" + "Press a key when image window is active to change algorithm or descriptor"; +} + -int main(void) + +int main(int argc, char *argv[]) { + vector typeDesc; vector typeAlgoMatch; + vector fileName; + help(); + // This descriptor are going to be detect and compute + 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 typeAlgoMatch.push_back("BruteForce"); + typeAlgoMatch.push_back("BruteForce-L1"); typeAlgoMatch.push_back("BruteForce-Hamming"); typeAlgoMatch.push_back("BruteForce-Hamming(2)"); + if (argc==1) + { + fileName.push_back("../data/basketball1.png"); + fileName.push_back("../data/basketball2.png"); + } + else if (argc==3) + { + fileName.push_back(argv[1]); + fileName.push_back(argv[2]); + } + else + { + help(); + return(0); + } + 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); + } - vector typeDesc; - typeDesc.push_back("AKAZE"); - typeDesc.push_back("ORB"); - typeDesc.push_back("BRISK"); - - String dataFolder("../data/"); - vector fileName; - fileName.push_back("basketball1.png"); - fileName.push_back("basketball2.png"); - - Mat img1 = imread(dataFolder+fileName[0], IMREAD_GRAYSCALE); - Mat img2 = imread(dataFolder+fileName[1], IMREAD_GRAYSCALE); - + vector desMethCmp; Ptr b; + // Descriptor loop vector::iterator itDesc; -// Descriptor loop - for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); itDesc++){ + for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); itDesc++) + { Ptr descriptorMatcher; - vector matches; /* keyImg1; /* keyImg2; /* matches; + // keypoint for img1 and img2 + vector keyImg1, keyImg2; + // Descriptor for img1 and img2 + Mat descImg1, descImg2; vector::iterator itMatcher = typeAlgoMatch.end(); if (*itDesc == "AKAZE"){ b = AKAZE::create(); @@ -47,23 +83,31 @@ int main(void) b = BRISK::create(); } try { + // We can detect keypoint with detect method b->detect(img1, keyImg1, Mat()); + // and compute their descriptors with method compute b->compute(img1, keyImg1, descImg1); + // or detect and compute descriptors in one step b->detectAndCompute(img2, Mat(),keyImg2, descImg2,false); - // Match method loop - for (itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); itMatcher++){ + // Match method loop + for (itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); itMatcher++){ descriptorMatcher = DescriptorMatcher::create(*itMatcher); descriptorMatcher->match(descImg1, descImg2, matches, Mat()); - // Keep best matches only to have a nice drawing + // 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(i, 0) = matches[i].distance; + } sortIdx(tab, index, SORT_EVERY_COLUMN + SORT_ASCENDING); vector bestMatches; for (int i = 0; i<30; i++) + { bestMatches.push_back(matches[index.at(i, 0)]); + } Mat result; drawMatches(img1, keyImg1, img2, keyImg2, bestMatches, result); namedWindow(*itDesc+": "+*itMatcher, WINDOW_AUTOSIZE); @@ -71,19 +115,45 @@ int main(void) FileStorage fs(*itDesc+"_"+*itMatcher+"_"+fileName[0]+"_"+fileName[1]+".xml", FileStorage::WRITE); fs<<"Matches"<::iterator it; - cout << "Index \tIndex \tindex \tdistance\n"; - cout << "in img1\tin img2\timage\t\n"; - for (it = matches.begin(); it != matches.end(); it++) - cout << it->queryIdx << "\t" << it->trainIdx << "\t" << it->imgIdx << "\t" << it->distance<<"\n"; + cout<<"**********Match results**********\n"; + cout << "Index \tIndex \tdistance\n"; + cout << "in img1\tin img2\n"; + double cumSumDist2=0; // Use to compute distance between keyPoint matches and to evaluate match algorithm + for (it = bestMatches.begin(); it != bestMatches.end(); it++) + { + 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(); } } - catch (Exception& e){ + catch (Exception& e) + { cout << "Feature : " << *itDesc << "\n"; if (itMatcher != typeAlgoMatch.end()) + { cout << "Matcher : " << *itMatcher << "\n"; + } cout<::iterator itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); itMatcher++) + { + cout<<*itMatcher<<"\t"; + } + cout << "\n"; + for (itDesc = typeDesc.begin(); itDesc != typeDesc.end(); itDesc++) + { + cout << *itDesc << "\t"; + for (vector::iterator itMatcher = typeAlgoMatch.begin(); itMatcher != typeAlgoMatch.end(); itMatcher++, i++) + { + cout << desMethCmp[i]<<"\t"; + } + cout<<"\n"; + } return 0; }