Ця публікація була відправною точкою мого рішення, тут багато хороших ідей, тому я хотів би поділитися своїми результатами. Основне розуміння полягає в тому, що я знайшов спосіб подолати повільність відповідності зображень на основі ключових точок, використовуючи швидкість фашу.
Для загального рішення найкраще використовувати кілька стратегій. Кожен алгоритм найкраще підходить для певних типів перетворень зображення, і ви можете цим скористатися.
Вгорі найшвидші алгоритми; внизу найповільніший (хоча і точніший). Ви можете пропустити повільні, якщо хороша відповідність буде знайдена на більш швидкому рівні.
- файловий хеш (md5, sha1 тощо) для точних дублікатів
- перцептивний хешинг (phash) для перетворених зображень
- на основі функцій (SIFT) для модифікованих зображень
У мене дуже хороші результати з фашем. Точність хороша для масштабованих зображень. Це не добре для (сприйнятих) модифікованих зображень (обрізаних, повернутих, дзеркальних тощо). Для боротьби зі швидкістю хешування ми повинні використовувати кеш-диск / базу даних, щоб підтримувати хеші для стога сіна.
Дійсно про фаш - це те, що коли ви створюєте свою хеш-базу даних (яка для мене становить близько 1000 зображень / с), пошук може бути дуже-дуже швидким, зокрема, коли ви можете зберігати всю базу даних хешу в пам'яті. Це досить практично, оскільки хеш - лише 8 байт.
Наприклад, якщо у вас є 1 мільйон зображень, він потребує масиву в 1 мільйон 64-бітних хеш-значень (8 МБ). На деяких процесорах це вписується в кеш L2 / L3! У практичному використанні я бачив порівняння corei7 зі швидкістю понад 1 гіга-хам / сек, це лише питання пропускної здатності пам’яті до процесора. База даних на 1 мільярд зображень практична для 64-бітного процесора (потрібно 8 Гб оперативної пам’яті), а пошук не перевищує 1 секунди!
Для модифікованих / обрізаних зображень це може здатися детектором функцій / детекторів ключових точок, як SIFT. SIFT створить хороші ключові точки, які будуть виявляти обрізання / обертання / дзеркало тощо. Однак порівняння дескриптора дуже повільне порівняно з дистанцією забивання, яку використовує фаш. Це головне обмеження. Можна порівняти багато, оскільки є максимальний дескриптор IxJxK порівняння для пошуку одного зображення (I = кількість зображень сіна, J = цільові ключові точки на зображення стога сіна, K = цільові ключові точки на зображення голки).
Щоб вирішити проблему зі швидкістю, я спробував використати фаш навколо кожної знайденої ключової точки, використовуючи розмір / радіус функції, щоб визначити підпрямокутник. Трюк в тому, щоб зробити цю роботу добре, полягає в зростанні / зменшенні радіусу для створення різних рівнів під прямою стрілкою (на зображенні голки). Зазвичай перший рівень (без шкали) буде відповідати, але часто це займає ще кілька. Я не на 100% впевнений, чому це працює, але я можу уявити, що це дозволяє занадто малі функції, щоб фаш працював (фаш масштабує зображення до 32х32).
Інша проблема полягає в тому, що SIFT не буде розподіляти ключові точки оптимально. Якщо є ділянка зображення з великою кількістю ребер, то ключові точки будуть кластеризуватися там, і ви не отримаєте жодної в іншій області. Я використовую GridAdaptedFeatureDetector у OpenCV для покращення розповсюдження. Не впевнений, який розмір сітки найкращий, я використовую невелику сітку (1x3 або 3x1 залежно від орієнтації зображення).
Ймовірно, ви хочете масштабувати всі зображення сіна (і голки) до меншого розміру до виявлення функції (я використовую 210 пікселів уздовж максимального розміру). Це зменшить шум у зображенні (завжди це проблема алгоритмів комп'ютерного зору), а також сфокусує детектор на більш помітних функціях.
Для зображень людей ви можете спробувати розпізнавання облич і використовувати його для визначення розміру зображення в масштабі та розміру сітки (наприклад, найбільше обличчя з масштабністю 100 пікселів). Детектор функцій враховує кілька масштабних рівнів (використовуючи піраміди), але є обмеження на кількість рівнів, які він буде використовувати (це можна налаштувати, звичайно).
Детектор ключових точок, мабуть, працює найкраще, коли він повертає менше кількості бажаних функцій. Наприклад, якщо ви попросите 400 і повернете 300, це добре. Якщо ви отримуєте 400 назад кожен раз, ймовірно, якісь хороші функції потрібно було залишити.
Зображення голки може мати менше ключових точок, ніж зображення сіна, і все ж отримувати хороші результати. Якщо додати більше, не обов'язково ви отримаєте величезні прибутки, наприклад, J = 400 і K = 40, мій показник враження становить близько 92%. При J = 400 і K = 400 частота влучень піднімається лише до 96%.
Ми можемо скористатися надзвичайною швидкістю функції забивання, щоб вирішити масштабування, обертання, дзеркальне відображення тощо. Можна використовувати багатопрохідну техніку. На кожній ітерації перетворіть підпрямокутники, перекройте хеш і запустіть функцію пошуку знову.