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

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

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

Начните с хороших ингредиентов

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

Однако здесь мы будем более конкретными. В качестве основного примера, который мы покажем вам в этом посте, мы будем работать с набором данных изображений, аннотированных с помощью инструментов геометрической аннотации Zillin, таких как Кисть, Многоугольники или Граничная рамка. Они создают аннотации, наиболее подходящие для преобразования в набор данных COCO Object Detection. Здесь мы немного забегаем вперед, но если вы прочитаете дальше, скоро станет ясно, почему.

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

Когда у вас будет готовый набор данных, экспортируйте его в JSON, и вы будете готовы к работе.

Рецепт Zillin COCO

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

Формат аннотации набора данных COCO определяется как файл JSON, содержащий следующие основные разделы:

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

Раздел «Информация»

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

Естественным местом для поиска такого рода информации в Zillin экспорте являются поля верхнего уровня.

Мы можем использовать временную метку VersionGenerated для заполнения полей year и date_created. Поле Версия можно скопировать как есть. В экспорте Zillin нет описания, но у нас есть ProjectName, который мы можем использовать. Для участника и url нет значимых эквивалентов, но мы можем оставить их пустыми или вставить некоторые заполнители. Все идет нормально.

Когда вы посмотрите на нижнюю часть фрагмента экспорта Zillin, вы увидите одну важную деталь, с которой нам нужно обращаться осторожно. Последнее поле DataSets названо во множественном числе не случайно. Фактически экспорт Zillin может описывать несколько наборов данных. Это отличается от формата COCO, который всегда описывает один набор данных для каждого файла JSON.

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

Раздел «изображения»

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

Что касается Zillin, каждый набор данных будет содержать список под названием Изображения, в котором вы найдете такие записи:

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

Итак, что мы будем использовать? Глядя на сторону COCO, нам сначала нужен id изображения. ImageId можно найти в экспорте Zillin, но, увы, COCO id поддерживает только целые числа, в то время как Zillin ImageId является буквенно-цифровым. Таким образом, нам придется переназначить ImageIds на последовательность чисел. Ничего страшного.

Глядя дальше, у нас есть ширина и высота изображения. Эта информация отсутствует в экспорте Zillin, но мы можем получить ее из самих файлов изображений. Имя каждого файла, который нам понадобится, можно найти в поле ImageName экспорта Zillin, и мы можем передать его напрямую (или с префиксом с информацией о локальном пути) в file_name поле в файле COCO.

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

В формате COCO следует лицензия. Поскольку Zillin в настоящее время не хранит информацию о лицензии на отдельные фотографии, для лицензии мы будем использовать заполнитель.

Далее идут flickr_url и coco_url, относящиеся к первоначально опубликованным наборам данных COCO. Мы пропустим или оставим эти поля пустыми в нашем экспорте, так как у нас нет достоверной информации для них.

Наконец, есть date_captured. Данные для этого поля отсутствуют в Zillin JSON, поэтому мы снова будем использовать файлы изображений. Есть несколько способов получить эту информацию, она может исходить из EXIF, дат создания или изменения файла. Наиболее достоверный источник будет зависеть от источника ваших изображений — мы будем использовать наиболее широко доступную дату последней модификации.

Раздел «Аннотации»

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

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

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

  • Обнаружение объектов и Сегментация материалов, которые используют геометрические аннотации или маски RLE.
  • Паноптическая сегментацияс использованием сопровождающих изображений PNG
  • Обнаружение ключевых точек, использующее точки и ребра
  • DensePose, в котором используются специальные теги и маски RLE.
  • Подпись к изображению, которая обеспечивает только одну подпись для всего изображения.

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

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

Как видите, в Zillin можно создавать аннотации для любого типа набора данных COCO, но в то же время для каждого формата COCO могут иметь смысл только определенные типы аннотаций. Некоторые аннотации, такие как Вопросы и Атрибуты, также предназначены для открытой интерпретации. Таким образом, их сопоставление с аннотациями COCO может меняться от набора данных к набору данных.

Давайте рассмотрим это в контексте конкретного и популярного варианта использования: преобразования набора данных с геометрическими аннотациями в формат COCO Обнаружение объектов. На стороне COCO необходимые аннотации в этом случае будут состоять из двух частей: список записей аннотаций

сопровождается списком используемых категорий в виде:

Тем временем полигональные аннотации в Zillin будут поступать из поля Сегментация, которое вы видели выше, когда мы обсуждали раздел ИЗОБРАЖЕНИЯ. Поле содержит список таких записей:

Сверху вниз аннотация COCO снова начинается с числового идентификатора. Аннотации в Zillin индивидуально не идентифицируются, поэтому мы будем перечислять их при конвертации.

Следующий image_id — это тот же числовой идентификатор, который мы создали в разделе IMAGES. Мы будем обрабатывать аннотации в контексте изображения, чтобы знать его id.

Далее идет category_id, который ссылается на соответствующую запись в categories. Zillin не использует идентификаторы классов, но предоставляет нам поле ClassName. Используя содержимое этого поля, мы можем перечислить классы, сгенерировать category_id и создать список categories для COCO. суперкатегория в этом случае останется неиспользованной, так как у нас нет двухуровневой категоризации, доступной в экспорте Zillin.

Затем у нас есть сегментация, где мы можем предоставить геометрические данные или маску RLE. В экспорте Zillin у нас есть соответствующее поле Selection, содержащее описание геометрии в популярном текстовом формате. Это, естественно, подходит для преобразования в аннотации полигонов COCO, что мы и сделаем.

