gpt4 book ai didi

Java OpenCV - 使用 knnMatch 和 findHomography 显示重复项

转载 作者:行者123 更新时间:2023-12-01 22:14:05 25 4
gpt4 key购买 nike

我是 OpenCV java 新手,我有一个 Android 应用程序,可以使用 ORB FeatureDetector 和 DescriptorExtractor 匹配两个图像。我使用 DescriptorMatcher BRUTEFORCE_HAMMING。匹配器始终有效,但有时它会显示关键点的重复项。当场景上的图像太亮或太暗时,它会显示重复的关键点,这不是我想要的。

准确匹配的图像:

enter image description here

不匹配的图像:

enter image description here

try {
bmpObjToRecognize = bmpObjToRecognize.copy(Bitmap.Config.ARGB_8888, true);
bmpScene = bmpScene.copy(Bitmap.Config.ARGB_8888, true);

img1 = new Mat();
img2 = new Mat();
Utils.bitmapToMat(bmpObjToRecognize, img1);
Utils.bitmapToMat(bmpScene, img2);
Imgproc.cvtColor(img1, img1, Imgproc.COLOR_RGBA2GRAY);
Imgproc.cvtColor(img2, img2, Imgproc.COLOR_RGBA2GRAY);
Imgproc.equalizeHist(img1, img1);
Imgproc.equalizeHist(img2, img2);
detector = FeatureDetector.create(FeatureDetector.ORB);
descExtractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);

keypoints1 = new MatOfKeyPoint();
keypoints2 = new MatOfKeyPoint();
descriptors = new Mat();
dupDescriptors = new Mat();

detector.detect(img1, keypoints1);
Log.d("LOG!", "number of query Keypoints= " + keypoints1.size());
detector.detect(img2, keypoints2);
Log.d("LOG!", "number of dup Keypoints= " + keypoints2.size());
// Descript keypoints1
descExtractor.compute(img1, keypoints1, descriptors);
descExtractor.compute(img2, keypoints2, dupDescriptors);
// matching descriptors
List<MatOfDMatch> knnMatches = new ArrayList<>();
matcher.knnMatch(descriptors, dupDescriptors, knnMatches, DescriptorMatcher.BRUTEFORCE);
goodMatches = new ArrayList<>();
knnMatchesValue = knnMatches.size();
Log.i("xxx", "xxx match count knnMatches = " + knnMatches.size());
for (int i = 0; i < knnMatches.size(); i++) {
if (knnMatches.get(i).rows() > 1) {
DMatch[] matches = knnMatches.get(i).toArray();
if (matches[0].distance < 0.89f * matches[1].distance) {
goodMatches.add(matches[0]);
}
}
}

// get keypoint coordinates of good matches to find homography and remove outliers using ransac
List<Point> pts1 = new ArrayList<>();
List<Point> pts2 = new ArrayList<>();
for (int i = 0; i < goodMatches.size(); i++) {
Point destinationPoint = keypoints2.toList().get(goodMatches.get(i).trainIdx).pt;
pts1.add(keypoints1.toList().get(goodMatches.get(i).queryIdx).pt);
pts2.add(destinationPoint);
}

// convertion of data types - there is maybe a more beautiful way
Mat outputMask = new Mat();
MatOfPoint2f pts1Mat = new MatOfPoint2f();
pts1Mat.fromList(pts1);
MatOfPoint2f pts2Mat = new MatOfPoint2f();
pts2Mat.fromList(pts2);

// Find homography - here just used to perform match filtering with RANSAC, but could be used to e.g. stitch images
// the smaller the allowed reprojection error (here 15), the more matches are filtered
Mat Homog = Calib3d.findHomography(pts1Mat, pts2Mat, Calib3d.RANSAC, 15, outputMask, 2000, 0.995);

// outputMask contains zeros and ones indicating which matches are filtered
better_matches = new LinkedList<>();
for (int i = 0; i < goodMatches.size(); i++) {
if (outputMask.get(i, 0)[0] != 0.0) {
better_matches.add(goodMatches.get(i));
}
}

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

imgOutputMat = new Mat();
MatOfByte drawnMatches = new MatOfByte();
Features2d.drawMatches(img1, keypoints1, img2, keypoints2, matches_final_mat,
imgOutputMat, GREEN, RED, drawnMatches, Features2d.NOT_DRAW_SINGLE_POINTS);
bmp = Bitmap.createBitmap(imgOutputMat.cols(), imgOutputMat.rows(), Bitmap.Config.ARGB_8888);
Imgproc.cvtColor(imgOutputMat, imgOutputMat, Imgproc.COLOR_BGR2RGB);
Utils.matToBitmap(imgOutputMat, bmp);
List<DMatch> betterMatchesList = matches_final_mat.toList();
final int matchesFound = betterMatchesList.size();


} catch (Exception e) {
e.printStackTrace();
}

我是否缺少部分代码?

最佳答案

TL;DR 使用类 BFMatcher 及其 create显式地调用方法,然后您就可以将crosscheck标志设置为true。这将启用您想要的“反之亦然检查”。

引用knnMatch的OpenCV文档及其标题:

Finds the k best matches for each descriptor from a query set.

knnMatch(InputArray queryDescriptors, InputArray trainDescriptors, ...)

因此,这意味着可能有多个“查询描述符”与“训练集”中的同一描述符匹配。它只是为您提供 k 个最佳值,如果查询描述符多于训练描述符,您将不可避免地得到重复项。特别是,当你在训练图像/集中几乎没有特征和描述符时(由于缺乏任何纹理,例如黑色输入),情况就会如此。

如果您想删除重复项,请将 BFMatcher 的“crosscheck”标志设置为 true。否则(即其他匹配器),您将需要通过相应的训练描述符对匹配项进行“分组”,并删除除距离最小的匹配项之外的所有匹配项。

关于Java OpenCV - 使用 knnMatch 和 findHomography 显示重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58639964/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com