我需要创建许多图像(大约100.000现有,每天1000新,RGB,JPEG,最大尺寸800x800)的指纹,以便非常快速地将每个图像与每个其他图像进行比较.我不能使用二进制比较方法,因为也应该识别几乎相似的图像.
最好的是现有的库,但对现有算法的一些提示对我有很大的帮助.
正常散列或CRC计算算法不适用于图像数据.必须考虑信息的维度性质.
如果您需要非常强大的指纹识别,以便考虑仿射变换(缩放,旋转,平移,翻转),您可以在图像源上使用Radon变换来生成图像数据的标准映射 - 将其存储在每个图像和然后比较指纹.这是一个复杂的算法,不适合胆小的人.
一些简单的解决方案是可能的:
为图像创建光度直方图作为指纹
创建每个图像的缩小版本作为指纹
将技术(1)和(2)组合成混合方法以提高比较质量
亮度直方图(尤其是分成RGB分量的直方图)是图像的合理指纹 - 并且可以非常有效地实现.从另一个直方图中减去一个直方图将产生一个新的历史图,您可以处理该历史图以确定两个图像的相似程度.直方图,因为只评估光度/颜色信息的分布和出现处理仿射变换相当好.如果将每个颜色分量的亮度信息量化为8位值,则768字节的存储空间足以满足几乎任何合理大小的图像的指纹.当操纵图像中的颜色信息时,亮度直方图产生假阴性.如果应用对比度/亮度,海报,色移,光度信息变化等变换.某些类型的图像也可能出现误报,例如风景和图像,其中单一颜色支配其他图像.
使用缩放图像是将图像的信息密度降低到更容易比较的水平的另一种方法.降低到原始图像大小的10%以下通常会丢失太多的信息 - 因此800x800像素图像可以缩小到80x80,并且仍然提供足够的信息来执行适当的指纹识别.与直方图数据不同,当源分辨率具有不同的宽高比时,您必须执行图像数据的各向异性缩放.换句话说,将300x800图像缩小为80x80缩略图会导致图像变形,这样当与300x500图像(非常相似)相比时,会导致漏报.当涉及仿射变换时,缩略图指纹通常也会产生假阴性.如果您翻转或旋转图像,其缩略图将与原始图像完全不同,并可能导致误报.
结合这两种技术是一种合理的方式来对冲你的赌注并减少误报和漏报的出现.
与这里提出的缩小图像变体相比,它的特殊方法要少得多,它们保留了它们的一般风格,但它为正在发生的事情提供了更为严格的数学基础.
拍摄图像的Haar小波.基本上,Haar小波是从较低分辨率图像到每个较高分辨率图像的差异的连续性,但是根据您在mipmap的"树"中的深度加权.计算很简单.然后,一旦你对Haar小波进行了适当的加权,就扔掉除k个最大系数之外的所有系数(就绝对值而言),对矢量进行标准化并保存.
如果你取两个标准化向量的点积,它给你一个相似度量,1几乎相同.我在这里发布了更多信息.
你一定要看看phash.
对于图像比较,有这个PHP项目:https: //github.com/kennethrapp/phasher
我的小javascript克隆:https: //redaktorcms.com/dev/phasher/demo_js/index.html
不幸的是,这是基于"bitcount"的,但会识别旋转的图像.javascript中的另一种方法是通过画布的帮助从图像构建光度直方图.您可以在画布上可视化多边形直方图并比较数据库中的多边形(例如mySQL空间......)
这是视频直方图的演示:https: //redaktorcms.com/dev/globetrottr/testHashVideo.php
很久以前我在一个具有类似特征的系统上工作,这是我们遵循的算法的近似值:
将图片划分为区域.在我们的例子中,我们处理的是4:3分辨率视频,因此我们使用了12个区域.这样做可以将源图像的分辨率从图像中分离出来.
对于每个区域,计算整体颜色 - 区域中所有像素的平均值
对于整个图像,计算整体颜色 - 所有区域的平均值
因此,对于每个图像,您将存储n + 1
整数值,其中n
是您要跟踪的区域数.
对于比较,您还需要单独查看每个颜色通道.
对于整体图像,比较整体颜色的颜色通道,看它们是否在一定的阈值范围内 - 比如10%
如果图像在阈值内,则接下来比较每个区域.如果所有区域也在阈值范围内,则图像足够匹配,您至少可以标记它们以进行进一步比较.
这使您可以快速丢弃不匹配的图像; 您还可以使用更多区域和/或递归应用算法以获得更强的匹配置信度.
与Ic的答案类似 - 您可以尝试以多种分辨率比较图像.因此每个图像保存为1x1,2x2,4x4 .. 800x800.如果最低分辨率不匹配(受阈值限制),您可以立即拒绝它.如果它匹配,您可以在下一个更高的分辨率下比较它们,依此类推.
此外 - 如果图像共享任何类似的结构,例如医学图像,您可能能够将该结构提取到更容易/更快比较的描述中.