Търсене на изображения по съдържание в PHP (CBIR), Red Spirit
Блогът на Алексей Таянчин
Търсене на изображения по съдържание в PHP (CBIR)
Има задача - как да използвате PHP на сървъраза да проверите приликата на две изображения. Това е необходимо, за данамирате дубликати на изображения, качени на сайта. Основният проблем е, че имаме нужда от такъв алгоритъм за сравнение на изображения, така че да възприема правилно едни и същи изображения с различна яркост, с шум, с рамка, с различен мащаб и изместване настрани, и разбира се с различни формати, резолюция и дълбочина на цвета.Има голям брой алгоритми, от прости, базирани на сравняване на яркостта на две изображения, до сложни, базирани на „опорни точки“, възприемани от човешкото око (както в tineye.com). Преди това използвах прост скрипт, който беше изцяло внедрен в php и използваше принципа на разликата в яркостта. Но в действителност този метод се оказа пълна глупост, която понякога дори не можеше да разпознае две визуално абсолютно идентични изображения. И освен това скоростта на работа остави много да се желае (използвайки хешове - около 1,5 секунди на 1000 сравнения).
ImageMagick
Започнах да търся по-добри решения. Открих, чеImageMagick има интересен метод Imagick::compareImages, той простосравнява две изображения (преди това намалени до същата височина и ширина) и дава резултата, като взема предвид избрания показател (вижте примера). В резултат на това се връща масив с две стойности: разликата на изображенията във визуална форма (нов обект на изображениеimagick ) и числова стойност, която определяразликата между изображенията, колкото по-малка е, толкова по-малка е разликата. Ако е равно на нула, тогава снимките са 100% идентични.
Експериментирах с няколкостотин различни изображения заза да определите надеждно кой коефициент на разлика да зададете, така че снимките да се считат за идентични. Примерът по-долу показва, че преобразувах стойността$d съгласно формулата$d = round($d/1000), за да мога удобно да избирам прагови стойности. За себе си го определих така:
- 0 до 20 –същото
- 21 до 50 –подобни
- >50 -различни
Що се отнася докачеството на разпознаване, всичко ми хареса с този инструмент, но има минус - скоростта. Сама по себе си скоростта на зареждане на изображение и сравнението му е ниска (около 1 секунда на 1000 сравнения). Но освен това, вие също трябва да приведете изображението в общ размер и да го конвертирате в един формат, всичко това значително влияе на скоростта. Специални проблеми могат да възникнат сGIF, ImageMagick не винаги чете правилно анимираните gif файлове, така че трябва допълнително да извлечете първия кадър на анимация и да работите с него (кадър по кадър ImageMagick чете анимацията нормално). При всичко това няма начин от изображението да се извлече хеш или подпис, който да характеризира вече обработеното изображение и да се съхранява в базата данни за бърз достъп. Максимумът, който можете да направите, е да съхранявате намалени изображения в базата данни (например 30x30 png) и да работите с него без ненужни преобразувания. Но това е в-първо, намалява качеството на разпознаване, второ, значително натоварва базата данни и трето, скоростта не се увеличава толкова много. Вече го направих по този начин, скоростта беше все същата 900-1000 сравнения в секунда.
библиотека с пъзели
Тогава, с помощта на моя приятел ConstXife, научих за библиотеката Libpuzzle. Това нещо прави точно това, от което имам нужда. Програмата се доставя с изходни кодове, самата програма и отделен PHP модул за нея. Компилирах и инсталирах всичко без проблеми и спечелих от първия път.
Веднага харесахПъзел библиотека заради нейната скорост и възможност да съхранява много компактни подписи на изображения вMySQL. Тоест, за да използвате ефективно тази библиотека, трябва предварително да индексирате всички изображения, които ще участват в търсенето и да запазите индекса (сигнатурите) в базата данни, откъдето и да направите избор. Ето прост пример за използване на Libpuzzle: