title: Strange result of SURF_GPU and BruteForceMatcher_GPU with knnMatch
body: <p>OpenCV 2.4.5, CUDA 5.0</p>
  
  <p>I tried to transfer my SURF matcher from the CPU to the GPU and got such a strange result. I use knnMatch and findHomography + perspectiveTransform together with my function, which checks the corners of the bounding box for the result to more precision.</p>
  
  <p><strong>GPU part:</strong></p>
  
  <pre><code>const int baseImagesSize = baseImages.size();
  SURF_GPU surf(1500);
  surf.extended = false; 
  
  GpuMat keypoints_test_GPU, descriptors_test_GPU;
  surf(frame, GpuMat(), keypoints_test_GPU, descriptors_test_GPU);
  vector&lt;float&gt; descriptors_test_CPU;
  surf.downloadDescriptors(descriptors_test_GPU, descriptors_test_CPU);
  Mat descriptors_test_CPU_Mat(descriptors_test_CPU);
  vector&lt;Point2f&gt; objs_corners(4);
  BruteForceMatcher_GPU&lt; L2&lt;float&gt; &gt; matcher;
  
  vector&lt;KeyPoint&gt; keypoints_test_CPU;
  surf.downloadKeypoints(keypoints_test_GPU, keypoints_test_CPU);
  
  for (int i = 0; i &lt; baseImagesSize; ++i)
  {
      //Get the corners from the object
      objs_corners[0] = cvPoint(0,0);
      objs_corners[1] = cvPoint( baseImages[i].cols, 0 );
      objs_corners[2] = cvPoint( baseImages[i].cols, baseImages[i].rows );
      objs_corners[3] = cvPoint( 0, baseImages[i].rows );
  
      //cout&lt;&lt;endl&lt;&lt;objs_corners[0]&lt;&lt;" "&lt;&lt;objs_corners[1]&lt;&lt;" "&lt;&lt;objs_corners[2]&lt;&lt;" "&lt;&lt;objs_corners[3]&lt;&lt;endl;
      GpuMat keypoints_tmp_GPU, descriptors_tmp_GPU;
      surf(baseImages[i], GpuMat(), keypoints_tmp_GPU, descriptors_tmp_GPU);
      GpuMat trainIdx, distance;
  
      vector&lt; vector&lt;DMatch&gt; &gt; matches;
      matcher.knnMatch(descriptors_test_GPU, descriptors_tmp_GPU, matches, 2);
      vector&lt;KeyPoint&gt; keypoints_tmp_CPU;
  
      surf.downloadKeypoints(keypoints_tmp_GPU, keypoints_tmp_CPU);
      std::vector&lt;DMatch &gt; good_matches;
  
      for(int k = 0; k &lt; min(descriptors_test_CPU_Mat.rows-1,(int) matches.size()); k++) //THIS LOOP IS SENSITIVE TO SEGFAULTS
      {
          if((matches[k][0].distance &lt; 0.6*(matches[k][1].distance)) &amp;&amp; ((int) matches[k].size()&lt;=2 &amp;&amp; (int) matches[k].size()&gt;0))
          {
              good_matches.push_back(matches[k][0]);
          }
      }
  
      vector&lt;Point2f&gt; obj;
      vector&lt;Point2f&gt; scene;
      vector&lt;Point2f&gt; scene_corners(4);
      Mat H;
      Mat img (baseImages[i]), img_matches, frame_cpu (frame);
      std::ostringstream o_stream;
      o_stream&lt;&lt;"Logo_save/"&lt;&lt;baseImagesNames[i];
      try
      {
          drawMatches( img, keypoints_tmp_CPU, frame_cpu, keypoints_test_CPU, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector&lt;char&gt;(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
          imwrite(o_stream.str(),img_matches);
      }
      catch(...)
      {
          cout&lt;&lt;"Error in drawMatches name: "&lt;&lt; baseImagesNames[i]&lt;&lt;endl;
      }
  
      if (good_matches.size() &gt;= 4)
      {
          for( int k = 0; k &lt; good_matches.size(); k++ )
          {
              //Get the keypoints from the good matches
              obj.push_back( (keypoints_tmp_CPU)[ good_matches[k].queryIdx ].pt );
              scene.push_back( keypoints_test_CPU[ good_matches[k].trainIdx ].pt );
          }
  
          cout&lt;&lt;good_matches.size()&lt;&lt;" "&lt;&lt;baseImagesNames[i]&lt;&lt;endl;
          H = findHomography( obj, scene, CV_RANSAC);
          perspectiveTransform( objs_corners, scene_corners, H);
          bool falseDetect = isSmallAngle(scene_corners);
          //cout&lt;&lt; falseDetect&lt;&lt; endl;
          if(!falseDetect)
          {
              cout&lt;&lt;"DETECT "&lt;&lt;baseImagesNames[i]&lt;&lt;endl;
          }
  
  
      }
  
      matcher.clear();
  }
  </code></pre>
  
  <p><strong>Bad result on GPU (MIN_HESSIAN==1500):</strong>
  <img src="https://i.stack.imgur.com/ZPygV.jpg" alt="surf(1500)"></p>
  
  <p><strong>Bad result on GPU (MIN_HESSIAN==400):</strong>
  <img src="https://i.stack.imgur.com/MVKLH.jpg" alt="surf(400)"></p>
  
  <p><strong>CPU part:</strong></p>
  
  <pre><code>SurfFeatureDetector detector( MIN_HESSIAN );//MIN_HESSIAN==400
  const int baseImagesSize = baseImages.size();
  vector&lt; vector&lt;KeyPoint&gt; &gt; kp_objects(baseImagesSize);
  
  //Calculate descriptors (feature vectors)
  SurfDescriptorExtractor extractor;
  vector&lt;Mat&gt; des_objects(baseImagesSize);
  FlannBasedMatcher matcher;
  //namedWindow("SURF feature detector");
  vector&lt; vector&lt;Point2f&gt; &gt; objs_corners(baseImagesSize,vector&lt;Point2f&gt;(4));
  
  for (int i = 0; i &lt; baseImagesSize; ++i)
  {
      detector.detect(baseImages[i], kp_objects[i]);
      extractor.compute(baseImages[i], kp_objects[i], des_objects[i]);
  
      //Get the corners from the object
      (objs_corners[i])[0] = cvPoint(0,0);
      (objs_corners[i])[1] = cvPoint( baseImages[i].cols, 0 );
      (objs_corners[i])[2] = cvPoint( baseImages[i].cols, baseImages[i].rows );
      (objs_corners[i])[3] = cvPoint( 0, baseImages[i].rows );
  }
  
  Mat des_image;
  std::vector&lt;KeyPoint&gt; kp_image;
  Mat image;
  cvtColor(frame, image, CV_RGB2GRAY);
  detector.detect( image, kp_image );
  extractor.compute( image, kp_image, des_image );
  
  for (int i = 0; i &lt; baseImagesSize; ++i)
  {
      Mat img_matches;
      std::vector&lt;vector&lt;DMatch &gt; &gt; matches;
      std::vector&lt;DMatch &gt; good_matches;
      std::vector&lt;Point2f&gt; obj;
      std::vector&lt;Point2f&gt; scene;
      std::vector&lt;Point2f&gt; scene_corners(4);
      Mat H;
      matcher.knnMatch(des_objects[i], des_image, matches, 2);
  
      for(int k = 0; k &lt; min(des_image.rows-1,(int) matches.size()); k++) //THIS LOOP IS SENSITIVE TO SEGFAULTS
      {
          if((matches[k][0].distance &lt; 0.6*(matches[k][4].distance)) &amp;&amp; ((int) matches[k].size()&lt;=2 &amp;&amp; (int) matches[k].size()&gt;0))
          {
              good_matches.push_back(matches[k][0]);
          }
      }
  
      //Draw only "good" matches
      std::ostringstream o_stream;
      o_stream&lt;&lt;"Logo_save/"&lt;&lt;baseImagesNames[i];
      try
      {
          drawMatches( baseImages[i], kp_objects[i], image, kp_image, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector&lt;char&gt;(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
          imwrite(o_stream.str(),img_matches);
      }
      catch(...)
      {
          cout&lt;&lt;"Error in drawMatches name: "&lt;&lt; baseImagesNames[i]&lt;&lt;endl;
      }
  
      if (good_matches.size() &gt;= 4)
      {
          for( int k = 0; k &lt; good_matches.size(); k++ )
          {
              //Get the keypoints from the good matches
              obj.push_back( (kp_objects[i])[ good_matches[k].queryIdx ].pt );
              scene.push_back( kp_image[ good_matches[k].trainIdx ].pt );
          }
  
          H = findHomography( obj, scene, CV_RANSAC);
          perspectiveTransform( objs_corners[i], scene_corners, H);
          bool falseDetect = isSmallAngle(scene_corners);
          if(!falseDetect)
          {
              cout&lt;&lt;"DETECT "&lt;&lt;baseImagesNames[i]&lt;&lt;endl;
          }
  
  
      }
  }
  </code></pre>
  
  <p><strong>Good result on CPU (MIN_HESSIAN==400):</strong>
  <img src="https://i.stack.imgur.com/EMzui.jpg" alt="good result on CPU:"></p>