2009-05-09 2 views
330

Я ищу, чтобы создать базовую таблицу изображений, а затем сравнить любые новые изображения с этим, чтобы определить, является ли новое изображение точным (или близким) дубликатом базы.Сравнение изображений - быстрый алгоритм

Например: если вы хотите уменьшить время хранения одного и того же изображения 100 раз, вы можете сохранить одну его копию и предоставить ссылки на нее. Когда вводится новое изображение, вы хотите сравнить с существующим изображением, чтобы убедиться, что это не дубликаты ... идеи?

Одна из моих идей заключалась в том, чтобы свести к небольшому миниатюре, а затем случайным образом выбрать 100 пикселей и сравнить их.

+5

Возможно, потребуется некоторое обновление с учетом достижений в «Глубоком обучении» – jldupont

ответ

393

Ниже приведены три подхода к решению этой проблемы (и есть много других).

  • Первый - это стандартный подход в компьютерном зрении, соответствие ключевых точек. Для этого может потребоваться некоторая справочная информация, и она может быть медленной.

  • Второй метод использует только элементарную обработку изображений и потенциально быстрее, чем первый подход, и его просто реализовать. Однако, что он получает в понятности, ему не хватает уверенности - совпадение не выполняется при масштабированных, повернутых или обесцвеченных изображениях.

  • Третий метод является быстрым и надежным, но потенциально может быть сложнее всего реализовать.

Keypoint Matching

лучше, чем выбор случайных точек 100 набирает 100 важные баллов. Некоторые части изображения имеют больше информации, чем другие (особенно на краях и углах), и это те, которые вы хотите использовать для интеллектуального сопоставления изображений. Google «keypoint extraction» и «keypoint matching», и вы найдете немало научных статей по этому вопросу. В эти дни, SIFT keypoints, возможно, самые популярные, так как они могут соответствовать изображениям в разных масштабах, поворотах и ​​освещении. Некоторые реализации SIFT можно найти here.

Одним недостатком для сопоставления ключевых точек является время работы наивной реализации: O (n^2m), где n - количество ключевых точек в каждом изображении, а m - количество изображений в базе данных. Некоторые умные алгоритмы могут найти ближайшее совпадение быстрее, например, квадранты или разбиение двоичных пространств.


Альтернативное решение: Histogram метод

Другой менее надежные, но потенциально быстрым решением является создание полнометражных гистограммы для каждого изображения и выбрать изображение с гистограммой, ближайшей к гистограммы входного изображения. Я реализовал это как undergrad, и мы использовали 3 цветные гистограммы (красный, зеленый и синий) и две гистограммы текстур, направление и масштаб. Я приведу подробности ниже, но я должен отметить, что это только хорошо работало для сопоставления изображений ОЧЕНЬ аналогично изображениям базы данных. Повторно масштабированные, повернутые или обесцвеченные изображения могут потерпеть неудачу с этим методом, но небольшие изменения, такие как обрезка, не нарушат алгоритм

Вычисление цветовых гистограмм простое - просто выберите диапазон для ваших гистограммных ведер, а для каждого диапазон, подсчитайте количество пикселей с цветом в этом диапазоне. Например, рассмотрим «зеленую» гистограмму и предположим, что для нашей гистограммы мы выбираем 4 ведра: 0-63, 64-127, 128-191 и 192-255. Затем для каждого пикселя мы посмотрим на значение зеленого цвета и добавим счет в соответствующее ведро. Когда мы закончили подсчет, мы разделим общее количество каждого ведра на количество пикселей всего изображения, чтобы получить нормализованную гистограмму для зеленого канала.

Для гистограммы направления текстуры мы начали с выполнения обнаружения края на изображении. Каждая точка ребра имеет нормальный вектор, направленный в направлении, перпендикулярном к краю. Мы квантовали угол нормального вектора в один из 6 ведер между 0 и PI (так как ребра имеют симметрию на 180 градусов, мы преобразуем углы между -PI и 0 между 0 и PI). После подсчета количества краевых точек в каждом направлении мы имеем ненормализованную гистограмму, представляющую направление текстуры, которую мы нормализуем, деля каждое ведро на общее количество точек ребра в изображении.

Чтобы вычислить гистограмму масштаба текстуры, для каждой граничной точки мы измерили расстояние до ближайшей ближайшей граничной точки в том же направлении. Например, если краевая точка A имеет направление 45 градусов, алгоритм движется в этом направлении, пока не найдет другую точку ребра с направлением 45 градусов (или в пределах разумного отклонения). После вычисления этого расстояния для каждой граничной точки мы выгружаем эти значения в гистограмму и нормализуем ее путем деления на общее количество точек ребра.