Здесь нам нужно помнить, что геометрия WKT работает немного иначе, чем полигоны COCO.

  1. Геометрия WKT может включать несколько полигонов, в то время как формат COCO кодирует отдельные полигоны в отдельные аннотации. Таким образом, при необходимости нам придется дезагрегировать геометрию WKT.
  2. Многоугольники WKT могут включать расширенную геометрию, например, многоугольники с отверстиями. Zillin может создавать такие формы аннотаций при использовании инструмента Кисть. С другой стороны, аннотации полигонов COCO можно использовать только для простых полигонов. Мы не будем подробно рассматривать этот случай расширенного перевода, чтобы не перегружать этот пост. Не стесняйтесь обращаться в службу поддержки Zillin, если вам нужна такая конвертация.

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

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

Что нам осталось предоставить для аннотаций COCO, так это area и bbox, которые предназначены для содержания области в пикселях аннотации и ее ограничивающей рамки. Оба они могут быть рассчитаны, поскольку мы переведем многоугольники геометрии Zillin WKT в аннотации COCO. Не беспокойтесь о математике. Библиотеки Python, которые мы будем использовать, поставляются со всеми функциями, необходимыми для вычисления того, что нам нужно.

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

Раздел «лицензии»

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

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

Давайте построим Zillin COCO maker

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

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

Один экспорт Zillin, несколько наборов данных

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

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

Информация о наборе данных

Проходя через разделы COCO, первый — это информация о наборе данных. Мы собираем его следующим образом:

Мы делаем это для каждого отдельного набора данных из экспорта Zillin, но информация, которая входит в год и date_created, а также версия, поступает из Заголовки экспорта Zillin верхнего уровня.

Приведенный выше фрагмент демонстрирует магию работы с JSON в Python. После анализа встроенной библиотекой json мы можем получить доступ к Zillin JSON через встроенные коллекции. Это так же просто и наоборот: мы можем составить COCO JSON как литералы для Python dict и list. В конечном итоге библиотека json позаботится о том, чтобы записать это содержимое в выходные файлы JSON. Мы будем использовать этот способ работы во всем коде.

Картинки

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

По мере продвижения мы также создаем словарь image_ids, который переводит буквенно-цифровые идентификаторы Zillin в целые числа COCO. Мы будем использовать этот словарь позже при обработке аннотаций.

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

Поля COCO, для которых у нас нет достоверной информации, а именно license и coco_url, остаются с допустимыми, но бессмысленными значениями.

Аннотации

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

Мы пропускаем метаданные рабочего процесса аннотации, содержащиеся в экспорте Zillin, прямо к сегментации.

Мы собираем информацию о категориях на основе имен классов, присваиваем идентификаторы аннотациям и обрабатываем геометрию. Все данные аннотаций, которые мы заполняем в полях COCO JSON, поступают из этих задач, за исключением значения iscrowd, которое не используется и остается со значением-заполнителем.

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

Геометрия

Обработка геометрии WKT, созданной Zillin, осуществляется с помощью библиотеки ogr, которая входит в пакет Python GDAL.

Мы обрабатываем геометрию в два этапа.

Один из них — определить полигоны, над которыми мы будем работать, в зависимости от типов геометрии WKT, используемых в аннотации.

Затем мы просматриваем полигоны один за другим, создавая все данные, которые нам понадобятся для аннотации COCO: геометрию сегментации, а также площадь полигона и bounding_box. . Как видно из кода, единственное, что нам нужно сделать вручную, — это перебрать точки и создать списки координат. Сложные геометрические вычисления выполняет ogr.

Категории

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

Каждая из категорий COCO получает числовой идентификатор, который мы присвоили, и имя, полученное непосредственно из Zillin ClassName. Для суперкатегории в данном случае у нас есть только заполнитель, но о наличии этого поля стоит помнить. Вскоре мы покажем вам пример, где это используется более осмысленно.

Собираем все части вместе

Со всеми этими битами полный сценарий преобразования Zillin в COCO выглядит следующим образом:

Как адаптировать

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

Пример взят из набора данных OCR. Набор данных содержал изображения отсканированных документов, на которых каждая буква была снабжена ограничивающей рамкой. Zillin Questions and Attributes использовались для предоставления информации о символах в полях и языке документа. Результирующая аннотация изображения выглядит следующим образом:

Как вы заметили, список Вопросы в разделе Аннотации больше не пуст, а содержит вопрос Язык с соответствующим ответом. Затем раздел Вопросы в разделе Сегментация содержит вопрос Значение символа, и его ответ содержит символ. Геометрия Selection теперь содержит отдельный многоугольник.

В COCO это можно выразить как суперкатегория и категория. Первые могут содержать информацию о языке документа, а вторые — о символах.

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

Один из них — убедиться, что функция COCOAnnotationsFrom(zillin_images_json, image_ids) обращается к вопросам Язык и Значение символа для получения категорий.

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

Геометрия аннотаций уже будет правильно преобразована.

Последние мысли

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

С помощью предоставленного кода теперь вы можете аннотировать изображения в Zillin и сразу же создавать наборы данных COCO Object Detection. Обладая некоторой ловкостью в Python, вы также сможете подойти к любой другой задаче COCO с хорошей отправной точки. Не стесняйтесь адаптировать наш код по своему усмотрению.

Если вы обнаружите, что ломаете голову над задачей преобразования COCO, для которой требуются методы, которые мы не рассмотрели, не стесняйтесь, дайте нам знать по адресу [email protected], и мы будем рады помочь!

Приятного аннотирования!