我们能否以编程方式比较相同分辨率的不同图像?

Can we programmatically compare different images of same resolutions?

有没有一种比较可靠的方法来比较相同格式和相同分辨率的图像并找出它们之间的差异?

在最好的情况下,我正在寻找可以比较的图像的一些数字表示,因为我必须比较很多图像。

您可以使用 ImageMagick 的 compare 命令来执行此操作。

(如果您成功使用命令行,则可以继续使用 ImageMagick 的 API 之一:除其他外,这些 API 可用于 C'MagickWand'), C++ ('Magick++'), Java ('JMagick'), LISP ('L-Magick'), .NET ('Magick.NET'), [28=] ('PerlMagick'), PHP ('IMagick') , Python ('PythonMagick') 和 Ruby ('RMagick'). -- 然后将各自的功能实现到您自己的应用程序中。)

唯一的要求是:图片需要具有相同的宽度和高度尺寸(以像素数衡量)。所以你甚至不需要你假设的格式

差额可以通过不同的方式返回:

  • 生成差异的视觉表示,其中具有增量的像素以某种方式在增量图像中突出显示。

  • 生成差异的文本 and/or 统计表示,其中输出是一个或多个数字,或者只是不同的像素数,或其他一些指标。


例子

这里有四个示例图像可以进行比较。它们每个看起来都相似,大小为 322x429 像素——但在颜色和格式上有一些细微的差别:右上角的是 JPEG,其他三个是 PNG:

视觉比较

这是最简单的命令,用于比较前两张图像并生成视觉效果 'delta':

compare                              \
  http://i.stack.imgur.com/GBax7.png \
  http://i.stack.imgur.com/D9IAV.jpg \
  delta1.pdf

这会将 PNG 与 JPEG 进行比较并生成 PDF 作为输出。对于此输出的视觉印象,请参见左下图(由于此处无法显示 PDF,我确实求助于生成 PNG 并使用它来显示)。

这个最简单的 ImageMagick compare 命令到底做了什么?

  1. 它使用第一张图像作为浅色背景。
  2. 它在第二张图像中相应像素的颜色与第一张图像不同的每个位置上覆盖了完全不透明的红色像素。

(如果我不想要默认的红色突出显示,我可以添加 -highlight-color blue-lowlight-color yellow 或任何其他颜色定义)

如果我不想要这样的 over-exact 像素颜色比较怎么办?如果我只在各个像素之间有更大的颜色距离时才想要红色像素怎么办?

简单:在命令行中添加一个'fuzz'因素!

compare                              \
  http://i.stack.imgur.com/GBax7.png \
  http://i.stack.imgur.com/D9IAV.jpg \
 -fuzz 2.5%                          \
  delta2.png

当运行第一个(最简单的)比较命令没有附加参数时,ImageMagick 默默地添加了其默认比较方法的规范,称为-compose src-over

当然我们可以覆盖它并使用不同的合成模式。如何了解可用的合成模式?命令 convert -list compose 将为我们枚举它们!这是完整的列表——它在我的系统中包含 67 个不同的列表:

Atop Blend Blur Bumpmap ChangeMask Clear ColorBurn ColorDodge Colorize CopyBlack CopyBlue CopyCyan CopyGreen Copy CopyMagenta CopyOpacity CopyRed CopyYellow Darken DarkenIntensity DivideDst DivideSrc Dst Difference Displace Dissolve Distort DstAtop DstIn DstOut DstOver Exclusion HardLight HardMix Hue In Lighten LightenIntensity LinearBurn LinearDodge LinearLight Luminize Mathematics MinusDst MinusSrc Modulate ModulusAdd ModulusSubtract Multiply None Out Overlay Over PegtopLight PinLight Plus Replace Saturate Screen SoftLight Src SrcAtop SrcIn SrcOut SrcOver VividLight Xor

让我们尝试每一个:

for i in $(convert -list compose|tr "\n" " "); do \
  compare                                         \
     http://i.stack.imgur.com/GBax7.png           \
     http://i.stack.imgur.com/D9IAV.jpg           \
    -compose ${i}                                 \
     delta-${i}.png ;                             \
done

