【问题标题】:Find similar images in (pure) PHP / MySQL在(纯)PHP / MySQL 中查找类似图像
【发布时间】:2012-07-05 05:22:02
【问题描述】:

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

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

  1. 他们需要一些非标准的 PHP 扩展(或者根本不在 PHP 中)——这对我来说没问题,但我想将它创建为我流行的 CMS 的插件,它在许多托管环境中使用,没有我的控制。
  2. 他们正在比较两个图像,但我需要一对多(例如数千个)进行比较,并且一张一张地进行比较会非常无效/缓慢...... ...

我可以只找到非常相似的图像(例如不同的大小、重新保存的 jpg 或不同的 jpg 压缩系数)。

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

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

有什么简单的方法吗?

【问题讨论】:

  • 您的想法还不错,256 种颜色不会给您带来“微小差异”。如果是这样,请降低该数字。另一个重要问题:您的图像哈希应该足以处理小图像旋转。
  • 我刚刚想到的关于在散列中处理图像旋转的一个想法是将散列分成四个大小相等的部分并旋转图像,使平均值最低的部分位于左下角。
  • pHash 不会“比较两个图像”。它计算每个图像的哈希值,并认为相似的图像具有相似的哈希值。然后,您可以使用特殊的数据结构来存储您的图像哈希,并有效地查找与上传图像的哈希相似的哈希(例如图像)。

标签: php mysql image similarity


【解决方案1】:

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

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


我是如何解决的

我的第一个失败的想法与您可能的想法类似,是我最终为每张图片制作了字符串(无论大小)。但我很快发现这会超快地填充您的数据库,但效果不佳。

下一个选项(有效)是一个较小的图像(就像你的 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() 和@987654336 存储在数据库中@。

在搜索相似的图像时,我对他们要上传的图像执行了完全相同的过程,然后从数据库中提取图像“哈希”以比较它们,并查看匹配的四舍五入 @987654337 @的。


提示

  • 50rgb 舍入中的更大,您的搜索将不太具体(反之亦然)。

  • 如果您希望您的 SQL 更具体,最好将有关图像的 extra/specific 信息存储在数据库中,以便您可以限制您在数据库中获得的搜索。 例如。如果纵横比为4:3,则仅从数据库中拉取4:3 周围的图像。 (等)

  • 很难完美地得到这个5px*5px,所以建议是phpthumb。我使用它的语法:

phpthumb.php?src=IMAGE_NAME_HERE.png&w=10&h=10&zc=1
// &w=  width of your image
// &h=  height of your image
// &zc= zoom control. 0:Keep aspect ratio, 1:Change to suit your width+height

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

【讨论】:

  • 这是一个很好的答案。与您和其他人分享的一点是,当您将 RGB 值四舍五入到最接近的 50 时,您一定会得到重复的颜色(我为许多照片做过)。通过使用 PHP 的 array_unique() 函数,这清除了所有重复项,只剩下 28 种颜色要存储 - 需要担心的数量要少得多。
  • 将 RGB 三重奏四舍五入到最接近的 50 会为您提供最接近的颜色是不正确的,因此会考虑大而相似的图像。 124、76、76 和 76,76,124(红色和蓝色)将变成 100,100,100(灰色)。最好将 RGB 转换为整数(从 0 到 16777216),然后以百或千取整。这将为您提供更好的方法来处理相似的色调和颜色。
  • 我有类似的问题(想在上传之前识别重复的照片),但我看不出你在这里所做的与 phash (github.com/jenssegers/imagehash) 有何不同?为什么这种方法是有利的?它们都产生一个字符串,必须进行比较才能找到附近的重复项。
【解决方案2】:

简单的 php 实现请查看:https://github.com/kennethrapp/phasher

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

【讨论】:

    【解决方案3】:

    我将图像缩小为 8x8,然后将 RGB 转换为 1 字节 HSV,因此结果哈希为 172 字节字符串。

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

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

    【讨论】:

      【解决方案4】:

      从学术角度来说,您正在寻找的是一个相似度函数,它接收两个图像并返回一个指示两个图像有多远/相似的指标。这个指标很容易是一个从 -1 到 1 的十进制数(相距很远到很近)。拥有此功能后,您可以将图像设置为参考并将所有图像与其进行比较。然后找到与一张相似的图像就像找到与其最接近的相似因子一样简单,只需在 MySQL 等 RDBMS 中的双字段上进行简单搜索即可。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-04
        • 1970-01-01
        • 2010-12-30
        • 2021-08-30
        • 2012-08-25
        • 2013-08-03
        • 2023-03-12
        • 1970-01-01
        相关资源
        最近更新 更多