Проверка на равенство изображений с использованием ImageMagick - PullRequest
1 голос
/ 29 октября 2011

Есть ли какая-либо функция предиката равенства в библиотеке ImageMagick? Я хочу сравнить два изображения и определить, являются ли они одинаковыми (все цвета пикселей одинаковы) или имеют какие-либо различия.

Я оглянулся, но, похоже, такой функции нет. Должен ли я сам написать функцию, используя пиксельные итераторы?

Ответы [ 2 ]

4 голосов
/ 03 марта 2015

ImageMagick предоставляет функцию compare для правильного сравнения изображений.

Проверка контрольной суммы md5 двух изображений не является правильным подходом, поскольку некоторые форматы изображений (например, PNG и JPEG с EXIF, например), содержат дату и время создания файла (см. Пример 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

Нечеткое сравнение изображений

Как намекает Курт, это также приводит к возможности нечеткого сравнения изображений. Мы можем исследовать это так:

# 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
3 голосов
/ 04 марта 2015

Ответ Марка точен.Однако он забыл упомянуть, что 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:

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различные распространенные форматы обозначений.

Кстати, 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.)

...