在(纯)PHP / MySQL中查找类似的图像

时间:2012-07-04 17:53:04

标签: php mysql image similarity

我的用户正在将图片上传到我的网站,我想先向他们提供已上传的图片。我的想法是  1.为每个现有图像创建某种图像“哈希”  2.创建新上传图像的哈希值,并将其与数据库中的其他图像进行比较

我找到了一些有趣的解决方案,例如http://www.pureftpd.org/project/libpuzzlehttp://phash.org/等,但他们遇到了一个或多个问题

  1. 他们需要一些非标准的PHP扩展(或根本不是PHP) - 对我来说没关系,但是我想把它作为我的流行CMS的插件创建,它在许多托管环境中使用我的控制。
  2. 他们正在比较两个图像,但我需要比较一个到多个(例如数千个)并逐个进行将非常无效/慢... ...
  3. 我可以找到非常相似的图像(例如不同大小,重新保存的jpg或不同的jpg压缩因子)。

    我唯一的想法是将图片大小调整为例如5px * 5px * 256种颜色,创建它的字符串表示然后找到相同的颜色。但我猜它可能会产生微小的颜色差异,即使只有两个不同尺寸的相同图像,所以找到100%相同的图像将毫无用处。

    所以我需要一些良好的图像字符串表示格式,可以与某些SQL函数一起使用来查找类似或其他一些好方法。例如。 phash创建感知哈希,所以当两个数字接近时,图像也应该接近,所以我只需找到最近的距离。但它又是外部图书馆。

    有简单的方法吗?

4 个答案:

答案 0 :(得分:21)

我以前遇到过这个完全相同的问题。

随意复制我所做的事情,希望它能帮助您/解决您的问题。


我是如何解决的

我的第一个想法是失败,类似于你的想法,我最终为每一张图片(无论大小)制作字符串。但是我很快就解决了这个超快速填充你的数据库的问题,并且没有效果。

下一个选项(可行)是一个较小的图片(就像您的5px想法一样),而我确实做到了这一点,但使用了10px * 10px张图片。我为每个图像创建“哈希”的方式是imagecolorat()函数。

See php.net here.

当接收到图像的rgb颜色时,我将它们四舍五入到最近的50,以便颜色不那么具体。该数字(50)是您想要更改的内容,具体取决于您希望搜索的具体

例如:

// Pixel RGB
rgb(105, 126, 225) // Original
rgb(100, 150, 250) // After rounding numbers to nearest 50

对每个像素执行此操作后(10px * 10px将为您提供100 rgb()),然后我将它们转换为数组,并将它们存储在数据库中base64_encode()serialize()

在搜索相似的图像时,我对他们想要上传的图像执行完全相同的处理,然后从数据库中提取图像“哈希”以将它们全部进行比较,并查看匹配舍入的内容{{ 1}}的


提示

  • <{>>更大 rgb50四舍五入,不太具体您的搜索将是(反之亦然)

  • 如果您希望 SQL 更具体,那么最好在数据库中存储关于图像的额外/特定信息,以便您可以限制您在数据库中获得的搜索。的例如即可。如果宽高比为rgb,则仅从数据库中提取4:3周围的图像。 (等)

  • 可能很难完美地4:3 * 5px,因此建议为phpthumb。我用它的语法:

5px
祝你好运,希望我能帮忙。

答案 1 :(得分:2)

对于简易php实施,请查看:https://github.com/kennethrapp/phasher

然而 - 我想知道是否有一个用于“比较”的本机mySql函数(参见上面的php类)

答案 2 :(得分:0)

我将图像缩小到8x8然后我将RGB转换为1字节的HSV,因此结果散列是172字节的字符串。

HSVHSVHSVHSVHSVHSVHSVHSV... (from 8x8 block, 172 bytes long)
0fff0f3ffff4373f346fff00...

它不是100%准确(没有找到一些重复),但它很好用,看起来没有误报结果。

答案 3 :(得分:0)

以学术方式把它放下,你要找的是一个相似函数,它接收两个图像并返回两个图像的距离/相似程度。该指标很容易是十进制数,范围从-1到1(相隔很远)。完成此功能后,您可以将图像设置为参考,并将所有图像与其进行比较。然后找到相似的图像就像找到最接近的相似因子一样简单,这是通过在像MySQL这样的RDBMS中的双字段上进行简单搜索来完成的。

现在剩下的就是如何定义相似度函数。说实话,这是特定问题。这取决于你所谓的相似之处。但是covariance通常是一个很好的起点,它只需要你的两个图像具有相同的大小,我认为这没什么大不了的。然而,您可以找到许多其他想法来搜索“两个图像之间的相似性度量”。