Сравнение изображений - быстрый алгоритм

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

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

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

Ответ 1

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

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

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

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

Соответствие ключевых точек

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

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


Альтернативное решение: метод гистограммы

Другим менее надежным, но потенциально более быстрым решением является построение гистограмм функций для каждого изображения и выбор изображения с гистограммой, ближайшей к гистограмме входного изображения. Я реализовал это как 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| 

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


Третий выбор - ключевые точки + деревья принятия решений

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

Обновление

Моя ошибка - документ Semantic Texton Forests не относится конкретно к сопоставлению изображений, а скорее к маркировке области. Оригинальная бумага, которая выполняет сопоставление, такова: Распознавание ключевых точек с использованием рандомизированных деревьев. Кроме того, в нижеприведенных документах продолжают развиваться идеи и представлять современное состояние (c. 2010):

Ответ 2

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

http://phash.org/

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

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

Ответ 3

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

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

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

  • файл-хэш (md5, sha1 и т.д.) для точных дубликатов
  • перцептивное хеширование (фаш) для масштабированных изображений
  • функциональный (SIFT) для модифицированных изображений

У меня очень хорошие результаты с phash. Точность хороша для перемасштабированных изображений. Это не хорошо для (перцептуально) измененных изображений (обрезанных, повернутых, зеркальных и т.д.). Чтобы справиться с скоростью хеширования, мы должны использовать кэш/базу данных для хранения хэшей для стога сена.

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

Например, если у вас есть 1 миллион изображений, для этого потребуется массив из 1 миллиона 64-битных хэш-значений (8 МБ). На некоторых процессорах это вписывается в кеш L2/L3! В практическом использовании я видел сравнение Corei7 с более чем 1 Giga-hamm/sec, это всего лишь вопрос пропускной способности памяти CPU. База данных с 1 миллиардом изображений практична для 64-битного процессора (требуется 8 ГБ ОЗУ), и поиск не будет превышать 1 секунду!

Для измененных/обрезанных изображений казалось бы, что преобразование-инвариантный признак функции/ключевого слова, такой как SIFT, - это путь. SIFT будет создавать хорошие ключевые точки, которые будут определять обрезку/поворот/зеркало и т.д. Однако сравнение дескрипторов очень медленное по сравнению с расстоянием от помех, используемым phash. Это основное ограничение. Есть много сравнений, поскольку есть максимальный дескриптор IxJxK, который сравнивается с поиском одного изображения (I = num haystack images, J = целевые ключевые точки на изображение сена, K = целевые ключевые точки на изображение иглы).

Чтобы обойти проблему скорости, я попытался использовать фаш вокруг каждой найденной ключевой точки, используя размер/радиус функции, чтобы определить суб-прямоугольник. Уловка для этого хорошо работает, заключается в том, чтобы вырастить/сжать радиус, чтобы создать разные субрекционные уровни (на изображении иглы). Как правило, первый уровень (немасштабированный) будет соответствовать, хотя часто это занимает еще несколько. Я не уверен на 100%, почему это работает, но я могу себе представить, что он позволяет слишком малым функциям, позволяющим работать в режиме фашизма (размер фейш-шкал уменьшается до 32x32).

Другая проблема заключается в том, что SIFT не будет распределять ключевые точки оптимально. Если есть часть изображения с большим количеством краев, то ключевые точки будут группироваться там, и вы не получите ни одного в другой области. Я использую GridAdaptedFeatureDetector в OpenCV для улучшения распространения. Не уверен, какой размер сетки лучше, я использую небольшую сетку (1x3 или 3x1 в зависимости от ориентации изображения).

Вероятно, вы хотите масштабировать все изображения скелета (и иглы) до меньшего размера до обнаружения функции (я использую 210 пикселей по максимальному размеру). Это уменьшит шум изображения (всегда проблема для алгоритмов компьютерного зрения), также будет фокусировать детектор на более важные функции.

Для изображений людей вы можете попробовать распознать лицо и использовать его для определения размера изображения для масштабирования и размера сетки (например, наибольшая грань масштабируется до 100 пикселей). Детектор функций учитывает множественные уровни шкалы (используя пирамиды), но есть ограничение на количество уровней, которые он будет использовать (это, конечно, настраивается).

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

Изображение иглы может иметь меньше ключевых точек, чем изображения сеновальной раковины, и по-прежнему получать хорошие результаты. Добавление большего не обязательно приведет к огромным выигрышам, например, с J = 400 и K = 40 мой коэффициент попадания составляет около 92%. При J = 400 и K = 400 скорость попадания достигает только 96%.

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

Я хочу сказать, что я искал в интернете повсюду, чтобы попытаться найти идеальное решение. Я даже разработал свой собственный алгоритм обнаружения краев.
Я оценил скорость и точность нескольких моделей. Мои изображения с белым фоном очень хорошо работают с фишингом. Как сказал redcalx, я рекомендую phash или ahash. НЕ НЕ используйте хеширование MD5 или другие криптографические хеши. Если только вам не нужны ТОЧНЫЕ совпадения изображений. Любое изменение размера или манипуляция между изображениями приведет к другому хешу.

Для phash/ahash, проверьте это: imagehash

Я хотел расширить пост * redcalx, опубликовав свой код и мою точность.

Что я делаю:

from PIL import Image
from PIL import ImageFilter
import imagehash

img1=Image.open(r"C:\yourlocation")
img2=Image.open(r"C:\yourlocation")
if img1.width<img2.width:
    img2=img2.resize((img1.width,img1.height))
else:
    img1=img1.resize((img2.width,img2.height))
img1=img1.filter(ImageFilter.BoxBlur(radius=3))
img2=img2.filter(ImageFilter.BoxBlur(radius=3))
phashvalue=imagehash.phash(img1)-imagehash.phash(img2)
ahashvalue=imagehash.average_hash(img1)-imagehash.average_hash(img2)
totalaccuracy=phashvalue+ahashvalue

Вот некоторые из моих результатов:

item1  item2  totalsimilarity
desk1  desk1       3
desk1  phone1     22
chair1 desk1      17
phone1 chair1     34

Надеюсь, это поможет!