Skip to content

Delviet/Kruzhok_trial

Repository files navigation

Руководство по использованию

pip install -r requirements.txt
python main.py <img-path>

Постановка тестовой задачи

Необходимо создать python-скрипт, принимающий в виде аргумента путь к jpg изображению, на котором требуется обнаружить целый "кружок" из логотипа кружкового движения НТИ. В случае обнаружения, необходимо вывести в стандартный вывод слово "kruzhok", иначе не вывести ничего.

Решение

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

Алгоритмический подход

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

Данный подход показался нам стоящим, поскольку он позволяет сопоставить изображения даже при изменении афинными преобразованиями + не учитывает цвета. Тем не менее, на данный момент у нас отсутствует ясное понимание алгоритмов поиска опорных точек, из-за чего мы не можем ручаться за корректность работы данного алгоритма при малом изменении изображения.

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

В какой-то момент, нам пришло в голову попробовать избавиться от цветов в изображении путём изменения домена изображений: перевести изображения из RGB в одноканальное бинарное изображение, на котором будут видны углы - теоретически, углы логотипа должны быть видны на любом изображении, потому можно было бы использовать некую pattern-matching технику для поиска изображений. Проблема в том, что оператор Кэнни многоступенчат, и имеет внутри себя два "порога", позволяющих контролировать количество найденных углов. Проблема заключается в том, что на некоторых изображениях различие логотипа и контекста может оказаться ниже порога, что сломает pattern-matching и приведёт к появлению False Negative.

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

Deep Learning подход

Поскольку наши попытки найти подходящие алгоритмы потерпели крах, мы были вынуждены прибегнуть к использованию DL. Изначально планировалось насинтезировать данных, обучить на них SEPC и затем дообучить на реальных изображениях, но затем мы наткнулись на данную статью, где авторы предлагают свой рабочий пайплайн с полу-автоматическим обучением детектора логотипов. Помимо этого, мы узнали что модель должна быть почти real-time на CPU, а потому двухэтапный SEPC нам не подходил и было необходимо найти другую архитектуру. Но обо всём по порядку.

Аугментация/синтез данных

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

Парс исходных изображений

Нам показалось наиболее разумным спарсить случайные изображения с фото-стока. Многие сайты подобного рода хорошо защищены, т.к. не в интересах админов, чтобы можно было скопировать их базу за считанные минуты, однако мы смогли найти незащищённый сайт. По каждой из представленных категорий мы выкачали ~40 фото и удалили дубликаты. Вышло примерно 3,5 тысячи изображений.

Аугментация логотипа

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

Парс сторонних логотипов

Поскольку нам стоило избавиться от ложных срабатываний на иных логотипах, мы решили добавить в обучающую выборку синтезированных данных сторонние логотипы. Для этого мы спарсили логотипы с этого сайта. Затем, чтобы в процессе аугментации добавлялись лишь самые "сложные" для отличия от лого "КД" логотипы, мы использовали метрику Intersection over Union, чтобы найти несколько наиболее похожих логотипов. Чтобы избежать использования одних и тех же логотипов в разных цветовых варициях/слишком похожие друг на друга логотипы X и Y, мы рассчитывали IoU(X, Y) и если значение было > 0.9, мы оставляли X при условии IoU(X, I) > IoU(Y, I), где I - исходный логотип.

Аугментация сторонних логотипов

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

Синтез данных

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

Выбор нейросети

Сразу после обращения к методам глубокого обучения, нам стало очевидно, что оптимальным решением является тренировка модели для обнаружения объектов. В случае, если она находит объект, крайне напоминающий ей "кружок", мы сообщаем, что на изображении присутствует кружок.
Изначально мы планировали использовать предложенный на CVPR2020 SEPC, однако необходимость запускать модель на CPU вывела нас на размышления о различных one-stage детекторах. Конечно, в первую очередь мы подумали про YOLO - на ней и решили остановиться. Взяли YOLOv5 в связи с довольно приятным для данной задачи соотношением точности и скорости работы.

Обучение нейросети

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

Распределение нагрузки

В команде состоят два участника - Арапов Даниил и Батыргариев Александр. Даниил имеет немалый опыт в анализе данных и работе с текстами (как чтение и анализ, так и написание), Александр же имеет неплохие навыки в full-stack разработке.
Совместно было сделано:

  • поиск канидатов для алгоритмических решений
  • продумывание приложения
    Даниил:
  • анализ кандидатов для алгоритмических решений
  • парс исходных изображений
  • аугментация и синтез данных
  • написание README
    Александр:
  • парс сторонних логотипов
  • выбор архитектуры нейросети
  • обучение нейросети
  • объединение кода команды в работающий механизм

About

Solution of a trial task from NTI.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published