使用ImageMagick对图像进行平等测试

时间:2011-10-29 18:48:58

标签: comparison imagemagick equals equality

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

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

2 个答案:

答案 0 :(得分:4)

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

为什么这两个在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

示例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

示例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

图像的模糊比较

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

# Create a grey image, 100x100 and put some noise in it
convert -size 100x100 xc:gray +noise gaussian noise.png

enter image description here

现在将所有像素乘以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)

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

# 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

答案 1 :(得分:3)

马克的回答是正确的。然而,他忘了提到compare也可以返回'delta image',它会将差异绘制为红色的任何像素,而相同的像素将是白色。

# Create a PNG and a JPEG from the builtin 'wizard:' image:
convert wizard: wizard.png
convert wizard: wizard.jpg

现在比较两者:

compare wizard.png wizard.jpg delta.png

这是'delta.png':

delta.png

PNG和JPEG之间存在很多差异!好的,这是因为JPEG是有损图像格式......

如您所见,'delta.png'背景苍白。如果您不想要此背景,只需要红/白像素,请修改compare命令:

compare wizard.png wizard.jpg -compose src delta.png

此外,您可能希望忽略低于某个阈值的差异。这里-fuzz N%参数派上用场。

你想要蓝色像素而不是红色吗?而黄色而不是白色?你走了:

compare                  \
  -highlight-color blue  \
  -lowlight-color yellow \
  -fuzz 3%               \
   wizard.png            \
   wizard.jpg            \
   delta2.png

delta2.png

您想要一个与各自坐标不同的所有像素的文字说明吗?这里的特殊输出格式*.txt可能很好。

试试这个:

compare                  \
  -fuzz 6%               \
   wizard.png            \
   wizard.jpg            \
  -compose src           \
   delta3.txt

'delta3.txt'文件会非常大,因为它以这种格式包含每像素一行:

# ImageMagick pixel enumeration: 480,640,255,srgba
0,0: (255,255,255,0.8)  #FFFFFFCC  srgba(255,255,255,0.8)
1,0: (255,255,255,0.8)  #FFFFFFCC  srgba(255,255,255,0.8)
2,0: (255,255,255,0.8)  #FFFFFFCC  srgba(255,255,255,0.8)
[....]
77,80: (241,0,30,0.8)  #F1001ECC  srgba(241,0,30,0.8)
[....]

第一列给出了相应像素的(row,column)对(计数从零开始,最顶部,最左边的像素具有地址(0,0)

接下来的三列以3种不同的常用符号格式返回相应的像素颜色。

BTW,ImageMagick可以将delta3.txt文件转换回真实图像,没有任何问题:

convert delta3.txt delta3.png

因此,要将所有不同(红色)的像素放入文本文件中,您可以这样做:

compare                  \
  -fuzz 6%               \
   wizard.png            \
   wizard.jpg            \
  -compose src           \
   txt:-                 \
| grep -v '#FFFFFFCC' 

计算不同像素的数量:

compare                  \
  -fuzz 6%               \
   wizard.png            \
   wizard.jpg            \
  -compose src           \
   txt:-                 \
| grep -v '#FFFFFFCC'    \
| wc -l

使用-fuzz 6%我有2269个不同的像素。使用-fuzz 0%,我得到122474个不同的像素。 (这些图像中的像素总数为307200。)