如何在java中使用openCV检查两个图像是否相似?

如何在java中使用openCV检查两个图像是否相似?,java,android,opencv,Java,Android,Opencv,我必须使用OpenCV检查两个图像在java中是否相似,我正在使用OpenCV和ORB 这是我的主课 System.out.println("Welcome to OpenCV " + Core.VERSION); System.loadLibrary(Core.NATIVE_LIBRARY_NAME);()); System.out.println(System.getProperty("user.dir")); File f1 = new File(System.getProperty("u

我必须使用OpenCV检查两个图像在java中是否相似,我正在使用OpenCV和ORB

这是我的主课

System.out.println("Welcome to OpenCV " + Core.VERSION);
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);());
System.out.println(System.getProperty("user.dir"));
File f1 = new File(System.getProperty("user.dir") + "\\test.jpg");
File f2 = new File(System.getProperty("user.dir") + "\\test2.jpg");
MatchingDemo2 m = new MatchingDemo2();
m.mth(f1.getAbsolutePath(), f2.getAbsolutePath());
这是我的匹配demo2.java文件

public class MatchingDemo2 {

public void mth(String inFile, String templateFile){
        FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
       //Create descriptors

        //first image
       // generate descriptors

        //second image
       // generate descriptors



        System.out.println("size " + matches.size());
        //HOW DO I KNOW IF IMAGES MATCHED OR NOT ????

        //THIS CODE IS FOR CONNECTIONS BUT I AM NOT ABLE TO DO IT
        //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);
        int DIST_LIMIT = 80;
        List<DMatch> matchList = matches.toList();
        List<DMatch> matches_final = new ArrayList<DMatch>();
        for(int i=0; i<matchList.size(); i++){
            if(matchList.get(i).distance <= DIST_LIMIT){
                matches_final.add(matches.toList().get(i));
            } 
        }

        MatOfDMatch matches_final_mat = new MatOfDMatch();
        matches_final_mat.fromList(matches_final);
        for(int i=0; i< matches_final.size(); i++){
            System.out.println("Good Matchs "+ matches_final.get(i));
        }
}
}
对于相同的图像以及不同的图像,我得到的匹配数是相同的 我真的很困惑?您能解释一下如何比较两幅图像,并判断它们是否相似吗


我试图实现的是

匹配器只搜索关键点图的最近匹配。对于度量差异,您需要使用距离的(平均)和(或其他度量)。

因为您使用的是BRUTEFORCE matcher,所以您将始终从列车中的查询(模板)(包含查询的图像)中获得所有关键点描述符的最佳匹配。 i、 e:BRUTEFORCE matcher将始终找到100%的匹配(列车描述符中所有查询关键点描述符的最佳等效关键点)

这意味着您需要将匹配项筛选为正确匹配项(内联项)和不正确匹配项(异常值)匹配项

你可以用两种方法来做

1.距离计算

使用Andrey Smorodov提到的距离。你可以用这个方法 (但这并不总是提供正确的结果)

3.另一种更简单的方法是比较这两幅图像的直方图,您可以使用compHist()openCV的功能,如图所示 并参考openCV文档

比较直方图中的各种方法给出了从0到1或更高值的输出范围,该输出取决于直方图之间的相似性。在某些方法中小心1是100%正匹配,在其他方法中小心0。 “对于卡方检验法,低分表示比高分更好的匹配。完美匹配为0,总不匹配是无限的(取决于直方图的大小)。”

余数:-两个完全不同的图像可以具有完全相同的直方图值

小贴士:

1.现在关于knnMatch,只需使用matcher.knnMatch();以及输出的适当数据类型

2.也在

 matcher.match(query, train, matches);
查询=>模板的关键点描述符,例如球和

包含相同球的图像的train=>关键点描述符。 查询描述符的数量小于列描述符的数量请确保这一点正确


现在祝你好运。

