使用 ImageMagick 对图像进行相等性测试

min*_*hee 2 comparison equality equals imagemagick

ImageMagick 库中是否有相等谓词函数?我想比较两个图像并找出它们是否完全相同(像素的所有颜色都相同)或有任何差异。

我环顾四周,但似乎没有这样的功能。我应该自己使用像素迭代器编写函数吗?

Mar*_*ell 7

ImageMagick 提供了compare正确比较图像的功能。

检查md5两个图像的校验和不是正确的方法,因为某些图像格式(例如带有 EXIF 的 PNG 和 JPEG)包含文件创建的日期和时间(参见示例 1),并且某些文件在视觉上可能相同但在内部表示完全不同(参见示例 2),或者具有不同的位深度(参见示例 3)。

示例 1

# Create two identical images (100x100 pixels, bright red) but with different file contents
convert -size 100x100 xc:red r1.png
convert -size 100x100 xc:red r2.png

# MD5 checksum them
md5 r?.png
MD5 (r1.png) = 9f6d612615efd88c3fd8521d717e9811
MD5 (r2.png) = 996911bec0e0da75af46a1e78c052998      # Mmmm different

# Ask IM to tell us absolute error between the two (number of differing pixels)
compare -metric AE r1.png r2.png null:
0                                                    # No difference - that's better
Run Code Online (Sandbox Code Playgroud)

为什么这两者在 MD5 中不同?因为日期在他们...

identify -verbose r[12].png | grep -i date
date:create: 2015-03-03T14:57:26+00:00
date:modify: 2015-03-03T14:57:26+00:00
date:create: 2015-03-03T14:57:43+00:00
date:modify: 2015-03-03T14:57:43+00:00
Run Code Online (Sandbox Code Playgroud)

示例 2

# Create PNG and identical GIF
convert -size 100x100 xc:red r.png
convert -size 100x100 xc:red r.gif

# Compare with MD5 sums
md5 r.png r.gif
MD5 (r.png) = 692ef06b62a15b799d5dc549b0dd3737
MD5 (r.gif) = 549feea78dc438924fbb3e0ef97dc0b3         # Ooops

# Compare properly
compare -metric AE r.gif r.png null:
0                                                      # Identical
Run Code Online (Sandbox Code Playgroud)

示例 3

# Create 8-bit PNG and 16-bit PNG
convert -size 100x100 xc:red PNG8:8.png
convert -size 100x100 xc:red PNG48:48.png

# MD5 sum them
md5 8.png 48.png
MD5 (8.png) = eb3fc9a06e1632c3b41ebb986b81a816
MD5 (48.png) = 32fdf1c30793a4fed941c91d27084e0a   # Ooops

# Let ImageMagick compare them
compare -metric AE 8.png 48.png  null:
0
Run Code Online (Sandbox Code Playgroud)

图像的模糊比较

正如库尔特所暗示的那样,这也导致了对图像进行模糊比较的可能性。我们可以这样探索:

# Create a grey image, 100x100 and put some noise in it
convert -size 100x100 xc:gray +noise gaussian noise.png
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

现在将所有像素乘以 1.01,使它们不易察觉地亮 1%:

# Make pixels 1% brighter
convert noise.png -evaluate multiply 1.01 brighternoise.png

# ... and compare the statistics of the two images
identify -verbose *noise* | grep -E "^Image|mean"

Image: brighternoise.png
  mean: 127.235 (0.498959)       <--- The brighter image is, well, brighter
Image: noise.png
  mean: 126.175 (0.494805)
Run Code Online (Sandbox Code Playgroud)

现在比较它们,几种不同的方式:

# Pixels may differ by up to 2% before being considered different
compare -fuzz 2% -metric AE noise.png brighternoise.png null:
0        # All pixel values within 2% between the 2 images

# Pixels may only differ by 0.5% before being considered different
compare -fuzz 0.5% -metric AE noise.png brighternoise.png null:
594      # 594 of the 10,000 pixels differ by more than 0.5%

# Calculate Root Mean Square Error (RMSE) to see how much pixels tend to differ
compare -metric RMSE noise.png brighternoise.png null:
278.96 (0.00425666)    # On average, the pixels differ by 0.4% - i.e. hardly at all
Run Code Online (Sandbox Code Playgroud)