Пару месяцев назад Google анонсировал пятый выпуск Open Images Dataset (OID) вместе с некоторыми предварительно обученными моделями для задачи обнаружения объектов. Давайте поиграем с одной из этих моделей и посмотрим, как она выглядит.

Вступление

Грубо говоря, последняя версия OID состоит из 15 миллионов аннотированных ограничивающих рамок в 601 категории, 2,5 миллиона сегментов экземпляров в 350 категориях, 36 миллионов меток уровня изображения в 20 тысячах категорий и 391 тысячи аннотаций отношений для 329 отношений. Это довольно большой объем данных, который, безусловно, открывает множество возможностей для исследований компьютерного зрения.

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

Как уже упоминалось, были выпущены некоторые модели, предварительно обученные на OID. Последние были обучены на версии 4 набора данных, и я буду играть с лучшей (с точки зрения mAP) - и более медленной (с точки зрения скорости) - в этом посте. . Эти и многие другие модели можно найти в репозитории моделей обнаружения Tensorflow.

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

Код

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

Все упомянутые в этом посте файлы доступны на моем GitHub. Посмотрите это репо!

Настройка среды

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

name: object-detection-oidv4
channels:
  - conda-forge
  - anaconda
dependencies:
  - python=3.6.9
  - numpy=1.16.5
  - tensorflow=1.13.1
  - matplotlib=3.1.1
  - pillow=6.1.0
  - pandas=0.25.1
  - jupyter=1.0.0
  - ipython=7.8.0

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

$ conda env create -f environment.yml

После завершения установки активируйте среду.

$ conda activate object-detection-oidv4

Все готово! Давайте погрузимся в код Python.

Проверка версии TensorFlow

В связи с недавним выпуском Tensorflow 2.0, давайте убедимся, что вы используете ту же версию, на которой был построен этот код - все в порядке, если не возникает ImportError. Не беспокойтесь об этом, если вы создали среду с помощью моего файла.

Настройка черчения

Настройте matplotlib для отображения изображений в строке, если вы используете блокнот jupyter. В противном случае просто выполните импорт.

Импорт некоторых распространенных библиотек

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

Получение файла модели

В этом посте я буду использовать модель с интересным названием:

faster_rcnn_inception_resnet_v2_atrous_oidv4

Если вы хотите проверить конфигурацию модели, вот файл.

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

Получение файла описания коробки

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

Если вас интересует 601 класс, доступный в OID для обнаружения объектов, посмотрите эту красивую дендрограмму.

Получение тестовых изображений

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

Извлечение файлов модели

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

Загрузка описаний ящиков в словарь

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

Проверка некоторых этикеток

Так отображаются классы, однако мы не будем использовать id. Вместо этого мы будем использовать индекс, чтобы упростить задачу. Чтобы проиллюстрировать, если мы получаем класс № 100, то он соответствует Cheese.

Загрузка замороженной модели из файла

Теперь нам нужно создать наш график из файла замороженной модели.

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

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

Хотите узнать, какие изображения я выбрал? Они здесь:

Собаки и кошки. Я бы сказал классический.

Определение некоторого вспомогательного кода

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

Выполнение вывода

Все готово! Давайте выполним вывод для всех тестовых изображений.

Отображение результатов

Давайте теперь нарисуем помеченные ограничительные рамки в соответствии с результатами и покажем изображения.

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

Более сложные результаты

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

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

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

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

Загородный дом: обнаружено все, что я ожидал. Можно было бы возразить, что Дверь могла быть обнаружена, но дверь открыта, и мы не можем ее увидеть, как и модель. Очень впечатляюще!

Фрукты: обнаружено все, что я ожидал. Никаких действий с малиной, так как такой класс не поддерживается. Strawberry, с другой стороны, поддерживается, но давайте согласимся, что их позиция не в пользу обнаружения.

Заключительные замечания

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

  1. Если приложение требует обработки в реальном времени, оно слишком медленно запускается на ЦП. Пожалуйста, дайте мне знать о результатах, если вы попробуете его на GPU.
  2. Вы ограничены классами, которые предоставляет модель. Включение нового класса потребует сбора помеченных изображений и переобучения модели. И, друг мой, переобучение этой модели на OID заняло бы огромное количество времени.
  3. Вам нужно будет оценить производительность каждого интересующего объекта, если вы хотите использовать эту модель в своем приложении. Некоторые классы определенно работают лучше, чем другие. Кроме того, порог оценки играет важную роль при принятии решения о том, что обнаружено, а что нет. Наконец, вам также необходимо рассмотреть возможность игнорирования некоторых классов, потому что, вероятно, не все из них будут иметь отношение к вашему приложению.

На сегодня все. Спасибо за прочтение! 🙂