Добро пожаловать в наш еженедельный блог с советами и рекомендациями FiftyOne, где мы резюмируем интересные вопросы и ответы, недавно появившиеся на Slack, GitHub, Stack Overflow и Reddit.
Подожди, а что такое FiftyOne?
FiftyOne — это набор инструментов машинного обучения с открытым исходным кодом, который позволяет группам специалистов по обработке и анализу данных повышать производительность своих моделей компьютерного зрения, помогая им выбирать высококачественные наборы данных, оценивать модели, находить ошибки, визуализировать встраивания и быстрее приступать к работе.
- Если вам нравится то, что вы видите на GitHub, поставьте звезду проекту.
- "Начать!" Мы упростили запуск и запуск за несколько минут.
- Присоединяйтесь к сообществу Slack FiftyOne, мы всегда рады помочь.
Хорошо, давайте погрузимся в советы и рекомендации этой недели!
Добавление метаданных в набор данных FiftyOne
Член сообщества Slack Иммануэль Вебер спросил:
«Всем привет! Прежде всего позвольте мне сказать, что я действительно люблю FiftyOne! Я хочу добавить метаданные в свои образцы, и с помощью set_values()
я смог добавить метаданные, но при таком подходе поля не отображаются в приложении FiftyOne. Является ли мой подход допустимым способом добавления новых метаданных? Есть ли способ заставить приложение FiftyOne отображать эти новые поля? Спасибо!"
Отличный вопрос, Иммануил. В FiftyOne поля, видимые в приложении FiftyOne, определяются вашим набором данных. В приложении отображаются только те поля, которые являются частью схемы. Вы можете распечатать dataset.get_field_schema()
, чтобы увидеть схему вашего поля.
Начиная с FiftyOne 0.19.0, когда вы используете set_values()
для добавления поля к образцам в вашем наборе данных, у него есть аргумент dynamic
, который вы можете использовать для управления добавлением поля в вашу схему. По умолчанию dynamic=False
, поэтому поле недобавляется. Если вы передадите dynamic=True
, то он будет добавлен в схему и появится в приложении FiftyOne.
Кроме того, несмотря на возможность добавления в поле metadata
, мы настоятельно рекомендуем создать отдельное поле в ваших образцах для любого атрибута, который вы хотите сохранить. Это связано с тем, что метод compute_metadata()
, который вычисляет высоту и ширину для каждого изображения в наборе данных, не будет работать должным образом, если метаданные не пусты, что может привести к проблемам в дальнейшем.
Вы по-прежнему можете создавать более сложные вложенные объекты в новых EmbeddedDocumentField
полях и отображать их в приложении FiftyOne. Например, если вы хотите создать новое поле custom_metadata
со встроенным полем, которое хранит уникальность образца, вы можете сделать это следующим образом:
import fiftyone as fo import fiftyone.brain as fob import fiftyone.zoo as foz import fiftyone.core.odm as foo # load dataset dataset = foz.load_zoo_dataset("quickstart") # compute uniqueness fob.compute_uniqueness(dataset) # Add a generic embedded document field to which you can add any fields you want dataset.add_sample_field( "custom_metadata", fo.EmbeddedDocumentField, embedded_doc_type=foo.DynamicEmbeddedDocument, ) # set values and add to schema dataset.set_values( "custom_metadata.uniqueness", dataset.values("uniqueness"), dynamic=True, ) # visualize session = fo.launch_app(dataset)
Узнайте больше о встроенных документах и динамических атрибутах в FiftyOne Docs.
Изменение тегов при загрузке аннотаций CVAT в FiftyOne
Даниэль Фортунато, член сообщества Slack, спросил:
«Привет всем! Я хочу загрузить образцы из прогона аннотации CVAT с тегом «to_annotate», а затем изменить их на «being_annotated» в FiftyOne, чтобы я мог отслеживать, какие образцы еще нужно загрузить. Я попытался использовать load_annotation_view()
для загрузки представления из определенного прогона аннотаций, но, похоже, это не работает с изменением тегов. Как бы вы порекомендовали мне это сделать?'
Эй, Даниэль! Когда вы меняете теги, причина, по которой load_annotation_view()
больше не работает, заключается в том, что внутри метод использует этап просмотра MatchTags, который определяется путем поиска всех образцов, имеющих определенные теги. Если вы создадите представление, передав ' to_annotate', а затем измените теги своих образцов на 'being_annotated', эти образцы больше не будут соответствовать условию.
Альтернативный подход, позволяющий обойти эту проблему, состоит в том, чтобы переопределить DatasetView
с помощью операции select()
после match_tags()
и перед изменением тегов. Этап просмотра Выбрать определяется набором идентификаторов образцов, поэтому на него не повлияют изменения в тегах.
import fiftyone as fo import fiftyone.zoo as foz # load dataset dataset = foz.load_zoo_dataset("quickstart") # match tags view = dataset.match_tags("to_annotate") # redefine the view by sample ID view = dataset.select(view) # change tags view.untag_samples("to_annotate") view.tag_samples("being_annotated")
Узнайте больше об стадиях просмотра, FiftyOne Annotation API и нашей интеграции CVAT в FiftyOne Docs.
Предварительный просмотр видеокадров в FiftyOne
Член сообщества Slack Триша Рамкумар спросила:
"У меня есть набор видеоданных с тысячей кадров. Как сэмплировать изображения через равные промежутки времени и предварительно просматривать их в приложении FiftyOne?»
Привет, Триша! В зависимости от продолжительности ваших видеороликов вы можете иметь возможность предварительно просмотреть их в приложении FiftyOne с помощью встроенного визуализатора видео. С помощью видеовизуализатора вы можете воспроизвести видео, наведя указатель мыши на миниатюру образца, а также просмотреть кадр за кадром или перейти к определенным временным меткам.
Однако, если вы работаете с очень большими видео, может случиться так, что вы захотите просмотреть только один из каждых 100 или 1000 кадров. Один из способов просмотреть видеокадры в приложении FiftyOne — преобразовать набор видеоданных в набор данных изображений, рассматривая каждый кадр как новый образец. Затем вы можете использовать ViewField FiftyOne и метод match()
для фильтрации по номеру кадра в поле frame_number
образцов кадров, превращенных в изображения.
Например, если вы работали с Quickstart Video Dataset и хотели сэмплировать кадры со скоростью одно изображение на каждые десять кадров исходного видео, вы могли бы запустить следующее:
import fiftyone as fo import fiftyone.zoo as foz from fiftyone import ViewField as F # load dataset dataset = foz.load_zoo_dataset("quickstart-video") # convert from videos to frames frames = dataset.to_frames(sample_frames=True) # sample every tenth frame view = frames.match(F("frame_number") % 10 == 0) # display, or "preview" the results session = fo.launch_app(view)
Узнайте больше о работе с видео, просмотрах видео и фреймах в FiftyOne Docs.
Агрегации на уровне кадра
Член сообщества Slack Джой Тиммерманс спросила:
"Как мне рассчитать распределение высоты ограничивающих рамок в моем наборе видеоданных, не зацикливаясь на каждом обнаружении?"
Отличный вопрос, Джой! В зависимости от того, какую статистику или информацию о распределении вы хотите извлечь из набора данных, в FiftyOne доступны различные методы агрегирования. Эти методы позволяют извлекать значения, отдельные значения, средние значения или верхние и нижние границы. В вашем случае может быть особенно полезен метод histogram_values()
, который позволяет вычислять гистограмму по значениям поля. Вы даже можете установить количество бинов и диапазон для гистограммы!
В FiftyOne агрегирование и многие другие операции изначально работают с кадрами видео с помощью синтаксиса "."
для доступа к атрибутам уровня кадра. Например, следующее генерирует гистограмму значений высоты кадра для всех кадров и выборок в Quickstart Video Dataset.
import fiftyone as fo import fiftyone.zoo as foz from fiftyone import ViewField as F # load dataset dataset = foz.load_zoo_dataset("quickstart-video") # compute frame width and height dataset.compute_metadata() # compute histogram counts and bin edges # height is last element of bounding box count, edges, _ = dataset.histogram_values( F('frames.detections.detections.bounding_box')[3] )
Узнайте больше о histogram_values() и Выражениях в FiftyOne Docs.
Удаление повторяющихся образцов
Участник сообщества Slack Дэн Эрез спросил:
«В моем наборе данных случайно оказалось несколько повторяющихся образцов. Есть ли быстрый способ удалить дубликаты и оставить только по одному?"
Эй, Дэн! Случайное дублирование — распространенная проблема при работе с данными компьютерного зрения. В FiftyOne, например, если вы попытаетесь добавить образец, который уже существует в вашем наборе данных, вместо того, чтобы ничего не делать или перезаписать исходный образец, набор данных создаст новую копию образца и добавит это к набору данных. Например, следующий код добавляет в Quickstart Dataset пятьдесят дубликатов образцов:
import fiftyone as fo import fiftyone.zoo as foz # load dataset dataset = foz.load_zoo_dataset("quickstart") print(dataset.count()) # 200 # randomly select 50 samples samples_to_duplicate = dataset.take(50) # add these as duplicates dataset.add_samples(samples_to_duplicate) print(dataset.count()) # 250
Во многих случаях возможность иметь несколько образцов с одним и тем же путем к файлу может быть полезной, но в некоторых случаях такое поведение может иметь непредвиденные последствия.
Предполагая, что каждая выборка в исходном наборе данных имеет уникальный путь к файлу, можно легко «отменить» это дублирование и вернуться к исходному набору данных. Ключом к выявлению дубликатов является определение того, какие пути к файлам встречаются в наборе данных более одного раза, а затем удаление всех образцов, кроме одного, для каждого.
Чтобы найти многократно встречающиеся пути к файлам, вы можете использовать агрегацию FiftyOne count_values()
:
fp_counts = dataset.count_values("filepath") dup_fps = [key for key in list(fp_counts.keys()) if fp_counts[key] > 1]
В приведенном выше примере, где образцы дублировались не более одного раза, мы можем дедуплицировать наш набор данных, получив идентификаторы образцов всех повторяющихся путей к файлам и передав их в delete_samples()
:
## IDs of first sample in dataset for each fp sids = [dataset[dup_fp].id for dup_fp in dup_fps] dataset.delete_samples(sids)
Если у вас более одного дубликата на путь к файлу, ознакомьтесь с нашим рецептом дедупликации изображений.
Узнайте больше об агрегациях и дедупликации в FiftyOne Docs.
Присоединяйтесь к сообществу FiftyOne!
Присоединяйтесь к тысячам инженеров и специалистов по данным, уже использующих FiftyOne для решения некоторых из самых сложных задач в области компьютерного зрения уже сегодня!
- 1400+ участников FiftyOne Slack
- 2600+ звезд на GitHub
- 3300+ Участников встречи
- Используется 254+ репозитория
- 56+ авторов
Что дальше?
- Если вам нравится то, что вы видите на GitHub, поставьте звезду проекту.
- "Начать!" Мы упростили запуск и запуск за несколько минут.
- Присоединяйтесь к сообществу Slack FiftyOne, мы всегда рады помочь.
Первоначально опубликовано на https://voxel51.com 10 марта 2023 г.