上面您已经打印了“good Matchs DMatch[queryIdx=29,trainIdx=67,imgIdx=0,distance=49.0]”。获取所有距离,求和,按它们的数量(计算平均值)进行划分,这将成为你的相似性度量。对于同一图像与自身相比,我得到0作为平均值,对于不同的图像,我得到50-70作为平均值。但是它实际上没有正确地比较图像?我应该怎么做才能得到一个很好的匹配(除了使用SURF)?我还应该如何为比较的图像绘制位图?你可能需要PSNR之类的东西吗?然后看看。为什么你们认为你们得到的平均距离并没有相关的差异度量?您可以像这里描述的那样绘制覆盖图:如何在java中实现它?什么是keypointsRef Determine Mask?你能把你的项目上传到github上吗?另外,你提供的直方图链接不是图像,而是存储在数组中的直方图,所以我检查了,但我在转换代码方面有问题1)我在技巧中解释过,keypointRef是从包含名为train keypoints 2)Mask的对象是Calib3d.findHomography()中的可选输出;3) 无需在android中转换代码。您可以在android NDK中使用jni包装器。您可以在github上上载项目吗?我认为使用earthmover距离(而不是使用平均距离)可能是更好的距离度量。
List<DMatch> matchesList = matches.toList();
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 < min_dist)
        min_dist = dist;
    if (dist > max_dist)
    max_dist = dist;
}

LinkedList<DMatch> good_matches = new LinkedList<DMatch>();
for (int i = 0; i < matchesList.size(); i++)  {  
    if (matchesList.get(i).distance <= (3 * min_dist)) // change the limit as you desire
    good_matches.addLast(matchesList.get(i));
}
        LinkedList<Point> objList = new LinkedList<Point>();
        LinkedList<Point> sceneList = new LinkedList<Point>();

        List<KeyPoint> keypoints_RefList = keypointsRef.toList();
        List<KeyPoint> keypoints_List = keypoints.toList();

        for (int i = 0; i < good_matches.size(); i++) {
            objList.addLast(keypoints_RefList.get(good_matches.get(i).queryIdx).pt);
            sceneList.addLast(keypoints_List.get(good_matches.get(i).trainIdx).pt);
        }                 

        MatOfPoint2f obj = new MatOfPoint2f();
        MatOfPoint2f scene = new MatOfPoint2f();

        obj.fromList(objList);  
        scene.fromList(sceneList);  

        Mat mask = new Mat();
        Mat hg = Calib3d.findHomography(obj, scene, 8, 10,  mask);
08-22 01:08:38.929: I/OCVSample::Activity(25799): Keypoints Size: 1x477  KeypointsRef Size : 1x165
08-22 01:08:39.049: I/OCVSample::Activity(25799): descriptor Size: 32x477  descriptorRef Size : 32x165
08-22 01:08:39.129: I/OCVSample::Activity(25799): Matches Size: 1x165
08-22 01:08:39.129: I/OCVSample::Activity(25799): matchesList Size: 165
08-22 01:08:39.139: I/OCVSample::Activity(25799): Max dist : 460.44110107421875   Min dist : 100.0
08-22 01:08:39.139: I/OCVSample::Activity(25799): good matches size: 19
08-22 01:08:39.139: I/OCVSample::Activity(25799): obj size : 1x165
08-22 01:08:39.139: I/OCVSample::Activity(25799): scene size : 1x165
08-22 01:08:40.239: I/OCVSample::Activity(25799): Homography  mask size : 1x165
08-22 01:08:40.239: I/OCVSample::Activity(25799): Homography  mask : [1; 1; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 0; 1; 1; 1; 0; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 1; 0; 0; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 1; 1; 1; 1; 1; 1; 0; 1; 1; 0; 1; 0; 1; 0; 0; 1; 0; 1; 1; 1; 1; 1; 1; 1; 0; 1; 1; 1; 1; 1; 0; 1; 1; 1; 1; 0; 0; 1; 1; 0; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 0; 1; 1; 1; 1; 0; 0; 0; 1; 0; 1; 1; 1; 1; 0; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 1; 0; 1; 1; 0; 1; 1; 1; 1; 0; 1; 1; 1; 1; 1; 1; 1; 0; 1; 1; 0; 0; 1; 1]
 matcher.match(query, train, matches);