Ответ 1
Вы можете использовать команду ImageMagick compare
для этого.
(Если вы успешно выполнили командную строку, вы можете перейти к использованию одного из API-интерфейсов ImageMagick: они доступны, среди прочих, для C
('MagickWand'), C++
(' Магический ++ '), Java
(' JMagick '), LISP
(' L-Magick '), .NET
(' Magick.NET '), Perl
(' PerlMagick '), PHP
(' IMagick '), Python
(' PythonMagick ') и Ruby
(' RMagick '). - Затем реализуйте соответствующие функции в своем приложении.)
Единственное требование: изображения должны иметь одинаковые размеры по ширине и высоте, измеренные в количестве пикселей. Таким образом, вам даже не нужен такой же формат, как вы предполагали.
Разницу можно вернуть по-разному:
-
Создайте визуальное представление различий, где пиксель с дельтами каким-то образом выделен в дельта-изображении.
-
Создайте текстовое и/или статистическое представление различий, где вывод - это одно или несколько чисел, или просто количество пикселей, которые являются разными, или какая-либо другая метрика.
Пример
Вот четыре примера изображений, которые можно сравнить. Они кажутся одинаково выглядящими, имеют размер 322x429 пикселей, но есть несколько более тонких различий в раскраске и формате: верхний правый - это JPEG, остальные три - PNG:
Визуальные сравнения
Вот самая простая команда для сравнения двух верхних изображений и создания визуальной "дельта":
compare \
http://i.stack.imgur.com/GBax7.png \
http://i.stack.imgur.com/D9IAV.jpg \
delta1.pdf
Это сравнивает PNG с JPEG и создает PDF в качестве вывода. Для визуального впечатления от этого выхода см. Изображение ниже слева (так как PDF файлы не отображаются здесь, я прибегал к созданию PNG и вместо этого использовал это для отображения).
Что сделала эта самая простая из всех команд ImageMagick compare
?
- Он использовал первое изображение в качестве бледного фона.
- Он накладывает красные, полностью непрозрачные пиксели в каждом месте, где цвет соответствующего пикселя во втором изображении отличается от первого.
(Я мог бы добавить -highlight-color blue
и -lowlight-color yellow
или любые другие определения цвета, если бы я не хотел, чтобы красная подсветка по умолчанию)
Что делать, если мне не нужно такое точное сравнение цветов пикселей? Что делать, если я хочу красный пиксель только тогда, когда есть более значительное расстояние между соответствующими пикселями?
Легко: добавьте в командную строку фактор "пух"!
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 Очистить ColorBurn ColorDodge Раскрасить CopyBlack CopyBlue CopyCyan КопироватьGreen Copy CopyMagenta CopyOpacity CopyRed CopyYellow Darken DarkenIntensity DivideDst DivideSrc Dst Разница Разложите Distolve Distort DstAtop DstIn DstOut DstOver Исключение HardLight HardMix Hue In Lighten LightenIntensity LinearBurn LinearDodge LinearLight Luminize Mathematics MinusDst MinusSrc Modulate ModulusAdd ModulusSubtract Multiply None Out Overlay Over PegtopLight PinLight Plus Замените насыщенный экран 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
- center right -
-compose MinusDst
- внизу слева
-compose Hue
- внизу справа
-compose LightenIntensity
Примечание: если вы поменяете порядок двух сравниваемых изображений, две результирующие дельта могут быть значительно разными двумя!
<Т411 >
Теперь вы уже можете начать свои собственные эксперименты с визуального сравнения двух похожих изображений.
Метрические результаты
Чтобы сгенерировать метрики о различиях двух изображений, вы можете запустить команду следующим образом:
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
( "перцептивный хэш" ). Это единственный, который не требует одинаковых размеров для двух сравниваемых изображений. Это действительно лучшая "метрика", чтобы сузить похожие изображения (или, по крайней мере, надежно исключить эти пары изображений, которые выглядят совсем по-другому), не глядя "на них", в командной строке и программно.
Один хороший эксперимент для запуска - это когда вы сравниваете изображение с самим собой. Он показывает, как соответствующая метрика переводит "личность" в ее собственную среду:
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)
Как вы можете видеть, каждый метод метрики возвращает 0
, кроме двух: PSNR возвращает infinity
, а NCC возвращает 1.00001
.
Запустите эту же команду и сравните чистый белый патч размером 100x100 пикселей с чистым черным:
for i in $(compare -list metric); do \
compare \
-metric $i \
-size 100x100 \
xc:white \
xc:black \
null: \
done
Это возвращает следующий результат:
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
) различны. Большинство других результатов также легко понять, если вы читаете и оцениваете, что означают соответствующие значения метрик....
Наконец, рассмотрим вывод каждой доступной метрики при сравнении двух верхних изображений (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)
Теперь выберите свой показатель!: -)