【发布时间】:2017-07-19 05:17:13
【问题描述】:
我试图找出两个图像与使用图像匹配的 openCV 相似。我正在运行以下代码:
public static void match(String firstImage, String secondImage, String outputFile) {
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
Mat firstImg = Imgcodecs.imread(firstImage, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
MatOfKeyPoint firstKeypoints = new MatOfKeyPoint();
Mat firstDescriptors = new Mat();
detector.detect(firstImg, firstKeypoints);
descriptor.compute(firstImg, firstKeypoints, firstDescriptors);
Mat secondImg = Imgcodecs.imread(secondImage, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
MatOfKeyPoint secondKeypoints = new MatOfKeyPoint();
Mat secondDescriptors = new Mat();
detector.detect(secondImg, secondKeypoints);
descriptor.compute(secondImg, secondKeypoints, secondDescriptors);
MatOfDMatch matches = new MatOfDMatch();
matcher.match(firstDescriptors, secondDescriptors, matches);
float minDis = Float.MAX_VALUE;
for (int i = 0;i < matches.rows();i++) {
if (matches.toArray()[i].distance < minDis)
minDis = matches.toArray()[i].distance;
}
LinkedList<DMatch> goodMatches = new LinkedList<>();
for (int i = 0;i < matches.rows();i++) {
if (matches.toArray()[i].distance < minDis*3)
goodMatches.add(matches.toArray()[i]);
}
List<Point> pts1 = new ArrayList<Point>();
List<Point> pts2 = new ArrayList<Point>();
for(int i = 0; i<goodMatches.size(); i++){
pts1.add(firstKeypoints.toList().get(goodMatches.get(i).queryIdx).pt);
pts2.add(secondKeypoints.toList().get(goodMatches.get(i).trainIdx).pt);
}
// 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);
Calib3d.findHomography(pts1Mat, pts2Mat, Calib3d.RANSAC, 15, outputMask, 2000, 0.995);
// outputMask contains zeros and ones indicating which matches are filtered
LinkedList<DMatch> betterMatches = new LinkedList<DMatch>();
for (int i = 0; i < goodMatches.size(); i++) {
if (outputMask.get(i, 0)[0] != 0.0) {
betterMatches.add(goodMatches.get(i));
}
}
Mat outputImg = new Mat();
MatOfDMatch betterMatchesMat = new MatOfDMatch();
betterMatchesMat.fromList(betterMatches);
Features2d.drawMatches(firstImg, firstKeypoints, secondImg, secondKeypoints, betterMatchesMat, outputImg);
Imgcodecs.imwrite(outputFile, outputImg);
}
当图像相似时,结果如下所示:
当图像不相似时,结果如下所示:
您可以看到,在第一种情况下,匹配线是平行的,因此这两个图像相似是有道理的。在第二种情况下,匹配线不平行,因此图像不相似是有道理的。有没有一种标准的方法来分析这些匹配并找出在哪种情况下图像最有可能相似?
【问题讨论】:
-
执行互相关
-
ORB、SIFT、SURF等主要用于查找图像中的特定对象。您可以执行相关性以确定图像的相似性。您可以单独上传您正在使用的图像吗?
-
平行度不足以判断匹配是否成功,如果您假设相机几乎是静止的,或者是一个几乎平面的场景/对象,您可以从匹配的点计算单应性。如果找到“良好”的单应性,则图像在这些点上是完全相等的。此外,在“应用”单应性(例如图像变形)之后,您可以使用比较像素等简单方法更好地比较两个图像。总而言之,这个主题非常难,但取决于您对“图像相似性”的定义/需求,它可能会或可能不会变得更容易。
-
@JeruLuke 你所说的相关性是什么意思?请注意,图像不相同但相似