计算图像“视觉”校验和的最快方法

4
我想创建一个图像分类的ID系统。由于更改图像的EXIF标签会导致md5()函数的结果发生变化,因此我无法使用该函数。
目前我正在使用ImageMagick计算的SHA1校验和。在较大的图像上(21百万像素的JPG),它的速度非常慢,需要约15秒才能运行完毕,即使是四核心的Xeon处理器也如此。
是否有其他“视觉”方法可以更快地唯一识别图像?
4个回答

3

您可以尝试在实际位图数据上运行MD5,而不是JPEG文件。我在我的机器上进行了测试(也是四核Xeon),以下代码在一个2300万像素的图像上运行大约需要900毫秒。

uint32_t width  = MagickGetImageWidth(imageWand);
uint32_t height = MagickGetImageHeight(imageWand);

uint8_t *imageData = malloc(width * height * 3);

MagickExportImagePixels(imageWand,
   0, 0, width, height, "RGB", CharPixel, imageData);

unsigned char *imageDigest = MD5(imageData, width * height * 3, NULL);

free(imageData);

1
你能指出你使用的MD5函数库吗? - Tahseen

3
你所说的“视觉校验和”是什么意思?你提到的算法(MD5 / SHA / CRC)是按字节进行处理的,但不考虑图像的视觉信息。如果将其中一个图像转换为JPEG格式,则两个文件将显示相同的图像,但具有完全不同的MD5 / SHA / CRC校验和。
如果你只担心Exif编辑,可以暂时复制图像,使用exiv2库剥离其所有元数据,然后运行校验和算法。我想这比手动缩小图像要快得多。您还可以通过仅使用源文件的前n千字节来加快计算速度。
如果所有图像文件都直接来自相机,那就更好了:您可以使用exiv2提取预生成的Exif缩略图(通常只有几千字节),并计算其校验和。
关于缩小比例的方法:还要注意ImageMagick可能会在未来更改其缩放算法,这将使您的校验和无效(缩小版本的字节结构将发生变化)。

校验嵌入式预览是个好主意。我至少会这样做。但对于没有这个的图片,我应该有一个备份计划。嗯,也许可以将校验和存储在exif签名位置(或iptc中),以便以后进行超快速检查。 - odinho - Velmont

1

正如Todd Yandell所指出的那样,MD5可能已经足够快了。如果不行,您可以通过使用32位或64位CRC来获得更快的校验和。主要区别在于任何人都可以用相同的CRC编造一个新图像;欺骗非常容易。对于某人欺骗MD5校验和则相当困难。次要区别是CRC具有更少的位数,但除非您拥有大量图像,否则碰撞仍然不太可能发生。

exiftool声称能够从JPEG文件中提取二进制图像,以便您可以在不解压缩的情况下计算校验和,但我无法从手册中找到如何执行此操作的方法。

我在一台笔记本电脑上进行了一些实验,使用Intel Core 2 Duo L7100 CPU,一个8MP的JPEG图像大约需要1秒钟压缩到PPM格式,然后再花费1秒钟进行校验和。使用md5sumsumsha1sum进行校验和的时间并没有显著不同。因此,你最好找到一种方法,在不解压缩的情况下提取二进制数据。

我还注意到,即使使用更少的像素,您的校验和也几乎同样好。比较这两个:

djpeg -scale 1/8 big.jpg | /usr/bin/sha1sum   # 0.70s
djpeg            big.jpg | /usr/bin/sha1sum   # 2.15s

0
你应该考虑到有人可能会裁剪图像或修改调色板、颜色深度或其他内容,这样一个平面校验和就会不同,即使在视觉上原始图像和修改后的图像看起来仍然非常相似。 也许有一种有效的算法可以用于裁剪或重新着色的图像,就像谷歌图片用于搜索相似图片的算法一样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接