Это сообщение было отправной точкой для моего решения, здесь было много хороших идей, поэтому я бы поделился своими результатами. Основное понимание заключается в том, что я нашел способ обойти медленность сопоставления изображений на основе ключевых слов, используя скорость фашизма.
Для общего решения лучше всего использовать несколько стратегий. Каждый алгоритм лучше всего подходит для определенных типов преобразований изображений, и вы можете воспользоваться этим.
Вверху, самые быстрые алгоритмы; внизу - самый медленный (хотя и более точный). Вы можете пропустить медленные, если хорошее совпадение будет найдено на более высоком уровне.
- на основе файла-хэш (md5, sha1 и т.д.) для точных дубликатов
- перцептивного хеширование (phash) для масштабированно- изображений
- функцию на основе (SIFT) для измененных изображений
I я получаю очень хорошие результаты с phash. Точность хороша для перемасштабированных изображений. Это не хорошо для (перцептуально) измененных изображений (обрезанных, повернутых, зеркальных и т. Д.). Чтобы справиться с скоростью хеширования, мы должны использовать кэш/базу данных для хранения хэшей для стога сена.
Очень приятно, что при создании вашей хэш-базы данных (которая для меня составляет около 1000 изображений в секунду) поиск может быть очень и очень быстрым, особенно если вы можете хранить всю хэш-базу данных в Память. Это довольно практично, так как хэш составляет всего 8 байт.
Например, если у вас 1 миллион изображений, для этого потребуется массив из 1 миллиона 64-битных хеш-значений (8 МБ). На некоторых процессорах это вписывается в кеш L2/L3! В практическом использовании я видел сравнение Corei7 с более чем 1 Giga-hamm/sec, это всего лишь вопрос пропускной способности памяти CPU. База данных с 1 миллиардом изображений практична на 64-битном процессоре (требуется 8 ГБ оперативной памяти), и поиск не будет превышать 1 секунду!
Для измененных/обрезанных изображений казалось бы, что преобразование-инвариантная функция/детектор ключевых точек, такой как SIFT, - это путь. SIFT будет создавать хорошие ключевые точки, которые будут определять обрезку/поворот/зеркало и т. Д. Однако сравнение дескрипторов очень медленное по сравнению с расстоянием от помех, используемым phash. Это основное ограничение. Есть много сравнений, поскольку существует максимальный дескриптор IxJxK, который сравнивается с поиском одного изображения (I = число изображений сена, J = целевые ключевые точки на изображение сена, K = целевые ключевые точки на изображение иглы).
Чтобы обойти проблему скорости, я попытался использовать фаш вокруг каждой найденной ключевой точки, используя размер/радиус функции, чтобы определить суб-прямоугольник. Уловка для этого хорошо работает, заключается в том, чтобы вырастить/сжать радиус, чтобы создать разные субрекционные уровни (на изображении иглы). Как правило, первый уровень (немасштабированный) будет соответствовать, хотя часто это занимает еще несколько.Я не уверен на 100%, почему это работает, но я могу себе представить, что он позволяет слишком малым функциям для работы фашизма (размер фейш-шкал до 32x32).
Другая проблема заключается в том, что SIFT не будет оптимально распределять ключевые точки. Если есть часть изображения с большим количеством краев, то ключевые точки будут группироваться там, и вы не получите ни одного в другой области. Я использую GridAdaptedFeatureDetector в OpenCV для улучшения распространения. Не уверен, какой размер сетки лучше, я использую небольшую сетку (1x3 или 3x1 в зависимости от ориентации изображения).
Возможно, вы захотите масштабировать все изображения скелета (и иглы) до меньшего размера до обнаружения функции (я использую 210 пикселей по максимальному размеру). Это уменьшит шум изображения (всегда проблема для алгоритмов компьютерного зрения), а также сфокусирует детектор на более заметных функциях.
Для изображений людей вы можете попробовать распознать лицо и использовать его для определения размера изображения для масштабирования и размера сетки (например, наибольшая грань масштабируется до 100 пикселей). Детектор функций учитывает несколько уровней шкалы (используя пирамиды), но есть ограничение на количество уровней, которые он будет использовать (это, конечно, настраивается).
Ключевой детектор, вероятно, работает лучше всего, когда он возвращает меньше, чем количество функций, которые вы хотели. Например, если вы попросите 400 и получите 300 обратно, это хорошо. Если вы получаете 400 обратно каждый раз, возможно, некоторые хорошие функции должны быть опущены.
Игла может иметь меньше ключевых точек, чем изображения сена и все еще получать хорошие результаты. Добавление большего не обязательно приведет к огромным выигрышам, например, с J = 400 и K = 40 мой коэффициент попадания составляет около 92%. При J = 400 и K = 400 скорость атаки достигает 96%.
Мы можем использовать экстремальную скорость функции помех для решения масштабирования, вращения, зеркалирования и т. Д. Можно использовать многопроходную технику. На каждой итерации преобразуйте суб-прямоугольники, повторно-хэш и снова запустите функцию поиска.
Возможно, потребуется некоторое обновление с учетом достижений в «Глубоком обучении» – jldupont