Android中的OpenCV图像比较 [英] OpenCV image comparison in Android

查看:64
本文介绍了Android中的OpenCV图像比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设计了一些用于图像比较的代码.匹配部分仍然有点缺陷,我希望得到一些帮助.该项目可以在 - 找到的代码.

我不知道如何初始化MatOfKeyPoint 变量keypointslogoKeypoints.这是我的代码片段:

 FeatureDetector 检测器 = FeatureDetector.create(FeatureDetector.SURF);//FeatureDetector 检测器 = FeatureDetector.create(FeatureDetector.FAST);//Imgproc.cvtColor(img1, img1, Imgproc.COLOR_RGBA2RGB);//Imgproc.cvtColor(img2, img2, Imgproc.COLOR_RGBA2RGB);DescriptorExtractor SurfExtractor = DescriptorExtractor.create(DescriptorExtractor.SURF);//提取关键点MatOfKeyPoint 关键点、logoKeypoints;长时间= System.currentTimeMillis();检测器.检测(img1,关键点);Log.d("LOG!", "查询Keypoints数= " + keypoints.size());检测器.检测(img2,logoKeypoints);Log.d("LOG!", "logo Keypoints 的数量 = " + logoKeypoints.size());Log.d("LOG!", "关键点计算时间已过" + (System.currentTimeMillis() -time));//描述关键点long time2 = System.currentTimeMillis();垫子描述符 = new Mat();Mat logoDescriptors = new Mat();Log.d("LOG!", "标志类型" + 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 初始化为空,因为那时我会收到空​​指针异常.我如何初始化它们?

解决方案

您应该明白这不是一个简单的问题,您可以遵循不同的概念.我只会指出两个没有源代码的解决方案.

  1. 直方图比较:您可以将两个图像都转换为灰度,在 [0,...,255] 范围内制作直方图.将计算每个像素值.然后使用两个直方图进行比较.如果像素强度的分布等于或高于某个阈值(可能是所有像素的 90%),您可以将这些图像视为重复图像.但是:这是最简单的解决方案之一,如果任何图片具有均等分布,则它不稳定.
  2. 兴趣点检测器/-描述符:看看 SIFT/SURF 图像检测器和描述符.检测器将尝试确定图像中强度的唯一关键点.将在此位置 I(x,y) 计算描述符.具有蛮力方法和欧几里德距离的普通匹配器可以使用它们的描述符匹配这些图像.如果图像是重复的,则给定匹配的比率应该非常高.此解决方案非常易于实施,并且可能有足够多的关于此主题的教程.

我希望这会有所帮助.有问题请追问.

[更新-1]C++ 教程: 并且有一个公共构造函数.AND:您可以使用要分析的图像的垫子.这很好.=)

MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage);

对于匹配使用 BRUTEFORCE_SL2 Descriptor-Matcher 导致您SURF 或 SIFT 需要欧氏距离.

[EDIT] I have devised some code for image comparison. The matching part is still a bit flawed and I would love some assitance. The project can be found at - GitHub.

I have these two images Img1 and Img2:

When I use the following command in 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
}

I get a double value for l2_norm. This double value varies for duplicate image pairs. But if the images are different, then an exception is thrown. Is this how I identify duplicate images? Or is there a better method? I've Googled extensively and couldn't find a really convincing answer. I would like the code and explanation as to how I'd compare two images and get a boolean value of true or false depending upon the images.

EDIT

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

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

I've tried this, but the if condition is never satisfied. I'm assuming there are a few differences, but there is no compare function for Scalar. What do I do?

EDIT

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);
    }

This method is again flawed. Although it can be used to compare images with a decent accuracy, it fails when images are of different sizes.

When images are of different sizes and I print the scalar values I get this:

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

The variation between the second and third numbers although not much is quite large compared to when the images of same size are compared. The first number however suffers the most change.

What would be the best fastest way to compare the contents of two images?

[EDIT]

I'm using the code I found here.

What I'm not able to figure out is how to initialize the MatOfKeyPoint variables keypoints and logoKeypoints. Here's my code snippet:

           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));

I obviously can't initialize the variables keypoints and logoKeypoints to null cuz I'll receive a null pointer exception then. How do I initialize them?

解决方案

You should understand that this is not a simple question and you have different concepts you could follow. I will only point out two solution without source-code.

  1. Histogram comparison: You could convert both images into grey-scale make a histogram in the range of [0,...,255]. Every pixel-value will be counted. Then use both histograms for comparison. If the distribution of pixel-intensities equals or is above some treshold (perhaps 90% of all pixels), you could consider this images as duplicates. BUT: This is one of the simplest solutions and it isn't stable if any picture has an equal distribution.
  2. Interest-Point-Detectors/-Descriptors: Take a look at SIFT/SURF image-detectors and descriptors. A detector will try to determine unique keypoits of intensities in an image. A descriptor will be computed at this location I(x,y). A normal matcher with a bruteforce-approach and euclidean distance can match these images using their descriptors. If an image is a duplicate the rate of given matches should very high. This solution is good to implement and there could be enough tutorials regarding this topic.

I'll hope this helps. Please ask if you have questions.

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

Some JavaCV-tutorials: http://code.google.com/p/javacv/w/list

[UPDATE-2] Here is an example with SIFT-Detector and SIFT-Descriptor using default parameters. RANSAC-Threshold for homography is 65, reprojection-error (epsilon) is 10, cross-validation enabled. You could try to count the matched. If the Inliner-Outlier-Ratio is too high you could see this pair as duplicates. For example: These images produce 180 keypoints in IMG1 and 198 in IMG2. The matched descriptors are 163 of which only 3 are outliers. So this gives a really good ratio which only could mean that these images could be duplicates.

[UPDATE-3] I don't understand why you can initialize the MatOfKeypoints. I've read the API and there's a public constructor. AND: You can use the Mat of the image you want to analyse. This is very nice. =)

MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage);

For Matching use a BRUTEFORCE_SL2 Descriptor-Matcher cause you will need the euclidean distance for SURF or SIFT.

这篇关于Android中的OpenCV图像比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