title: OpenCV Sift/Surf/Orb : drawMatch function is not working well
body: <p>I use Sift/Surf and ORB but sometimes i have a problem with the drawMatch function.</p>
  
  <p>Here the error :</p>
  
  <blockquote>
    <p>OpenCV Error: Assertion failed (i2 >= 0 &amp;&amp; i2 &lt; static_cast(keypoints2.size())) in drawMatches, file /home/opencv-2.4.6.1/modules/features2d/src/draw.cpp, line 208
    terminate called after throwing an instance of 'cv::Exception'
      what():  /home/opencv-2.4.6.1/modules/features2d/src/draw.cpp:208: error: (-215) i2 >= 0 &amp;&amp; i2 &lt; static_cast(keypoints2.size()) in function drawMatche</p>
  </blockquote>
  
  <p>The code :</p>
  
  <pre><code>drawMatchPoints(img1,keypoints_img1,img2,keypoints_img2,matches);
  </code></pre>
  
  <p>I tried to invert img 1,keypoints_img1 with img2 and keypoints_img2 like that :</p>
  
  <pre><code>drawMatchPoints(img2,keypoints_img2,img1,keypoints_img1,matches);
  </code></pre>
  
  <p><strong>Corresponding to my function who is doing an homography :</strong></p>
  
  <pre><code>void drawMatchPoints(cv::Mat image1,std::vector&lt;KeyPoint&gt; keypoints_img1,
                                        cv::Mat image2,std::vector&lt;KeyPoint&gt; keypoints_img2,std::vector&lt;cv::DMatch&gt; matches){
  
      cv::Mat img_matches;
      drawMatches( image1, keypoints_img1, image2, keypoints_img2,
                           matches, img_matches, Scalar::all(-1), Scalar::all(-1),
                           vector&lt;char&gt;(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
              std::cout &lt;&lt; "Number of good matching " &lt;&lt; (int)matches.size() &lt;&lt; "\n" &lt;&lt; endl;
  
  
  
              //-- Localize the object
              std::vector&lt;Point2f&gt; obj;
              std::vector&lt;Point2f&gt; scene;
  
              for( int i = 0; i &lt; matches.size(); i++ )
              {
                //-- Get the keypoints from the good matches
                obj.push_back( keypoints_img1[ matches[i].queryIdx ].pt );
                scene.push_back( keypoints_img2[matches[i].trainIdx ].pt );
              }
  
              Mat H = findHomography( obj, scene, CV_RANSAC );
              std::cout &lt;&lt; "Size of homography " &lt;&lt; *H.size &lt;&lt; std::endl ;
  
              //-- Get the corners from the image_1 ( the object to be "detected" )
              std::vector&lt;Point2f&gt; obj_corners(4);
              obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( image1.cols, 0 );
              obj_corners[2] = cvPoint( image1.cols, image1.rows ); obj_corners[3] = cvPoint( 0, image1.rows );
              std::vector&lt;Point2f&gt; scene_corners(4);
  
  
              perspectiveTransform( obj_corners, scene_corners, H);
  
  
              //-- Draw lines between the corners (the mapped object in the scene - image_2 )
              line( img_matches, scene_corners[0] + Point2f( image1.cols, 0), scene_corners[1] + Point2f( image1.cols, 0), Scalar(0, 255, 0), 4 );
              line( img_matches, scene_corners[1] + Point2f( image1.cols, 0), scene_corners[2] + Point2f( image1.cols, 0), Scalar( 0, 255, 0), 4 );
              line( img_matches, scene_corners[2] + Point2f( image1.cols, 0), scene_corners[3] + Point2f( image1.cols, 0), Scalar( 0, 255, 0), 4 );
              line( img_matches, scene_corners[3] + Point2f( image1.cols, 0), scene_corners[0] + Point2f( image1.cols, 0), Scalar( 0, 255, 0), 4 );
  
              //-- Show detected matches
              cv::imshow( "Good Matches &amp; Object detection", img_matches );
              cv::waitKey(5000);
  </code></pre>
  
  <p>}</p>
  
  <p>But i have still the error !</p>
  
  <p>I have noticed that the error happened when the size of my keypoints_img1 <strong>is lower</strong> than the size of my keypoints_img2 :</p>
  
  <blockquote>
    <p>Size keyPoint1 : 244
    - Size keyPoint2 : 400</p>
  </blockquote>
  
  <p>So if i invert the loading of my two picture, that works but i can't now in advance if my first picture will have more keypoints that my second picture...</p>
  
  <p>My code (the most important step) in order to create the features :</p>
  
  <pre><code>init_Sift(400,5,0.04,25,1.6);
  void init_Sift(int nf,int nOctaveL,double contrastThresh, double edgeThresh,double sigma){
  this-&gt;nfeatureSift=nf;
  this-&gt;nOctaveLayerSift=nOctaveL;
  this-&gt;contrastThresholdSift=contrastThresh;
  this-&gt;edgeThresholdSift=edgeThresh;
  this-&gt;sigmaSift=sigma;}
  
  
  
   cv::FeatureDetector* detector=new SiftFeatureDetector(nfeatureSift,nOctaveLayerSift,contrastThresholdSift,edgeThresholdSift,sigmaSift);
  cv::DescriptorExtractor* extractor=new SiftDescriptorExtractor
  
  extractor-&gt;compute( image, keypoints, descriptors );
  </code></pre>
  
  <p>The matching part :</p>
  
  <pre><code>    std::cout &lt;&lt; "Type of matcher : " &lt;&lt; type_of_matcher &lt;&lt; std::endl;
  if (type_of_matcher=="FLANN" || type_of_matcher=="BF"){
      std::vector&lt;KeyPoint&gt; keypoints_img1 = keyfeatures.compute_Keypoints(img1);
      std::vector&lt;KeyPoint&gt; keypoints_img2 = keyfeatures.compute_Keypoints(img2);
  
      cv::Mat descriptor_img1 = keyfeatures.compute_Descriptors(img1);
      cv::Mat descriptor_img2 = keyfeatures.compute_Descriptors(img2);
  
      std::cout &lt;&lt; "Size keyPoint1 " &lt;&lt; keypoints_img1.size() &lt;&lt; "\n" &lt;&lt; std::endl;
      std::cout &lt;&lt; "Size keyPoint2 " &lt;&lt; keypoints_img2.size() &lt;&lt; "\n" &lt;&lt; std::endl;
  
      //Flann with sift or surf
      if (type_of_matcher=="FLANN"){
          Debug::info("USING Matcher FLANN");
          fLmatcher.match(descriptor_img1,descriptor_img2,matches);
  
          double max_dist = 0; double min_dist = 100;
  
          //-- Quick calculation of max and min distances between keypoints
          for( int i = 0; i &lt; descriptor_img1.rows; i++ ){
              double dist = matches[i].distance;
              if( dist &lt; min_dist ) min_dist = dist;
              if( dist &gt; max_dist ) max_dist = dist;
           }
  
          std::vector&lt; DMatch &gt; good_matches;
  
            for( int i = 0; i &lt; descriptor_img1.rows; i++ )
            { if( matches[i].distance &lt;= max(2*min_dist, 0.02) )
              { good_matches.push_back( matches[i]); }
            }
  
            std::cout &lt;&lt; "Size of good match : " &lt;&lt;  (int)good_matches.size() &lt;&lt; std::endl;
            //-- Draw only "good" matches
            if (!good_matches.empty()){
                drawMatchPoints(img1,keypoints_img1,img2,keypoints_img2,good_matches);
  
            }
            else {
                Debug::error("Flann Matcher : Pas de match");
                cv::Mat img_matches;
                drawMatches( img1, keypoints_img1, img2, keypoints_img2,
                                  matches, img_matches, Scalar::all(-1), Scalar::all(-1),
                                  vector&lt;char&gt;(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
                cv::imshow( "No match", img_matches );
                cv::waitKey(5000);
            }
  
      }
      //BruteForce with sift or surf
      else if (type_of_matcher=="BF"){
          Debug::info("USING Matcher Brute Force");
  
          bFmatcher.match(descriptor_img1,descriptor_img2,matches);
          if (!matches.empty()){
              std::nth_element(matches.begin(),//Initial position
                               matches.begin()+24, //Position  of the sorted element
                               matches.end());//End position
              matches.erase(matches.begin()+25,matches.end());
  
              drawMatchPoints(img1,keypoints_img1,img2,keypoints_img2,matches);
              //drawMatchPoints(img2,keypoints_img2,img1,keypoints_img1,matches);
          }
          else {
              Debug::error("Brute Force matcher  : Pas de match");
              cv::Mat img_matches;
              drawMatches( img1, keypoints_img1, img2, keypoints_img2,
                                matches, img_matches, Scalar::all(-1), Scalar::all(-1),
                                vector&lt;char&gt;(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
              cv::imshow( "No match", img_matches );
              cv::waitKey(5000);
  
          }
  
  }
  </code></pre>
  
  <p>Do you have any suggestions or advises ? </p>
  
  <p><strong>EDIT :</strong> i solved my problem.
  I had a c++ problem, because i had two classes . One about matching and another about finding keyFeature. I have wrote on my .h std::vector and the same for descriptors. </p>
  
  <pre><code>class keyFeatures{
  
  public:
  ...   
  std::vector&lt;keyPoint&gt; keypoints;
  ...
  </code></pre>
  
  <p>I delete this attribute and i did a function that take in argument std::vector keypoints </p>
  
  <pre><code>cv::Mat descriptor_img1 = keyfeatures.compute_Descriptors(img1,keypoints_img1);
  </code></pre>
  
  <p>instead of </p>
  
  <pre><code>cv::Mat descriptor_img1 = keyfeatures.compute_Descriptors(img1);
  </code></pre>
  
  <p>I think there was a conflict when i did the matching...
  But i don't know why i shouldn't have to write it on my .h and do a local parameter on my function.</p>
  
  <p>Thank you !</p>