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

Мы недавно прошли через этот процесс и решили, что я поделюсь своими выводами здесь. Присутствующий код написан на Python, но используемые методы и модули должны быть доступны на большинстве языков.

Задний план

Может быть несколько причин для желания иметь возможность вычислять сходство изображений, наша была следующей:

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

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

Основная концепция подобия изображений

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

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

Что такое вектор изображения? Ну в основном это:

[0.012, 0.982, 0.673, 0.004, 0.455, 0.231]

Комбинация чисел, обычно от 0 до 1 или от -1 до 1, организованная в виде списка, массива или тензора, в зависимости от используемой библиотеки. Этот конкретный вектор имеет длину всего 6 индексов, но нет ничего необычного в том, чтобы увидеть векторы из 4096 значений.

Учитывая, что вы преобразовали два изображения в векторы, вы можете использовать следующий код для вычисления расстояния между ними (очевидно, что vector3 намного ближе к vector1, чем vector2):

Два важных замечания, прежде чем мы продолжим:

  • Существует множество различных метрик расстояния, каждая из которых имеет свои (отрицательные) преимущества, но в этом примере я использую евклидово расстояние. Если вы хотите узнать больше о различиях, вот интересный пост для чтения:
    http://dataaspirant.com/2015/04/11/five-most-popular-similarity-measures-implementation-in -python /
  • Если вам нужно вычислить расстояния между тысячами векторов изображений, вычисление расстояния между изображениями может оказаться долгим процессом. Использование Annoy вместо этого может сэкономить много времени (включая выполнение этих вычислений в режиме реального времени внутри конечной точки API). Проект можно найти здесь: https://github.com/spotify/annoy

Векторные методы изображения

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

Значения пикселей

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

Цветовая гистограмма

Несколько более сложный способ создания векторного представления изображения - это использование цветовой гистограммы. Это можно описать как представление распределения цветов в изображении. Цветовая гистограмма использует каналы RedGreenBlue (RGB) или HueSaturationValue (HSV) отдельно, в зависимости от того, как считывается изображение.

Цветовые гистограммы особенно полезны, если вы фокусируетесь на сходстве изображений, но менее актуальны в случаях, когда важны узоры. Код может быть довольно легко сгенерирован с помощью модуля Python opencv (в коде под названием cv2).

Конкретный недостаток, который может возникнуть с цветовой гистограммой, заключается в том, что объект находится, например, на белом фоне. если объекты имеют разную форму, это означает, что распределение белого фона в изображении различается в зависимости от формы, что может привести к странным результатам при расчетах сходства. К счастью, есть возможность добавить опцию «маска» к функции цветовой гистограммы opencv, где вы в основном описываете пиксель на пиксель, какую область нужно игнорировать, а какую нужно использовать на фотографии.

Вы можете создать эту маску вручную, но вы также можете сделать это автоматически (с определенной частотой ошибок) с помощью opencv с помощью функции: `grabCut`! Единственное, что вам нужно сделать, это дать расплывчатое описание того, где обычно должен находиться объект (это можно сделать на основе процентов изображения).

недостатки:

  • Хотя это хорошо решает проблему, алгоритм grabCut не является быстрой функцией, что может вызвать проблемы в службе, которая должна выполнять быстрые (почти в реальном времени) вычисления.
  • Цветовая гистограмма очень мало описывает формы и абсолютно не дает представления о узорах внутри цветов. Поскольку синюю рубашку в полоску нельзя сочетать с простой синей рубашкой, это также не было подходящим вариантом для нас.

Алгоритмы обнаружения OpenCV

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

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

Вот лишь несколько примеров этих алгоритмов: SIFT, SURF, BRIEF и KAZE, у каждого из которых уже есть свои плюсы и минусы. В приведенном ниже коде я использую пример с SIFT, но для всех этих алгоритмов вы можете в основном использовать один и тот же код и переключать имена.

Обратите внимание, что для использования sift вам потребуется установить другую версию opencv:

pip install opencv-contrib-python

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

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

Сверточные нейронные сети

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

И что еще лучше, многие исследователи уже создают всевозможные предварительно обученные модели, которые вам даже не нужно создавать самостоятельно!

На https://keras.io/applications/ вы уже можете найти множество предварительно обученных моделей классификации, которые уже основаны на тысячах классов. Один из них мы будем использовать для примера кода.

Но подождите, классификация? Разве нам не следует создавать векторные изображения?

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



Здесь я просто перейду к той части, которая интересна для получения векторных представлений.

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

[0.96728301, 0.85966611, 0.03054662, 0.52898392, 0.64065855,
0.31420002, 0.37003331, 0.37319377, 0.89147464, 0.03048572,
0.71571433, 0.34301471, 0.44178935, 0.85526603, 0.82869657,
0.72308823, 0.74962207, 0.75073109, 0.86568716, 0.75487048,
0.94466039, 0.48530138, 0.48537673, 0.37207373, 0.43916694,
0.63603849, 0.13870812, 0.74275987, 0.50442685, 0.82969852

……
0.86371747, 0.55040323, 0.28048927, 0.77291785, 0.76442145,
0.54567903, 0.00839382, 0.88606217, 0.11655837, 0.71924104,
]

Вектор чисел с плавающей запятой от 0 до 1 или от -1 до 1! Более того, эти векторы слоев - не просто случайные числа. Поскольку сеть обучена предсказывать определенные метки, а веса в слоях меняются во время обучения, чтобы помочь направить классификацию к правильной метке, неудивительно, что большинство этих чисел с плавающей запятой (под поверхностью) имеют определенное значение.

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

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

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

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

Создайте свою собственную сверточную нейронную сеть

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

  • Мужская или женская одежда
  • Обувь vs не обувь
  • Какая именно одежда (брюки / рубашки / юбки / ботинки / кроссовки и т. Д.)
  • Основной цвет (красный / синий / желтый и т. Д.)
  • Специфический цвет (светло-голубой, бордовый, лососевый и др.)
  • Узор (полосатый, клетчатый, без узора и т. Д.)

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



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

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

В заключении

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