使用PHP + GD进行图像比较

11

如何使用php和GD库进行比较两张图片的最佳方法?

这是场景:

alt text

我有一张图片,想找出给定集合中与其最相似的图片。

最相似的图片实际上是同一张图片,不是像素完全匹配但确实是同一张图。

我在示例中用数字1夸大了两张图片的差异,以便更容易理解我的意思。

即使没有带来一致的结果,我的方法是使用imagecopyresampled函数将图像缩小到1px,并查看图像之间的RGB值有多接近。

从可能匹配的图像中的每个红、绿和蓝十进制等效值中扣除每个红、绿和蓝十进制等效值的总和给了我一个不相似的指数,即使最相似的RGB图片并不总是目标图片,但我可以使用它来选择一个可用的目标图片。

以下是将4张图片与目标图像进行比较时的输出示例, 在这种情况下,苹果公司的徽标匹配其中一张图片但不完全相同:

原始图片:

红色:222 绿色:226 蓝色:232

与以下进行比较:

http://a1.twimg.com/profile_images/571171388/logo-twitter_normal.png红色:183 绿色:212 蓝色:212,相似指数为56

红色:117 绿色:028 蓝色:028,相异指数为530

红色:218 绿色:221 蓝色:221,相异指数为13 匹配正确。

红色:061 绿色:063 蓝色:063,相异指数为491

可能无法比我已经得到的更好结果,我在这里浪费时间,但由于似乎有很多经验丰富的PHP程序员,所以我想你们可以指点我如何改进这个问题。

我愿意尝试其他的图像库,例如iMagickGmagickCairo,但我更喜欢避免使用PHP以外的其他语言。

提前致谢。


那么你想打败验证码? - Tor Valamo
不是验证码,图片和我说的一样,没有旋转,中间没有线条,也没有模糊。这是我正在进行的一个大项目的一部分,我似乎无法有效地解决这个问题。 - johnnyArt
可能是如何在PHP中检测相似图像?的重复问题。 - DanMan
5个回答

4
我认为你的方法似乎是合理的,但将整个图像缩小到1x1像素大小可能有些过分。然而,如果你将每个图像转换为相同的大小,然后计算每个16x16(或32x32、64x64等,具体取决于你想要使用多少处理时间/功率)单元格中的平均颜色,你应该能够形成某种合理的比较。

最终我使用了我的代码,既然你说它是合理的,那么,嘿,你得到了被接受的答案。 - johnnyArt
抱歉搅动了一个旧的帖子,但我正处于同样的情况。感谢链接imagecopyresampled,我可以调整图像大小,但是如何计算每个16x16图像中的平均颜色呢? - Marci-man
1
@Marci-man 在非常基本的层面上,您可以使用imagecolorat来获取“单元格”内像素的RGB值,然后对这些值取平均以获得整个单元格的值。 - John Parker

1

对于 PHP 8.1 或更高版本,您可以使用 https://github.com/sapientpro/image-comparator 库。它在底层使用 Gd 扩展。您还可以使用它来比较多个图像。

$comparator = new SapientPro\ImageComparator\ImageComparator();

$similarity = $comparator->compare('your-images/your-image1.jpg', 'your-images/your-image12.jpg');

echo $similarity; //89.3

0

我建议像middaparka一样,不要将图像降采样到1像素,因为您会失去所有的空间信息。将其降采样到16x16(或32x32等)肯定会提供更好的结果。

然后还取决于颜色信息对您是否重要。从我所了解的情况来看,您实际上可以不需要它,并从您的彩色图像(例如亮度)开始计算灰度图像并计算交叉相关性。如果像您说的那样,有几个图像完全匹配(除了颜色信息),这应该给您一个相当可靠的结果。


0

我使用了问题和答案中提到的缩放降采样灰度级的思路,利用GD库对两幅图像的像素通道值进行均方误差比较。

代码在这个答案中,包括了一个使用这些思路的测试。

此外,我进行了一些基准测试,发现在这些小图像中可能不需要降采样,因为该方法非常快(使用PHP),只需几分之一秒。


-1

使用middparka的方法,您可以将每个图像转换为一系列数字值,然后使用Levenshtein算法来查找最接近的匹配项。


3
莱文斯坦算法如何帮助这里?引用“两个字符串之间的莱文斯坦距离是将一个字符串转换为另一个字符串所需的最少操作次数”,因为所有序列都由三个两位数字组成,所需的操作次数始终为3。除非它们具有相同的红色、绿色或蓝色值,否则并不一定是最接近的颜色,也不一定是最相似的图像。 - johnnyArt
2
而且作为额外的奖励,PHP已经有了一个Levenshtein函数:http://php.net/manual/en/function.levenshtein.php - Marko

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