知道两个图像是否相同的最有效方法?

时间:2014-03-23 08:07:26

标签: macos algorithm cocoa uiimage nsimage

现在在Cocoa工作。只想要一个超简单的图像相同的算法。不需要完美。只需要足够好。

3 个答案:

答案 0 :(得分:0)

这是一个建议,您的里程可能会有所不同。

创建一个包含大约10-100个图像的文件夹,或者只使用Cmd + Shift + 4进行10次屏幕抓取,并在屏幕区域周围绘制一个框。然后转到该文件夹​​并尝试下面的示例。

获取ImageMagick(免费提供here)您可以轻松获得图像统计信息,例如

convert *.png -format "%[fx:standard_deviation]" info:

convert *.png -format "%[fx:mean]" info:

这些将告诉您文件夹中所有图像的均值和标准。我的iMac每秒可以拍摄10张图像,每张100-300kB。

另一种比较方法,可能是将图像缩小为4x4像素,然后区分它们。

您也可以使用ImageMagick生成统计数据,因此要计算a.pgn和b.png两个图像之间的均方误差,您可以这样做:

compare -metric MSE a.png b.png /dev/null

其他选项是归一化互相关(NCC)和绝对错误计数(AE)。请查看this页面上的选项。

以下是一些例子。我从屏幕抓取开始a.png,然后用蓝色涂抹一点并将其保存为b.png,然后在整个右半部分涂成蓝色,并将其保存为c.png

a.png b.png c.png

然后我跑了:

# Compare Mean Squared Error of a.png with b.png (discarding result to /dev/null)
compare -metric MSE a.png b.png /dev/null 
47.5718 (0.0007259)

# Compare Mean Squared Error of a.png with c.png
compare -metric MSE a.png c.png /dev/null 
11893.9 (0.181489)

显然,a.pngb.png的距离与c.png的距离更近。

回到我刚才提到的简单平均值:

convert a.png -format "%[fx:mean]" info:
0.0595082

convert b.png -format "%[fx:mean]" info:
0.0600574

convert c.png -format "%[fx:mean]" info:
0.195744

请注意,b.png非常接近a.png,但c.png距离数英里。

如果性能很重要,请考虑将结果缓存在备用数据streem / resource fork / database中。

此外,所有Mac(Powerbooks和iMac)都是多核的,因此请考虑运行多个线程来并行处理图像。

在Mac上,您还可以使用SIPS(here))获取有关图像的信息.ImageMagick还有identifyhere) ,可以告诉您图像大小和色彩空间等。

此外,ImageMagick具有C语言绑定,因此您可以使用它们,或使用fork + exec或system()之类的东西来使用命令行版本。

答案 1 :(得分:0)

获取MD5(或其他)哈希是一种非常直接的方法,可能效率很高。例如,

// Very nice NSData category with different 
// hashes at https://gist.github.com/0xced/986427
#import "NSData+CommonDigest.h"

NSImage *image1 = ...
NSImage *image2 = ...
NSData *image1MD5 = [[image1 TIFFRepresentation] md5];
NSData *image2MD5 = [[image2 TIFFRepresentation] md5];
if ([image1MD5 isEqualToData:image2MD5]) {
    // image are the same
} else {
    // image are different
}

这将完全匹配,但是,如果您想启发式匹配,那么您当然可以定义一些可以比较图像的指标。例如,您可以细分图像并计算不同象限的平均RGB值;使用此信息作为指纹。如果图像按比例调整大小,那么这应该给出相同的结果。但是,如果图像被不成比例地裁剪或调整大小,那么您的milage可能会有所不同。这个问题通常很难,因为你必须接受误报。成功将取决于您的图像有多么不同以及您选择哪些指标进行比较。

答案 2 :(得分:0)

在大多数情况下,如果不一样的话,最快的方法就是纾困。 首先检查文件大小和名称以及其他简单元数据。 在那之后,检查第一个和最后N个字节是否相同,并且可能在中间的某个地方有一些N个字节。 更准确的方法是检查哈希值,但是对于大文件可能需要很长时间。 匹配的哈希值的百分比越多,就越接近确定的匹配。

通过快速排除简单的非匹配,您可以节省大部分时间。 您还可以在执行其他操作时在后台缓存哈希值。这有助于大部分比较更快。

逐字节比较是唯一100%准确的方法,但也是最慢的。