title: Using OpenCV Cuda ORB feature detector
body: <p>I have an application where I am receiving a stream of images within which I want to monitor detected features within a set ROI.  This is accomplished using an ORB detector.  In the first image, I use the detector to find "reference" keypoints and descriptors for the given ROI.  For subsequent images, I find "test" keypoints and descriptors for the same ROI.  I then use a knn matcher to find matches between to reference and test descriptors.  Finally, I attempt to find the "best" matches, add the associated keypoints to a "matched keypoints" collection, and then calculate a "match intensity".  This match intensity is intended to indicate how well the keypoints found in the reference image match the keypoints in the test image.</p>
  
  <p>I have a few questions:</p>
  
  <p>1 - is this a valid use of a feature detector?  I understand that a simple template matching might give me similar results, but I was hoping to avoid issues with slight changes in lighting.  </p>
  
  <p>2 - am I screen my matches properly for "good" matches, and then am I getting the correctly associated keypoint for that match?</p>
  
  <p>3 - my code seems to work as is, however, if I try move to the async versions of the OpenCV calls using streams, I get an exception:
  "invalid resource handle in function cv::cuda::GpuMat::setTo" which happens in a call to ORB_Impl::buildScalePyramids (that was called from ORB_Impl::detectAndComputeAsync).  See the async version of my "NewFrame" function below.  This just makes me think I'm not getting all of this set up properly.</p>
  
  <p>Here is my code:</p>
  
  <pre><code>void Matcher::Matcher()
  {
      // create ORB detector and descriptor matcher
      m_b = cuda::ORB::create(500, 1.2f, 8, 31, 0, 2, 0, 31, 20, true);   
      m_descriptorMatcher =       cv::cuda::DescriptorMatcher::createBFMatcher(cv::NORM_HAMMING); 
  }
  
  void Matcher::Configure(int imageWidth, int imageHeight, int roiX, int roiY, int roiW, int roiH)
  {
      // set member variables
      m_imageWidth = imageWidth;
      m_imageHeight = imageHeight;
      m_roiX = roiX;
      m_roiY = roiY;
      m_roiW = roiW;
      m_roiH = roiH;
  
      m_GpuRefSet = false; // set flag indicating reference not yet set
  
      // create mask for specified ROI
      m_mask = GpuMat(imageHeight,imageWidth, CV_8UC1, Scalar::all(0));
      cv::Rect rect = cv::Rect(m_roiX, m_roiY, m_roiW, m_roiH);
      m_mask(rect).setTo(Scalar::all(255));       
  }
  
  
  double Matcher::NewFrame(void *pImagedata)
  {
      // pImagedata = pointer to BGRA byte array
      // m_imageHeight and m_imageWidth have already been set
      // m_b is a pointer to the ORB detector
  
      if (!m_GpuRefSet)
      { // 1st time through (after call to Matcher::Configure), set reference keypoints and descriptors
  
          cv::cuda::GpuMat mat1(m_imageHeight, m_imageWidth, CV_8UC4, pImagedata);  // put image data into GpuMat
  
          cv::cuda::cvtColor(mat1, m_refImage, CV_BGRA2GRAY); // convert to grayscale as required by ORB
  
          m_keyRef.clear(); // clear the vector&lt;KeyPoint&gt;, keypoint vector for reference image
  
          m_b-&gt;detectAndCompute(m_refImage, m_mask, m_keyRef, m_descRef, false); // detect keypoints and compute descriptors
  
          m_GpuRefSet = true;     
      }
  
      cv::cuda::GpuMat mat2(m_imageHeight, m_imageWidth, CV_8UC4, pImagedata);  // put image data into GpuMat
  
      cv::cuda::cvtColor(mat2, m_testImage, CV_BGRA2GRAY, 0);  // convert to grayscale as required by ORB
  
      m_keyTest.clear(); // clear vector&lt;KeyPoint&gt;, keypoint vector for test image
  
      m_b-&gt;detectAndCompute(m_testImage, m_mask, m_keyTest, m_descTest, false);  // detect keypoints and compute descriptors
  
  
      double value = 0.0f;  // used to store return value ("match intensity")
  
          // calculate best match for each descriptor
          if (m_descTest.rows &gt; 0)
          {   
              m_goodKeypoints.clear(); // clear vector of "good" KeyPoints, vector&lt;KeyPoint&gt; 
  
              m_descriptorMatcher-&gt;knnMatch(m_descTest, m_descRef, m_matches, 2, noArray());  // find matches
  
              // examine all matches, and collect the KeyPoints whose match distance mets given criteria
              for (int i = 0; i&lt;m_matches.size(); i++){
                  if (m_matches[i][0].distance &lt; m_matches[i][1].distance * m_nnr){ // m_nnr = nearest neighbor ratio (typically 0.6 - 0.8)
                      m_goodKeypoints.push_back(m_keyRef.at(m_matches[i][0].trainIdx));  // not sure if getting the correct keypoint here
                  }
              }
  
              // calculate "match intensity", i.e. percent of the keypoints found in the reference image that are also in the test image
              value = ((double)m_goodKeypoints.size()) / ((double)m_keyRef.size());
          }
          else
          {
              value = 0.0f;
          }
  
      return value;
  }
  </code></pre>
  
  <p>And here's the stream/async version of the NewFrame function that fails:</p>
  
  <pre><code>double Matcher::NewFrame(void *pImagedata)
  {
      if (m_b.empty()) return 0.0f;
  
      if (!m_GpuRefSet)
      {
          try
          {
              cv::cuda::GpuMat mat1(m_imageHeight, m_imageWidth, CV_8UC4, pImagedata);
  
              cv::cuda::cvtColor(mat1, m_refImage, CV_BGRA2GRAY);
  
              m_keyRef.clear();
  
              m_b-&gt;detectAndComputeAsync(m_refImage, m_mask, m_keyRef, m_descRef, false,m_stream);  // FAILS HERE
  
              m_stream.waitForCompletion();
  
              m_GpuRefSet = true;
          }
          catch (Exception e)
          {
              string msg = e.msg;
          }
  
      }
  
      cv::cuda::GpuMat mat2(m_imageHeight, m_imageWidth, CV_8UC4, pImagedata);
  
      cv::cuda::cvtColor(mat2, m_testImage, CV_BGRA2GRAY, 0, m_stream);
  
      m_keyTest.clear();
  
      m_b-&gt;detectAndComputeAsync(m_testImage, m_mask, m_keyTest, m_descTest, false, m_stream);
  
      m_stream.waitForCompletion();
  
      double value = 0.0f;
  
      // calculate best match for each descriptor
  
      if (m_descTest.rows &gt; 0)
      {
          m_goodKeypoints.clear();
          m_descriptorMatcher-&gt;knnMatchAsync(m_descTest, m_descRef, m_matches, 2, noArray(), m_stream);
  
          m_stream.waitForCompletion(); 
  
          for (int i = 0; i&lt;m_matches.size(); i++){
              if (m_matches[i][0].distance &lt; m_matches[i][1].distance * m_nnr) // m_nnr = nearest neighbor ratio
              {
                  m_goodKeypoints.push_back(m_keyRef.at(m_matches[i][0].trainIdx));
              }
          }
  
          value = ((double)m_goodKeypoints.size()) / ((double)m_keyRef.size());
      }
      else
      {
          value = 0.0f;
      }
  
  
      if (value &gt; 1.0f) value = 1.0f;
  
      return value;
  }
  </code></pre>
  
  <p>Any suggestions/advice would be appreciated.</p>
  
  <p>Thanks!!</p>