当然,现在显示每一个生成的增量图像就太过分了。最有趣的如下:

  • 左上角是-compose Difference
  • 右上角是-compose DivideSrc
  • 中间左边是 -compose CopyBlue
  • 中间右边是-compose MinusDst
  • 左下方是-compose Hue
  • 右下角是-compose LightenIntensity

注意:如果交换两个比较图像的顺序,则两个结果增量可能会有很大不同!

现在您已经可以开始自己的实验,通过视觉比较两个相似的图像。

测量结果

要生成关于两个图像差异的指标,您可以运行这样的命令:

compare                               \
  -metric rmse                        \
   http://i.stack.imgur.com/GBax7.png \
   http://i.stack.imgur.com/D9IAV.jpg \
   null:

rmse 均方根误差 的缩写。以上示例图像的结果给出:

 1339.53 (0.02044)

支持多少种不同的度量方法?

以下命令针对当前版本的 ImageMagick 枚举给定系统上所有可用的比较指标方法:

compare -list metric 

在我的笔记本上,这些是:

AE Fuzz MAE MEPP MSE NCC PAE PHASH PSNR RMSE

这些缩写的含义是:

AE     absolute error count, number of different pixels (`-fuzz` effected)
FUZZ   mean color distance
MAE    mean absolute error (normalized), average channel error distance
MEPP   mean error per pixel (normalized mean error, normalized peak error)
MSE    mean error squared, average of the channel error squared
NCC    normalized cross correlation
PAE    peak absolute (normalized peak absolute)
PHASH  perceptual hash
PSNR   peak signal to noise ratio
RMSE   root mean squared (normalized root mean squared)

一个有趣的(也是相对较新的)指标是 phash ('perceptual hash')。它是唯一一个不要求两个比较图像具有相同尺寸的图像。最好 'metric' 缩小看起来相似的图像(或者至少可靠地排除这些看起来非常不同的图像对)而无需真正 "looking at them",在命令行和程序调用上.

运行 的一个很好的实验是将图像与其自身进行比较。它显示了相应的指标如何将 'identity' 转化为它自己的环境:

for i in $(compare -list metric); do     \
    compare                              \
     -metric $i                          \
      http://i.stack.imgur.com/GBax7.png \
      http://i.stack.imgur.com/GBax7.png \
      null:                              \
done

这是结果:

AE    :   0
Fuzz  :   0 (0)
MAE   :   0 (0)
MEPP  :   0 (0, 0)
MSE   :   0 (0)
NCC   :   1.00001
PAE   :   0 (0)
PHASH :   0
PSNR  :   inf
RMSE :    0 (0)

如您所见,每个度量方法 returns 0,除了两个:PSNR returns infinity 和 NCC returns 1.00001.

运行 使用相同的命令并将 100x100 像素的纯白色补丁与纯黑色补丁进行比较:

for i in $(compare -list metric); do \
  compare                            \
     -metric $i                      \
     -size 100x100                   \
      xc:white                       \
      xc:black                       \
      null:                          \
done

这returns结果如下:

AE    :   10000
Fuzz  :   65535 (1)
MAE   :   65535 (1)
MEPP  :   1.96605e+09 (1.00003, 1)
MSE   :   65535 (1)
NCC   :   0
PAE   :   65535 (1)
PHASH :   417.941
PSNR  :   0
RMSE  :   65535 (1)

AE 指标符合预期:10000 个像素(来自 -size 100x100)不同。一旦您 read up and grokked 各个指标定义的含义,大多数其他结果也很容易理解....

最后,让我们看看在比较上面的前两张图片(PNG 和 JPEG)时每个可用指标的输出:

for i in $(compare -list metric); do     \
    compare -metric $i                   \
      http://i.stack.imgur.com/GBax7.png \
      http://i.stack.imgur.com/D9IAV.jpg \
      null:                              \
done

AE    :   74200
Fuzz  :   1339.53 (0.02044)
MAE   :   499.997 (0.00762946)
MEPP  :   2.07206e+08 (0.000417654, 0.435294)
MSE   :   27.3801 (0.000417793)
NCC   :   0.99709
PAE   :   28527 (0.435294)
PHASH :   0.745389
PSNR  :   33.7904
RMSE  :   1339.53 (0.02044)

现在选择您的指标! :-)