Android中的OpenCV图像比较(OpenCV image comparison in And

2019-07-19 20:25发布

[编辑]我设计用于图像比较一些代码。 匹配的部分仍然是一个有点瑕疵的,我会喜欢一些assitance。 该项目可以在这里找到- GitHub上 。

我有这两个图像IMG1和IMG2:

当我使用OpenCV中下面的命令

Mat img1 = Highgui.imread("mnt/sdcard/IMG-20121228.jpg");
Mat img2 = Highgui.imread("mnt/sdcard/IMG-20121228-1.jpg");

try{
    double l2_norm = Core.norm( img1, img2 );
    tv.setText(l2_norm+"");
} catch(Exception e) {
    //image is not a duplicate
}

我得到l2_norm的双重价值。 这种双重价值重复的图像对变化。 但是,如果图像是不同的,然后抛出一个异常。 这是我如何找出重复的图片? 或者,有没有更好的方法? 我已经广泛用谷歌搜索,但没有找到一个真正有说服力的答案。 我想代码,并解释如何,我会比较两个图像,并得到一个布尔值truefalse取决于图像。

编辑

Scalar blah= Core.sumElems(img2);
    Scalar blah1=Core.sumElems(img1);

    if(blah.equals(blah1))
    {
        tv.setText("same image");
    }
    }

我已经试过这一点,但if条件永远不会满足。 我假设有一些差别,但没有compare的功能Scalar 。 我该怎么办?

编辑

try{
    Scalar blah= Core.sumElems(img2);
    Scalar blah1=Core.sumElems(img1);
    String b=blah.toString();
    String b1=blah1.toString();
    System.out.println(b+" "+b1);
    double comp=b.compareTo(b1);
    tv.setText(""+comp);
    }

这种方法是有缺陷的再次。 虽然可以使用一个体面的精度比较图像,它的图像时的大小不同的失败。

当图像是不同大小的,我打印标量值我得到这样的:

[9768383.0, 1.0052889E7, 1.0381814E7, 0.0] [1.5897384E7, 1.6322252E7, 1.690251E7, 0.0]

时相比,同样大小的图像进行比较,以在第二和第三个数字虽然不多之间的变化是相当大的。 然而,第一个数字受到最多的变化。

什么是比较两个图像的内容最好最快的方法?

[编辑]

我使用的是我找到的代码在这里 。

什么我无法弄清楚是如何初始化MatOfKeyPoint变量keypointslogoKeypoints 。 这里是我的代码片段:

           FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF);
        //FeatureDetector detector = FeatureDetector.create(FeatureDetector.FAST);
        //Imgproc.cvtColor(img1, img1, Imgproc.COLOR_RGBA2RGB);
        //Imgproc.cvtColor(img2, img2, Imgproc.COLOR_RGBA2RGB);

        DescriptorExtractor SurfExtractor = DescriptorExtractor
        .create(DescriptorExtractor.SURF);


        //extract keypoints
        MatOfKeyPoint keypoints, logoKeypoints;
        long time= System.currentTimeMillis();
        detector.detect(img1, keypoints);
        Log.d("LOG!", "number of query Keypoints= " + keypoints.size());
        detector.detect(img2, logoKeypoints);
        Log.d("LOG!", "number of logo Keypoints= " + logoKeypoints.size());
        Log.d("LOG!", "keypoint calculation time elapsed" + (System.currentTimeMillis() -time));

        //Descript keypoints
        long time2 = System.currentTimeMillis();
        Mat descriptors = new Mat();
        Mat logoDescriptors = new Mat();
        Log.d("LOG!", "logo type" + img2.type() + "  intype" + img1.type());
        SurfExtractor.compute(img1, keypoints, descriptors);
        SurfExtractor.compute(img2, logoKeypoints, logoDescriptors);
        Log.d("LOG!", "Description time elapsed" + (System.currentTimeMillis()- time2));

我显然不能初始化变量, keypointslogoKeypoints为空因为我会收到一个空指针异常即可。 我该如何初始化呢?

Answer 1:

你应该明白,这不是一个简单的问题,你有,你可以遵循不同的概念。 我只点了两次解决方案,而源代码。

  1. 直方图比较 :您可以两种图像转换成灰度进行直方图的范围[0,...,255]。 每个像素值将被计算在内。 然后使用两个直方图进行比较。 如果像素强度的分布等于或高于某个treshold(也许90%的像素),你可以考虑此图片为重复。 但是:这是最简单的解决方案之一,如果任何图片都有平等的分配不能稳定下来。
  2. 兴趣点探测器/ -Descriptors:看看SIFT / SURF图像探测器和描述符。 探测器将尝试确定图像中强度的独特keypoits。 描述符将在此位置I(X,Y)来计算。 用暴力破解的方法和欧几里德距离A正常匹配器可以使用其的描述符相匹配这些图像。 如果图像是一个重复的给定匹配的速度应该非常高。 该解决方案是很好的实施,有可能是关于这个话题足够的教程。

我希望这有助于。 如果您有任何疑问请询问。

[UPDATE-1] A C ++ -教程: http://morf.lv/modules.php?name=tutorials&lasit=2#.UR-ewKU3vCk

一些JavaCV-教程: http://code.google.com/p/javacv/w/list

[UPDATE-2]下面是SIFT检测器的示例,并且使用默认参数SIFT描述符。 RANSAC门限为单应为65,重投影误差(ε)为10,交叉验证启用。 你可以试着算匹配。 如果内衬离群,比过高,你可以看到这双为重复。 例如:这些图像产生180点的关键点在IMG1和IMG2中198。 匹配描述符163,其中只有3是异常值。 所以这给了一个很好的比例只有可能意味着,这些照片可能是重复的。

[更新-3]我不明白你为什么可以初始化MatOfKeypoints。 我读过的API ,并有一个公共的构造函数。 和:你可以使用你想分析图像的垫子。 这是非常好的。 =)

MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage);

匹配使用BRUTEFORCE_SL2描述符匹配器 ,因为你将需要SURF欧氏距离或SIFT。



Answer 2:

使用cv2.absDiff计算图片之间的差异cv2.sumElems获得的所有像素差的总和。

然后,通过发明您判断阉两个图像相似与否的阈值。



Answer 3:

你可以试试下面的代码:

Mat img1 = Highgui.imread("mnt/sdcard/IMG-20121228.jpg");
Mat img2 = Highgui.imread("mnt/sdcard/IMG-20121228-1.jpg");
Mat result = new Mat();

Core.compare(img1,img2,result,Core.CMP_NE);

int val = Core.countNonZero(result);

if(val == 0) {
    //Duplicate Image
} else {
    //Different Image
}

在这里,在代码比较功能将比较两个图像,然后,如果有有图像之间的相似性DIS然后然后特定矩阵值将是255和所有其他值将是零。 然后,你可以指望非零值的数量来确定,如果图像都是平等的。 这将只能用于完全相同的图像。

如果你想比较忽略的灯光效果,我建议你先产生边缘图像的图像(使用的OpenCV精明的功能),然后比较图像。

希望这个答案可以帮助你!



文章来源: OpenCV image comparison in Android