Теперь у вас есть 5 гистограмм для каждого изображения. Чтобы сравнить два изображения, вы принимаете абсолютное значение разницы между каждым ведром гистограммы, а затем суммируете эти значения. Например, для сравнения изображений A и B, мы бы вычислить

|A.green_histogram.bucket_1 - B.green_histogram.bucket_1| 

для каждого сегмента в зеленой гистограмме и повторите для других гистограмм, а затем суммировать все результаты. Чем меньше результат, тем лучше матч. Повторите для всех изображений в базе данных и выиграйте матч с наименьшим результатом. Вероятно, вы захотите иметь порог, над которым алгоритм заключает, что совпадения не найдено.


Третий выбор - ключевые точки + Decision Trees

Третий подход, который, вероятно, гораздо быстрее, чем два других использует semantic texton forests (PDF). Это включает в себя извлечение простых ключевых точек и использование деревьев решений коллекции для классификации изображения.Это быстрее, чем простое сопоставление ключевых слов SIFT, поскольку оно позволяет избежать дорогостоящего процесса сопоставления, а ключевые точки намного проще, чем SIFT, поэтому извлечение ключевых слов происходит намного быстрее. Тем не менее, он сохраняет инвариантность метода SIFT к вращению, масштабированию и освещению, что является важной особенностью, которой не хватало метода гистограммы.

Update:

Моя ошибка - семантический Текстон Леса бумаги не конкретно о согласовании изображения, а маркировка региона. Исходная бумага, которая соответствует совпадению, такова: Keypoint Recognition using Randomized Trees. Кроме того, документы ниже продолжают развивать идеи и представляют собой состояние искусства (с 2010).:

+0

Подход гистограммы, кажется, имеет наибольший смысл. Я предполагаю, что вы можете повернуть изображение, чтобы выполнить это со всех сторон, на случай, если изображение будет сравниваться с тем, что было повернуто (обращение с тем же изображением, что и 4) - спасибо – meade

+3

@meade Это верно. Что-то еще нужно учитывать: в зависимости от вашей проблемы вам может не понадобиться использовать все 5 гистограмм в вашем алгоритме. Отбрасывание гистограммы направления текстуры позволит вам сопоставить вращающиеся версии изображения. Отбрасывание гистограммы масштаба текстуры позволит вам сопоставить повторно масштабированные версии изображения. Вы потеряете способность сравнивать сходство, но это может быть не проблема, в зависимости от вашей ситуации. Кроме того, поскольку вычисление информации текстуры является самой дорогостоящей частью алгоритма, это также сделает ваш алгоритм слишком быстрым. –

+0

@redmoskito: У меня вопрос. Как вы получаете числовое значение гистограммы зеленого, например? Таким образом, вы можете вычесть его с помощью другой гистограммы изображения? Предположим, у нас есть зеленая гистограмма с 3 пикселями, принадлежащими 0-63 ведрам, и 5 пикселов, принадлежащих 64-127. Какая ценность? – dynamic

2

Если у вас есть большое количество изображений, просмотрите Bloom filter, в котором используется несколько хэшей для вероятного, но эффективного результата. Если количество изображений не велико, тогда достаточно криптографического хэша, такого как md5.

+0

Итак, (пытаясь понять фильтр Блума) - означает ли это, что вы выбираете случайные пиксельные точки на базовом изображении, случайно получаете либо красное/зеленое/синее значение пиксель - затем сравнить с новым изображением? а затем использовать уровень вероятности (совпадение 90%), чтобы определить, насколько похожи оба изображения? – meade

+3

Это не проверка сходства, это проверка эквивалентности. Если вам нужна схожесть, хеширование - неправильный подход. Идея Bloom заключается в использовании нескольких алгоритмов хэширования, чтобы повысить вероятность уникальной идентификации. Выбор случайных точек - не лучший подход для алгоритма хеширования, потому что он будет давать разные результаты каждый раз. – jdigital

3

Выбор 100 случайных точек может означать, что похожие (или иногда даже разнородные) изображения будут отмечены как одно и то же, что я предполагаю не то, что вы хотите. Хеши MD5 не будут работать, если изображения имеют разные форматы (png, jpeg и т. Д.), Имеют разные размеры или имеют разные метаданные. Уменьшение всех изображений до меньшего размера - хорошая ставка, поэтому сравнение пикселей по пикселям не должно занять слишком много времени, пока вы используете хорошую библиотеку изображений/быстрый язык, а размер достаточно мал.

Вы можете попробовать сделать их крошечные, а затем, если они такие же выполнить другое сравнение на больший размер - может быть хорошее сочетание скорости и точности ...

