我正在尝试使用 OpenCV 的 DescriptorMatcher 匹配 2 个相反的图像,但没有成功。 图片是:http://i61.tinypic.com/28whu0g.jpg (从左到右)和 http://i61.tinypic.com/x35vte.jpg (从右到左)。
我的代码与我在 StackOverflow 和网络上看到的许多示例非常相似,但我仍然无法匹配。
String firstImageSourcePath = "RTL_IMAGE_PATH";
String secondImageSourcePath = "LTR_IMAGE_PATH";
Mat firstImageSrcImgMat = Highgui.imread(firstImageSourcePath);
Mat secondImageSrcImgMat = Highgui.imread(firstImageSourcePath);
if (firstImageSrcImgMat.empty() || secondImageSrcImgMat.empty()) {
System.out.println("Failed to load images");
return;
}
System.out.println("Loaded image at " + firstImageSourcePath + " and " + secondImageSourcePath);
FeatureDetector featureDetector = FeatureDetector.create(FeatureDetector.BRISK);
MatOfKeyPoint firstImgMatOfKeyPoints = new MatOfKeyPoint();
MatOfKeyPoint secondImgMatOfKeyPoints = new MatOfKeyPoint();
featureDetector.detect(firstImageSrcImgMat, firstImgMatOfKeyPoints);
featureDetector.detect(secondImageSrcImgMat, secondImgMatOfKeyPoints);
System.out.println("Detected " + firstImgMatOfKeyPoints.size() + " and " + secondImgMatOfKeyPoints + " blobs in the images");
List<KeyPoint> firstImgKeyPoints = firstImgMatOfKeyPoints.toList();
List<KeyPoint> secondImgKeyPoints = secondImgMatOfKeyPoints.toList();
System.out.println("First Image key points: " + firstImgKeyPoints);
System.out.println("Second Image key points: " + secondImgKeyPoints);
Mat firstImgDescriptors = new Mat();
Mat secondImgDescriptors = new Mat();
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.BRISK);
extractor.compute(firstImageSrcImgMat, firstImgMatOfKeyPoints, firstImgDescriptors);
extractor.compute(secondImageSrcImgMat, secondImgMatOfKeyPoints, secondImgDescriptors);
System.out.println("descriptorsA.size() : " + firstImgDescriptors.size());
System.out.println("descriptorsB.size() : " + secondImgDescriptors.size());
MatOfDMatch matches = new MatOfDMatch();
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMINGLUT); // BRUTEFORCE_HAMMINGLUT
matcher.match(firstImgDescriptors, secondImgDescriptors, matches);
System.out.println("matches.size() : " + matches.size());
System.out.println("matches : " + matches);
MatOfDMatch matchesFiltered = new MatOfDMatch();
List<DMatch> matchesList = matches.toList();
List<DMatch> bestMatches = new ArrayList<DMatch>();
Double max_dist = 0.0;
Double min_dist = 100.0;
for (int i = 0; i < matchesList.size(); i++) {
Double dist = (double) matchesList.get(i).distance;
if (dist > 0)
System.out.println("dist : " + dist);
if (dist < min_dist && dist != 0) {
min_dist = dist;
}
if (dist > max_dist) {
max_dist = dist;
}
}
System.out.println("max_dist : " + max_dist);
System.out.println("min_dist : " + min_dist);
if (min_dist > 50) {
System.out.println("No match found, min_dist under minimum value");
return;
}
double threshold = 3 * min_dist;
double threshold2 = 2 * min_dist;
if (threshold > 75) {
threshold = 75;
} else if (threshold2 >= max_dist) {
threshold = min_dist * 1.1;
} else if (threshold >= max_dist) {
threshold = threshold2 * 1.4;
}
System.out.println("Threshold : " + threshold);
for (int i = 0; i < matchesList.size(); i++) {
Double dist = (double) matchesList.get(i).distance;
if (dist < threshold) {
bestMatches.add(matches.toList().get(i));
System.out.println(String.format(i + " best match added : %s", dist));
}
}
matchesFiltered.fromList(bestMatches);
System.out.println("matchesFiltered.size() : " + matchesFiltered.size());
if (matchesFiltered.rows() >= 1) {
System.out.println("match found");
} else {
System.out.println("match not found");
}
任何提示我做错了什么?
最佳答案
正如@Iwillnotexist-Idonotexist 所述,第一个问题是您应用的阈值。尝试使用不依赖于表现不佳的描述符之间的距离的阈值,因为一些描述符比其他描述符更具辨别力。我认为这会给你更好的结果。我建议您使用 D. Lowe 在 SIFT 的论文中提出的 Ratio Test。 请查看第 7.1 节:http://cs.ubc.ca/~lowe/papers/ijcv04.pdf
第二个问题是您正在使用 BRISK 来检测图像中的特征。这个 OpenCV 实现有错误(你可以在这里查看:http://code.opencv.org/issues/3976)所以尝试使用另一个 FeatureDetector,比如 FAST、ORB 等……(描述符很好,所以你可以继续使用它)
我最终在您的图片中进行了测试,并设法使用不同的检测器/描述符获得了一些结果: (没有匹配的关键点 -> 黄色)
BRISK 检测器和描述符:
- 左图关键点:74
- 右图关键点:86
- 匹配:3(即使检测器坏了我也有匹配)
以 BRISK 作为描述符的 ORB 检测器:
- 左图关键点:499
- 右图关键点:500
- 匹配:26
ORB 检测器和描述符
- 左图关键点:841
- 右图关键点:907
- 匹配:43
所有结果都是使用比率测试去除错误匹配获得的。 希望对您有所帮助!
编辑:
BruteForceMatcher<Hamming> matcher;
vector< vector<DMatch> > matches;
vector <DMatch> goodMatches;
matcher.knnMatch(imgDescriptors1, imgDescriptors2, matches, 2);
// Ratio Test
for (unsigned int matchIdx = 0; matchIdx < matches.size(); ++matchIdx)
{
const float ratio = 0.8; // As in Lowe's paper (can be tuned)
if (matches[matchIdx][0].distance < ratio * matches[matchIdx][1].distance)
{
goodMatches.push_back(matches[matchIdx][0]);
}
}
关于java - OpenCV - Java - 使用 DescriptorMatcher 与 2 个相反的图像不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26860992/