Добро пожаловать в наш еженедельный блог с советами и рекомендациями FiftyOne, где мы резюмируем интересные вопросы и ответы, недавно появившиеся на Slack, GitHub, Stack Overflow и Reddit.

Подождите, а что такое FiftyOne?

FiftyOne — это набор инструментов машинного обучения с открытым исходным кодом, который позволяет группам специалистов по обработке и анализу данных повышать производительность своих моделей компьютерного зрения, помогая им выбирать высококачественные наборы данных, оценивать модели, находить ошибки, визуализировать встраивания и быстрее приступать к работе.

Хорошо, давайте погрузимся в советы и рекомендации этой недели!

Преобразование схемы ярлыков FiftyOne в CVAT

Член сообщества Slack Винисиус Мадурейра спросил:

«Я пытаюсь создать проект с помощью утилит FiftyOne CVAT и инициализировать его с помощью определенных классов. Я пытался использовать FiftyOne label_schema, но он не работает. Каким будет правильный label_schema

Чтобы создать проект CVAT с использованием утилит FiftyOne CVAT, вам необходимо передать label_schema соответствующую схему метки CVAT. Вы можете сгенерировать это из FiftyOne label_schema, используя функцию get_cvat_schema() в утилитах CVAT:

import fiftyone as fo
import fiftyone.utils.cvat as fouc
cvat = fouc.CVATAnnotationAPI(...)

project_name = “my_project_name”
project_id = “my_project_id”

### example FiftyOne label schema
label_schema = {
    "detections": {
        "type": "detections",
        "classes": [
            "class1",
            "class2",
            "class3",
        ]
    }
}

# conversion from FiftyOne to CVAT
# attrs embed concepts like occlusion and group ids from CVAT into FiftyOne
cvat_schema, assign_scalar_attrs, occluded_attrs, group_id_attrs = cvat._get_cvat_schema(
    label_schema,
    project_id=project_id,
    occluded_attr=occluded_attr,
    group_id_attr=group_id_attr,
)

cvat.create_project(project_name,schema=cvat_schema)

После преобразования схемы метки вы можете передать ее в функцию create_project() для создания проекта в CVAT.

cvat.create_project(project_name, schema = cvat_schema)

Узнайте больше об интеграции FiftyOne с CVAT в FiftyOne Docs.

Понимание показателя поддержки в оценках

Член сообщества Slack Исаак Падберг спросил:

"Я надеюсь получить некоторое представление о показателе support, отображаемом при печати отчета об оценке. Что это значит?»

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

Тем не менее, это может быть полезно для оценки производительности модели. Когда поддержка определенного класса невелика, метрики оценки для этого класса могут иметь высокую дисперсию.

Узнайте больше об API оценки FiftyOne в документации FiftyOne.

Отложенная загрузка больших медиафайлов в приложении FiftyOne

Член сообщества Slack Мохамед Серрари спросил:

"Есть ли способ отложенной загрузки медиафайлов с высоким разрешением, таких как спутниковые изображения, в приложение FiftyOne?"

При настройке приложения FiftyOne медиафайл, связанный с каждым образцом, отображается в виде сетки. По умолчанию медиафайл, отображаемый в представлении сетки, совпадает с медиафайлом, используемым для определения Sample (находится в sample.filepath ). Это хорошо работает для изображений малого и среднего размера.

Однако если вы имеете дело с изображениями в формате Ultra HD или со спутниковыми снимками, это может привести к медленной загрузке приложения FiftyOne. Лучшей практикой в ​​этих сценариях является создание эскиза изображения с более низким разрешением для каждого образца и настройка приложения для отображения эскизов в представлении сетки:

import fiftyone as fo
import fiftyone.utils.image as foui
import fiftyone.zoo as foz

dataset = foz.load_zoo_dataset("quickstart")

# Generate some thumbnail images
foui.transform_images(
    dataset,
    size=(-1, 32),
    output_field="thumbnail_path",
    output_dir="/tmp/thumbnails",
)

dataset.app_config.media_fields = ["filepath", "thumbnail_path"]
dataset.app_config.grid_media_field = "thumbnail_path"
dataset.save()

Миниатюры могут быть любого размера, если соотношение сторон соответствует исходному медиафайлу. С этими настройками медиафайл, отображаемый в расширенном модальном окне, по-прежнему будет исходной версией с полным разрешением.

Узнайте больше о нескольких полях мультимедиа и настройке приложения FiftyOne в FiftyOne Docs.

Фильтрация ограничивающих рамок по ширине и высоте

Член сообщества Slack Джордж Пирс спросил:

"Есть ли способ фильтровать ограничивающие рамки по их абсолютной ширине и высоте?"

Да! В FiftyOne обнаружение объектов хранится в образцах в Detection объектах с bounding_box атрибутами, которые хранят информацию о двумерной области в формате [top-left-x, top-left-y, width, height].

Эти размеры представлены в относительных координатах с размером относительно общего размера изображения в диапазоне [0,1]. Чтобы преобразовать это в абсолютные значения ширины и высоты, вы можете использовать абсолютную ширину и высоту изображения в пикселях, которые хранятся в поле metadata образца.

import fiftyone as fo
import fiftyone.zoo as foz

dataset = foz.load_zoo_dataset(“quickstart”)
## One-time computation of the metadata for all samples in dataset
dataset.compute_metadata()

### get abs width and height for first sample
sample = dataset.first()
img_width = sample.metadata.width
img_height = sample.metadata.height

По отношению к обнаружениям на изображении эти метаданные хранятся на родительском уровне. К счастью, с FiftyOne можно использовать эту информацию родительского уровня в фильтрах, добавляя к имени поля символ $ и передавая его в ViewField.

Например, чтобы получить наземные ограничивающие рамки с width < 400 и height < 600 пикселями, мы можем создать следующий фильтр:

from fiftyone import ViewField as F

rel_width = F("bounding_box")[2]
img_width = F("$metadata.width")
abs_width = rel_width * img_width

rel_height = F("bounding_box")[3]
img_height = F("$metadata.height")
abs_height = rel_height * img_height

size_filter = (abs_width < 400) & (abs_height < 600)

Наконец, мы можем применить этот фильтр к нашему набору данных:

small_boxes_view = dataset.filter_labels(
    "ground_truth", size_filter
)

Узнайте больше о синтаксисе MongoDB, лежащем в основе выражений FiftyOne в документации FiftyOne.

Выбор идентификаторов из сеанса

Участник сообщества Slack Дэн Эрез спросил:

"Есть ли способ извлечь список идентификаторов образцов, которые я выбрал, при использовании инструмента графика выбора?"

Если вы используете приложение FiftyOne для построения некоторых из ваших образцов, например, для визуализации встраивания uMAP, вы можете получить доступ к коллекции образцов, на которые в настоящее время нанесено лассо, с помощью plot.selected_ids. Это может быть полезно, если, например, вы хотите предварительно аннотировать выборку образцов по кластеру.

Эта функция демонстрирует простоту переключения между Python SDK и приложением FiftyOne. В качестве другого примера, если вы щелкнете изображение в сетке выборки и выберете ограничивающую рамку обнаружения, вы можете передать информацию о выборке и прогнозе в Python SDK с помощью session.selected_labels .

Узнайте больше о сеансах и приложении FiftyOne в FiftyOne Docs.

Присоединяйтесь к сообществу FiftyOne!

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

Что дальше?