5

Как Картман отметил, вы можете использовать любой вид хэш-значения для нахождения точных дубликатов.

Одной отправной точкой для поиска близких изображений может быть here. Это инструмент, используемый компаниями CG, чтобы проверить, не изменили ли обновленные изображения по существу одну и ту же сцену.

6

У меня есть идея, которая может работать, и это, скорее всего, очень быстро. Вы можете подпрограммировать изображение, чтобы сказать разрешение 80x60 или сопоставимое, и преобразовать его в шкалу серого (после подвыборки он будет быстрее). Обработать оба изображения, которые вы хотите сравнить. Затем выполните нормализованную сумму квадратов различий между двумя изображениями (изображение запроса и каждый из db), или даже лучше нормализованное кросс-корреляцию, которое дает ответ ближе к 1, если оба изображения схожи. Затем, если изображения похожи, вы можете перейти к более сложным методам , чтобы убедиться, что это те же изображения. Очевидно, что этот алгоритм является линейным с точки зрения количества изображений в вашей базе данных , так что он будет очень быстро до 10000 изображений в секунду на современном оборудовании. Если вам нужна инвариантность к вращению, тогда для этого маленького изображения можно вычислить доминирующий градиент , а затем всю систему координат можно повернуть до канонической ориентации , однако это будет медленнее. И нет, здесь нет никакой инвариантности.

Если вы хотите что-то более общее или используя большие базы данных (миллион изображений), то вам нужно изучить теорию извлечения изображений (загружено много статей за последние 5 лет). В других ответах есть несколько указателей. Но это может быть излишним, и предлагаемый подход к гистограмме будет выполнять эту работу. Хотя я бы подумал, что сочетание многих разных подходов будет еще лучше.

4

Я считаю, что уменьшение размера изображения до почти размера значка, скажем, 48x48, затем преобразование в оттенки серого, а затем изменение разницы между пикселями или Delta должно работать хорошо. Поскольку мы сравниваем изменение цвета пикселей, а не фактический цвет пикселя, не имеет значения, немного ли изображение или изображение более светлое. Большие изменения будут иметь значение, поскольку пиксели, слишком светлые/темные, будут потеряны. Вы можете применить это в одной строке или столько, сколько хотите увеличить точность. В лучшем случае у вас будет 47x47 = 2,209 вычитаний, чтобы сформировать сопоставимый ключ.

63

Лучший способ, которым я знаю, - использовать Perceptual Hash.Там, кажется, хорошая открытая реализация такой хэш доступен по адресу:

http://phash.org/

Основная идея заключается в том, что каждое изображение будет уменьшено до небольшой хэш-код или «отпечатки пальцев», выявляя характерные черты в оригинальный файл изображения и хэширование компактного представления этих функций (а не хэширование данных изображения напрямую). Это означает, что скорость ложных срабатываний значительно снижается благодаря упрощенному подходу, например, уменьшению изображений до небольшого размера отпечатка пальца и сравнению отпечатков пальцев.

phash предлагает несколько типов хешей и может использоваться для изображений, аудио или видео.

+0

Кто интересен в этом методе, может найти Objective-C Perceptual Реализация хэша по ссылке https://github.com/ameingast/cocoaimagehashing –

21

Это сообщение было отправной точкой для моего решения, здесь было много хороших идей, поэтому я бы поделился своими результатами. Основное понимание заключается в том, что я нашел способ обойти медленность сопоставления изображений на основе ключевых слов, используя скорость фашизма.

Для общего решения лучше всего использовать несколько стратегий. Каждый алгоритм лучше всего подходит для определенных типов преобразований изображений, и вы можете воспользоваться этим.

Вверху, самые быстрые алгоритмы; внизу - самый медленный (хотя и более точный). Вы можете пропустить медленные, если хорошее совпадение будет найдено на более высоком уровне.

  • на основе файла-хэш (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%.

Мы можем использовать экстремальную скорость функции помех для решения масштабирования, вращения, зеркалирования и т. Д. Можно использовать многопроходную технику. На каждой итерации преобразуйте суб-прямоугольники, повторно-хэш и снова запустите функцию поиска.

+3

Является ли ваше окончательное решение проприетарным? Можете ли вы поделиться исходным кодом? Я хотел бы видеть ваш конечный продукт. –

+1

Мне нравится, как некоторые люди приходят на stackoverflow, собирают ценную информацию и не делятся своими конечными результатами, Браво! – mahieddine

+0

@mahieddine: Кажется, решение было использовать phash - поэтому код доступен там. – mplungjan