[编辑] 的 我已经设计了一些图像比较代码。匹配的部分仍然有点缺陷,我希望得到一些帮助。该项目可在 - 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的double值。对于重复的图像对,此双值会有所不同。但是如果图像不同,则抛出异常。这是我识别重复图像的方式吗?还是有更好的方法?我用Google搜索广泛,无法找到真正有说服力的答案。我希望代码和解释如何比较两个图像,并根据图像得到布尔值true
或false
。
修改
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]
与比较相同尺寸的图像相比,第二和第三数字之间的变化虽然不是很大但是相当大。然而,第一个数字的变化最大。
比较两张图片内容的最快方法是什么?
[编辑] 的
我正在使用我找到的代码here。
我无法弄清楚如何初始化MatOfKeyPoint
变量keypoints
和logoKeypoints
。这是我的代码片段:
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));
我显然无法将变量keypoints
和logoKeypoints
初始化为null因为我将收到空指针异常。我如何初始化它们?
答案 0 :(得分:25)
您应该明白这不是一个简单的问题,您可以遵循不同的概念。我只会指出两个没有源代码的解决方案。
我希望这会有所帮助。如果您有任何疑问,请询问。
<强> [UPDATE-1] 强> 一个C ++ - 教程:http://morf.lv/modules.php?name=tutorials&lasit=2#.UR-ewKU3vCk
一些JavaCV教程:http://code.google.com/p/javacv/w/list
<强> [UPDATE-2] 强> 以下是使用默认参数的SIFT-Detector和SIFT-Descriptor的示例。单应性的RANSAC-阈值为65,重投影误差(epsilon)为10,启用交叉验证。您可以尝试计算匹配的数量。如果Inliner-Outlier-Ratio太高,您可能会看到这对重复。 例如:这些图像在IMG1中生成180个关键点,在IMG2中生成198个关键点。匹配的描述符是163,其中只有3个是异常值。所以这给出了一个非常好的比例,这可能意味着这些图像可能是重复的。
<强> [UPDATE-3] 强> 我不明白为什么你可以初始化MatOfKeypoints。 I've read the API并且有一个公共构造函数。 AND:您可以使用要分析的图像的Mat。这非常好。 =)
MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage);
对于匹配使用BRUTEFORCE_SL2 Descriptor-Matcher原因,您将需要SURF或SIFT的欧氏距离。
答案 1 :(得分:1)
使用cv2.absDiff
计算图片与cv2.sumElems
之间的差异,以获得所有像素差异的总和。
然后发明一个阈值来判断两个图像是否相似。
答案 2 :(得分:0)
您可以尝试以下代码:
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
}
此处代码比较功能将比较两个图像,然后如果图像之间存在不相似性,则特定矩阵值将为255,所有其他值将为零。然后,您可以计算非零值的数量,以确定图像是否相等。这仅适用于完全相同的图像。
如果你想比较忽略灯光效果的图像,我建议你首先生成边缘图像(使用OpenCV的canny函数),然后比较图像。
希望这个答案可以帮助你!!