Тема: Простенький алгоритм для порівняння картинок
Нарешті добравсі до написання коду на тому Nim'і. Скажу відразу — воно не набагато легше за C, але суть не в тому..
Якщо пам'ятаєте, то коли я вперше писав програмку для порівняння картинок, то я використовував алгоритм, котрий просто зменшував їх до розміру 64x64, потім робив всі пікселі чорно-білими (мається на увазі, що всі компоненти пікселя були однакові, в діапазоні від 0 до 255, а не просто чорні, або білі), ну а потім відбувалось порівняння кожного пікселя першої картинки з відповідним пікселем іншої, і підраховувалась кількість відмінних пікселів, якщо такі були — одже картинки не є ідентичними.
Далі я експериментував з картинками, котрі лише незначною мірою відрізняються, наприклад, якщо намалювати невеличку рисочку на одній з картинок, тоді кількість відмінних пікселів була не дуже великою, і таку картинку можна було б позначити, як потенційно такою ж самою, і тоді користувач сам повинен був би визначити, що з нею робити, залишати, чи ні.
Але я не передбачив одного випадку, коли кількість відмінних пікселів досить значна, хоча картинки практично ідентичні...
Сталося це от як...
Я відкрив картинку в GIMP'і, та затер декілька маленьких пташок у верхньому правому куті картинки. Якщо не дуже приглядатись, то цієї зміни навіть не видно було б. Потім я зберіг картинку, але при збереженні GIMP попросив мене обрати якість цієї картинки, вона була встановлена в 90%, і я її такою і залишив.
Після збереження картинки та порівняння її з оригіналом, виявилось, що 1017 пікселів з 4096 були різними!!!
А так трапилось, тому що оте налаштування якості картинки трішечки змінило чимало пікселів. Оку важко помітити різницю між 134 та 136, але програмка це бачить, та рахує такі пікселі як різні.
Виникає питання — як тоді розкермувати подібну ситуацію, адже очевидно, що ми не можемо використовувати коефіцієнт різних пікселів для того, аби судити, на скільки картинки є різними, бо в цьому випадку коефіцієнт буде аж 1017/4096 = ~0.25%, тобто, картинки різні на 25%, хоча це зовсім не так.
Далі виникає думка — а що, якщо брати до уваги "силу" різності між двома різними пікселями, тобто, рахувати відмінність усіх пікселів, замість того, аби рахувати кількість відмінних пікселів. В моєму випадку ця сума була лише 3012, вона досить мала, в порівнянні з сумою відмінностей між дійсно різними картинками — 341245.
Тоді можна взяти число, котре б представляло максимальну відмінність картинок, та ділити його на нашу суму відмінностей, цей коефіцієнт показуватиме вже хоч щось, але яке число використати як максимально можливу відмінність?
Якщо кожен піксель має значення від 0 до 255, і таких пікселів 4096, то може треба просто помножити 255 на 4096, а це буде 1044480, і тоді для першої пари картинок відмінність буде 3012 / 1044480 = ~0.003 що є дуже мало, враховуючи, що максимальний коефіцієнт буде 1. Тоді для другої пари картинок, котрі вже дійсно різні, цей коефіцієнт сягатиме 341245 / 1044480 = 0.32, а це вже дійсно чимало.
Подібний підрахунок відмінностей видається досить непоганим, але він працює лише для таких відмінностей, що рівномірно розподілені по картинці, але якщо відмінності зустрічаються в деяких конкретних місцях картинки, то загальна сума відмінностей може бути не дуже великою, але людське око точно помітить це (як вважаєте?).
Було б непогано, аби алгоритм розумів, коли відмінності є скупченими в одному, або декількох місцях, а коли вони рівномірно розподілені.