【问题标题】:Error matching with ORB in Android在 Android 中与 ORB 匹配时出错
【发布时间】:2017-01-24 16:01:26
【问题描述】:

我的代码运行良好,但是当它提取关键点时,这两个图像的匹配度很差。 在这里你可以找到我的代码,但是我不知道如何在JAVA Android中绘制好的匹配

 descriptors = new Mat();
        keypoints = new MatOfKeyPoint();
        detector = FeatureDetector.create(FeatureDetector.ORB);
        detector.detect(img1, keypoints);
        descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
        descriptor.compute(img1, keypoints, descriptors);
        matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
     ColorDetection.cvt_YUVtoRGBtoHSV(mYuv,mGraySubmat);
          MatOfKeyPoint mKeyPoints = new MatOfKeyPoint();
        MatOfDMatch  matches = new MatOfDMatch();

          detector.detect(mGraySubmat, mKeyPoints);
          descriptor.compute(mGraySubmat, mKeyPoints, mIntermediateMat);

        matcher.match(mIntermediateMat,descriptors,matches);
        mIntermediateMat2.create(resultSize, CvType.CV_8UC1);
        Features2d.drawMatches(img1, keypoints, mGraySubmat, mKeyPoints, matches, 
                mIntermediateMat2,GREEN, RED,  MATCH_MASK, Features2d.NOT_DRAW_SINGLE_POINTS);

          Imgproc.resize(mIntermediateMat2, mIntermediateMat2, mRgba.size());
          Imgproc.cvtColor(mIntermediateMat2, mRgba, Imgproc.COLOR_RGBA2BGRA, 4);
     Utils.matToBitmap(mRgba, bmp);

      DMatch dm[] = matches.toArray();
          List<Point> lp1 = new ArrayList<Point>(dm.length);
          List<Point> lp2 = new ArrayList<Point>(dm.length);
          KeyPoint tkp[] = keypoints.toArray();
          KeyPoint qkp[] = mKeyPoints.toArray();
          for (int i = 0; i < dm.length; i++) {
              DMatch dma = dm[i];
              lp1.add(tkp[dma.trainIdx].pt);
              lp2.add(qkp[dma.queryIdx].pt);
          }
          MatOfPoint2f pointsPrev = new MatOfPoint2f(lp1.toArray(new Point[0]));
          MatOfPoint2f pointsAct  = new MatOfPoint2f(lp2.toArray(new Point[0]));
        Log.i("pointsPrev", pointsPrev.size().toString());
        Log.i("pointsAct", pointsAct.size().toString());
          fundamental_matrix.create(resultSize, CvType.CV_8UC1);
        fundamental_matrix = Calib3d.findFundamentalMat(
                  pointsAct, pointsPrev, Calib3d.FM_RANSAC, 3, 0.99);

有什么建议吗?

编辑:

我无法将匹配项转换为列表!因为Feature2d.drawMatches() 需要MatOfDmatch 而不是List&lt;Dmatch&gt;

MatOfDMatch matches, matches12, matches21;
matcher.match( descriptors1, descriptors2, matches12 );
matcher.match( descriptors2, descriptors1, matches21 );

iterate matches12
    DMatch forward = matches12[i];  
    DMatch backward = matches21[forward.trainIdx]; 
    if( backward.trainIdx == forward.queryIdx ) 
 //add forward to matches 
Features2d.drawMatches(img1, keypoints, mGraySubmat, mKeyPoints, matches,mIntermediateMat2);

【问题讨论】:

  • 你能修正一下代码的缩进吗?
  • 这段代码是用来提取两个图像的关键点,使用ORB目标是我想提取好的匹配并全部绘制出来

标签: android opencv


【解决方案1】:

你的代码应该是这样的:

 FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
 DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);;
 DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);

 //first image
 Mat img1 = Highgui.imread("<image1 path>");
 Mat descriptors1 = new Mat();
 MatOfKeyPoint keypoints1 = new MatOfKeyPoint();

 detector.detect(img1, keypoints1);
 descriptor.compute(img1, keypoints1, descriptors1);

 //second image
 Mat img2 = Highgui.imread("<image2 path>");
 Mat descriptors2 = new Mat();
 MatOfKeyPoint keypoints2 = new MatOfKeyPoint();

 detector.detect(img2, keypoints2);
 descriptor.compute(img2, keypoints2, descriptors2);

 //matcher should include 2 different image's descriptors
 MatOfDMatch  matches = new MatOfDMatch();             
 matcher.match(descriptors1,descriptors2,matches);
 //feature and connection colors
 Scalar RED = new Scalar(255,0,0);
 Scalar GREEN = new Scalar(0,255,0);
 //output image
 Mat outputImg = new Mat();
 MatOfByte drawnMatches = new MatOfByte();
 //this will draw all matches, works fine
 Features2d.drawMatches(img1, keypoints1, img2, keypoints2, matches, 
 outputImg, GREEN, RED,  drawnMatches, Features2d.NOT_DRAW_SINGLE_POINTS);

此外,如果您只想显示功能,您可以添加以下代码:

 Mat featuredImg = new Mat();
 Scalar kpColor = new Scalar(255,159,10);//this will be color of keypoints
 //featuredImg will be the output of first image
 Features2d.drawKeypoints(img1, keypoints1, featuredImg , kpColor, 0);
 //featuredImg will be the output of first image
 Features2d.drawKeypoints(img1, keypoints1, featuredImg , kpColor, 0);

然后你可以像这样显示匹配点:

  Bitmap imageMatched = Bitmap.createBitmap(outputImg.cols(), outputImg.rows(), Bitmap.Config.RGB_565);//need to save bitmap
  Utils.matToBitmap(outputImg, imageMatched);
  ImageView.setImageBitmap(imageMatched);

最终您可以实现良好的匹配。我希望this thread 会有所帮助。

【讨论】:

  • 您好,谢谢您的回复,现在我想要一个好的条件来找到一个好的相似性,但这个条件不是有效的,为什么? if(row_count>490&&good_matches.size()
  • 欢迎您。我不想误导,但我认为这取决于您的工作。您必须为自己的项目进行计算。
  • 我已经使用了你的代码,并用 10-12 张图像对其进行了测试,但它没有给出完美匹配,我只想找到精确匹配位置的坐标,但它无法给出我完美的结果。如果可能的话,请告诉我提高匹配准确性的方法
  • 似乎有几种方法可以提高匹配的准确性,但我不知道该怎么做。也许没有办法,它只是按照自己的方式行事。因为它是android中的本机库。这样我们就看不到里面的方法了。我还尝试使用分数的平均值,并定义了一个阈值(这取决于您正在处理的内容)以消除不良匹配。
【解决方案2】:

良好匹配方法基于从您的 MatOfDMatch matches = new MatOfDMatch(); 列表中删除具有不同描述符或空间位置的匹配点。我建议做的是循环匹配列表并将满足以下条件的匹配放入新列表中:

int DIST_LIMIT = 80;
List<DMatch> matchesList = matches.toList();
List<DMatch> matches_final= new ArrayList<DMatch>();
for(int i=0; i<matchesList.size(); i++)
   if(matchesList .get(i).distance <= DIST_LIMIT){
       matches_final.add(matches.toList().get(i));
   }
}

MatOfDMatch matches_final_mat = new MatOfDMatch();
matches_final_mat.fromList(matches_final);

你可以对匹配的点坐标做同样的事情。 Here 是有用的链接。

【讨论】:

  • 我无法将匹配项转换为列表!因为 Feature2d.drawMatches() 需要 MatOfDmatch 而不是 List MatOfDMatch matches, matches12, matches21; matcher.match(描述符1,描述符2,matches12); matcher.match(描述符2,描述符1,matches21); // 迭代matches12 DMatch forward = matches12[i]; DMatch 向后 =matches21[forward.trainIdx]; if(backward.trainIdx == forward.queryIdx) // 添加到 matches Features2d.drawMatches(img1, keypoints, mGraySubmat, mKeyPoints, matches,mIntermediateMat2);跨度>
  • 您可以使用MatOfDMatch matches = new MatOfDMatch(); matches.fromList(matches_final); 转换它。它效率不高,但我看不到在 java 中做 Good Matches 的另一种方法。
  • 是的,我解决了为什么?如果我们调用函数 c++ jni?你有其他解决方案吗
  • @Torcellite 在 compare() 函数内部,在第 162 行的 matcher.match() 之后添加我的答案代码。我刚刚编辑了它。我还建议使用 BRUTEFORCE_HAMMING 匹配器。如果你的图像非常相似,你应该使用更小的 DIST_LIMIT。我用的是 80,因为图像上有噪点
  • 是的。将匹配项和关键点转换为列表List&lt;DMatch&gt; matches_list = matches.toList();List&lt;KeyPoint&gt; kp_list = keypoints.toList();,然后遍历列表 kp_list.get(matches_list.get(i).queryIdx) 并找到匹配关键点的最小和最大 X 和 Y,以便遇到两个点来定义您的长方形。然后定义一个矩形Rect roi = new Rect(new Point(minX,minY),new Point(maxX,maxY)),然后您可以在匹配(识别)区域周围绘制矩形。取自我之前的answer
猜你喜欢
  • 1970-01-01
  • 2018-02-22
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多