Распознавание объектов на изображениях

Наши Скрибы собирают много фото и видео в дополнение к векторным данным, которые они собирают через Fulcrum app.

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

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

После того, как я решил использовать нейронную сеть, мне нужно было решить, как я хочу проводить обнаружение. Существуют различные способы использования нейронной сети для обнаружения объектов на изображении, и у каждого из них есть свои плюсы и минусы. В итоге я выбрал метод обнаружения под названием You Only Look Once (YOLO). Этот метод является быстрым и использует единую нейронную сеть для всего изображения, разделяя его на области, а затем предсказывает ограничивающие рамки и вероятности для каждой из областей. Поскольку YOLO просматривает изображение целиком, прогнозы имеют глобальный контекст по сравнению с другими прогнозами, которые работают изолированно на различных частях изображения.

Выбрав метод, я обратил внимание на поиск предварительно обученной сети для использования с OpenCV. К счастью, на отличном сайте Даркнет есть несколько предварительно обученных нейронных сетей, которые находятся в свободном доступе. Первая сеть, которую я использовал, была обучена на наборе данных Common Objects in Context (COCO) из Корнельского университета. Сеть даркнета предварительно обучена обнаруживать 80 различных классов объектов.

Сначала я написал доказательство концепции на Python для проверки наших фотографий. Он подключался к нашей внутренней базе данных, чтобы получить путь к файлу, загружал файл, запускал сеть с изображением, а затем сохранял результаты в нашей внутренней базе данных. Чтобы помочь нашим аналитикам получить опыт работы с распознаванием объектов и уровнями достоверности, я провел серию прогонов с шагом 10 от минимальной достоверности 40 % до 90 %.

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

Прежде чем мы развернули ее для более широкого внутреннего тестирования, я переписал программу на C++ и использовал настраиваемое количество потоков операционной системы, чтобы попытаться ускорить ее. Программе Python потребовалось около шести дней, чтобы запустить модель COCO для всех 500 000+ изображений. После некоторых оптимизаций версия C++ могла выполнить полный запуск COCO примерно за 24 часа.

После внутреннего тестирования мы поняли, что нам нужно более 80 классов объектов, которые предоставляет COCO. К счастью, на сайте Darknet также есть предварительно обученная модель, основанная на наборе данных Open Images (OI) от Google. Сеть OI обучена распознавать 601 класс объектов, некоторые из которых перекрываются с моделью COCO. Всего это дало нам 607 различных классов объектов, которые мы могли обнаружить. Тестирование показало, что COCO работает намного лучше, чем OI, для классов, которые они разделяют. Затем я модифицировал код, чтобы пропускать каждое изображение через обе нейронные сети, игнорируя результаты OI-модели, которые также были в COCO.

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

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

Оглядываясь назад, можно извлечь несколько уроков из этого. Первый я уже реализовал, сохранив каждое обнаружение с достоверностью не менее 10%. Первоначально мы сохраняли результаты только в том случае, если они имели как минимум 75% достоверности. Однако тестирование показало нам, что во многих случаях COCO был особенно точен, даже когда он сообщал о достоверности только некоторых обнаружений в диапазоне 50%. Я решил сохранить все, что соответствует как минимум 10%, так как это позволит нам настроить наши результаты. Если бы мы хотели получить больше результатов с повышенной вероятностью ложных срабатываний, мы могли бы снизить пороговое значение при запросе к базе данных.

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

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

Часть 1 можно прочитать здесь