вторник, 11 октября 2011 г.

Linux. How to compare images?

Linux в самом деле удивительная операционная система.
В процессе разбора картинок wallpapers появилась задача убрать дубликаты.
Нетривиальная задача. Правда?

Но оказалось не все так сложно. Сейчас объясню.
Вот две картинки:



На вид они абсолютно одинаковы, имеют одинаковый размер.
Но, если посчитать хеш, то он будет разный, а утилита для сравнения картинок покажет, что они значительно отличаются:
$ perceptualdiff img-l-1.tif img-l-2.tif FAIL: Images are visibly different 5456 pixels are different $ echo $? 0 $

Как говорит старая мудрость: "Черт прячется в деталях". Так и здесь, видимо одна картинка получена из другой с помощью отличных друг от друга преобразований. Чтобы убрать лишние детали нужно увеличить размер пикселя, или, что тоже самое отмасштабировать картинки в маленький размер.
Что при этом произойдет?
Программа масштабирования, чтобы сохранить картинку картинкой при объединении пикселей возьмет средние значения цветов, яркости и контрастности. Во время этой операции шум внесенный в картинку будет с высокой вероятностью удален.
$ convert -resize 30 img-l-1.tif img-s-1.tif $ convert -resize 30 img-l-2.tif img-s-2.tif $
Я отмасштабировал картинки до ширины в 30 пикселей, а в блоге увеличил, чтобы показать, что из этого получается:


Теперь сравним их опять:
$ perceptualdiff img-s-1.tif img-s-2.tif PASS: Images are perceptually indistinguishable $ echo $? 1 $

Вуаля! А не какая не виола.
Теперь, вооружившись этими знаниями не составляет труда написать простенький скрипт по удалению дубликатов изображений.


Очень важно:
  • Очень важно правильно выбрать количество пикселей в картинках, которые будут сравниваться. Если, как я указал в примере, ужимать до 30 пикселей в ширину, то вероятность ложных срабатываний достаточно велика. Опытным путем установлено, что 100 пикселей в ширину - оптимальный размер для выявления дубликатов.
  • Скрипт, который я написал относится к категории brute force, На ноутбуке Thinkpad x220 с процессором i7 2620 на обработку 1600 картинок требуется около 15 часов.


Полезные ссылки: