我试图找出两个图像与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);
}
当图像相似时,结果如下:
当图像不相似时,结果如下:
您可以看到,在第一种情况下,匹配线是平行的,因此两个图像相似是有意义的。在第二种情况下,匹配线不是平行的,因此图像不相似是有意义的。有没有一种标准的方法来分析这些匹配,并找出在哪种情况下图像最可能相似?
答案 0 :(得分:3)
为了检查相似图像的两个视角之间的单应矩阵的适当性,我编写了这个函数。您可以根据自己的喜好选择自己喜欢的内容,具体取决于您认为哪个更合适:
private static boolean check_homography(Mat homography_mat){
/* Check 1. Compute the determinant of the homography, and see if it's too close
to zero for comfort*/
if(!homography_mat.empty())
{
double Determinant = Core.determinant(homography_mat);
if (Determinant > 0.1)
return true;
else
return false;
}
else
return false;
/* Check 2. Compute its SVD, and verify that the ratio of the first-to-last
singular value is not too high (order of 1.0E7). */
Mat singularValues = new Mat();
Core.SVDecomp(homography_mat, singularValues, new Mat(), new Mat(), Core.SVD_NO_UV);
System.out.print("\n Printing the singular values of the homography");
for (int i = 0; i < singularValues.rows(); i++){
for ( int j = 0; j < singularValues.cols(); j++){
System.out.print("\n Element at ( " + i + ", " + j + " ) is " + singularValues.get(i, j)[0]);
}
}
double conditionNumber = singularValues.get(0, 0)[0] / singularValues.get(2, 0)[0];
System.out.print("\n Condition number is : " + conditionNumber);
if(conditionNumber < Math.pow(10, 7)){
System.out.print("\n Homography matrix is non-singular");
return true;
}
else{
System.out.print("\n Homography matrix is singular (or very close)");
return false;
}
/* Check 3. Check the compare absolute values at (0,0) and (0,1) with (1,1) and (1,0)
* respectively. If the two differences are close to 0, the homography matrix is
* good. (This just takes of rotation and not translation)
* */
if(Math.abs((Math.abs(homography_mat.get(0, 0)[0]) - Math.abs(homography_mat.get(1, 1)[0]))) <= 0.1){
if(Math.abs((Math.abs(homography_mat.get(0, 1)[0]) - Math.abs(homography_mat.get(1, 0)[0]))) <= 0.1){
System.out.print("\n The homography matrix is good");
return true;
}
}
else{
System.out.print("\n The homography matrix is bad");
return false;
}
return false;
/*
* Check 4: If the determinant of the top-left 2 by 2 matrix (rotation) > 0, transformation is orientation
* preserving.
* Else if the determinant is < 0, it is orientation reversing
*
* */
Determinant of the rotation mat
double det = homography_mat.get(0, 0)[0] * homography_mat.get(1,1)[0] - homography_mat.get(0, 1)[0] * homography_mat.get(1, 0)[0];
if (det < 0)
return false;
double N1 = Math.sqrt(homography_mat.get(0, 0)[0] * homography_mat.get(0, 0)[0] + homography_mat.get(1, 0)[0] * homography_mat.get(1, 0)[0]);
if (N1 > 4 || N1 < 0.1)
return false;
double N2 = Math.sqrt(homography_mat.get(0, 1)[0] * homography_mat.get(0, 1)[0] + homography_mat.get(1, 1)[0] * homography_mat.get(1, 1)[0]);
if (N2 > 4 || N2 < 0.1)
return false;
double N3 = Math.sqrt(homography_mat.get(2, 0)[0] * homography_mat.get(2, 0)[0] + homography_mat.get(2,1)[0] * homography_mat.get(2, 1)[0]);
if (N3 < 0.002)
return false;
return true;
}
注意 - 我在使用ORB时为Java,OpenCV编写了这个代码。我个人(根据我的经验),可以看一下Homography矩阵,如果好或不好,或者说 Check 1 或多或少。希望它有所帮助!!
修改强> 另外,正如@Micka所提到的,这取决于您的偏好,您还可以逐个像素地迭代这两个图像以找到相似性。我在这里发布的方法用于检查单应性是否良好,但应注意这一点 根据图像和方法(前/后处理,描述符,检测器等),即使两个图像相似,也会出现错误的单应性
答案 1 :(得分:0)
用外行术语来说,相关确定两个变量/数据集/等之间的线性关系。这种关系可能是正线性的,也可能是负线性的。 Pearson的R 是查找两个变量之间相关系数的常用方法。
Pearson's R的结果位于-1
和+1
之间。
-1
- &gt; 彼此高度非线性+1
- &gt; 彼此高度线性这是一种表示两个变量有多相似或不相似的数字方式。
在这种情况下,我假设灰度图像是两个变量。在计算它之前,我将图像展平为1D阵列。
Pearson的R可以通过使用 scipy 库(在Python中)来确定。
from scipy.stats.stats import pearsonr
要获取有关pearsonr
及其返回类型的详细信息,请查看THIS LINK
因此,使用python我为所有三个图像计算了Pearson的R,相互之间。
这就是我得到的:
(0.62908215058685268, 0.0)
(-0.34523397781005682, 0.0)
(-0.36356339857880066, 0.0)
因此,我们可以说(在数字/统计术语中)前两个图像有些相似(假设有一个手提包,另一个没有手提包)。
如果您为两张相同的图像执行Pearson的R,您将获得1
的结果