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

发布于 12-12 18:58 字数 111 浏览 1 评论 0原文

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

我查了一下,好像没有这样的功能。我应该自己使用像素迭代器编写函数吗?

Is there any equality predicate function in ImageMagick library? I want to compare two images and find whether they are the exactly same (all colors of the pixels are the same) or have any differences.

I’ve looked around, but it seems not to have a such function. Should I write the function using pixel iterators by myself?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请爱~陌生人2024-12-19 18:58:50

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

在此处输入图像描述

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

ImageMagick provides the compare function to properly compare images.

Checking the md5 checksum of two images is not the correct approach, since some image formats (e.g. PNG and JPEG with EXIF for example), contain the date and time the file was created (see example 1) below, and some files can be visually identical but represented completely differently internally (see example 2), or have different bit-depths (see example 3).

Example 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

Why do these two differ in MD5? Because the date is in them...

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

Example 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

Example 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

Fuzzy Comparison of Images

As Kurt alludes to, this also leads to the possibility of doing a fuzzy compare of images. We can explore that like this:

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

enter image description here

Now multiply all pixels by 1.01 to make them an imperceptible 1% brighter:

# 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)

And now compare them, a few different ways:

# 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
手心的温暖2024-12-19 18:58:50

马克的回答很准确。然而,他忘记提到 compare 还可以返回“增量图像”,它将任何有差异的像素绘制为红色,而相同的像素将绘制为白色。

# 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 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 种不同的常见表示法格式返回 将 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。)

Mark's answer is spot-on. However, he forgot to mention that compare can also return a 'delta image', which will paint any pixel with differences as red, while identical pixels will be white.

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

Now compare the two:

compare wizard.png wizard.jpg delta.png

This is the 'delta.png':

delta.png

Lots of differences between PNG and JPEG! Ok, this is explained by the fact that JPEG is a lossy image format...

As you can see, the 'delta.png' has a pale background. If you do not want this background, but only red/white pixels, modify the compare command:

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

Also, you may want to ignore such differences which are below a certain threshold. Here the -fuzz N% parameter comes in handy.

You want blue pixels instead of red? And yellow ones instead of white? Here you go:

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

delta2.png

You want a textual description of all pixels which are different with their respective coordinates? Here the special output format *.txt may be good.

Try this:

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

The 'delta3.txt' file will be quite large, because it contains one line per pixel in this format:

# 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)
[....]

The first column gives the (row,column) pair of the respective pixel (counting is zero-based, the topmost, leftmost pixel has the address (0,0).

The next three columns return the respective pixel color, in 3 different common notation formats.

BTW, ImageMagick can convert the delta3.txt file back to a real image without any problem:

convert delta3.txt delta3.png

So to get all the pixels which are different (red) into a text file, you could do this:

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

To count the number of different pixels:

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

With -fuzz 6% I have 2269 different pixels. With -fuzz 0% I get 122474 different pixels. (Total number of pixels in these images was 307200.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文