matchmethod_orb_akaze_brisk.cpp 8.0 KB

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