Перейти к содержанию

Изоляция объектов сегментации

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

Пример сегментации изолированного объекта

Пошаговое руководство по рецепту

  1. Краткое руководство по установке необходимых библиотек см. в разделе Краткое руководство по установке Ultralytics.


  2. Загрузите модель и запустите predict() метод для источника.

    from ultralytics import YOLO
    
    # Load a model
    model = YOLO("yolo11n-seg.pt")
    
    # Run inference
    results = model.predict()
    

    Нет аргументов для предсказания?

    Без указания источника будут использоваться примеры изображений из библиотеки:

    'ultralytics/assets/bus.jpg'
    'ultralytics/assets/zidane.jpg'
    

    Это полезно для быстрого тестирования с помощью predict() метод.

    Для получения дополнительной информации о моделях сегментации посетите Задача сегментации странице. Чтобы узнать больше о predict() метод, см. Режим predict раздел Документации.


  3. Теперь выполните итерацию по результатам и контурам. Для рабочих процессов, которые хотят сохранить изображение в файл, исходное изображение base-name и обнаружение class-label извлекаются для последующего использования (необязательно).

    from pathlib import Path
    
    import numpy as np
    
    # (2) Iterate detection results (helpful for multiple images)
    for r in res:
        img = np.copy(r.orig_img)
        img_name = Path(r.path).stem  # source image base-name
    
        # Iterate each object contour (multiple detections)
        for ci, c in enumerate(r):
            # (1) Get detection class name
            label = c.names[c.boxes.cls.tolist().pop()]
    
    1. Чтобы узнать больше о работе с результатами обнаружения, см. раздел Раздел Boxes для режима Predict.
    2. Чтобы узнать больше о predict() результаты см. Работа с результатами для режима Predict
    For-Loop (цикл for)

    Одно изображение будет итерировать первый цикл только один раз. Одно изображение только с одним обнаружением будет итерировать каждый цикл только один раз.


  4. Начните с создания бинарной маски из исходного изображения, а затем нарисуйте заполненный контур на маске. Это позволит изолировать объект от других частей изображения. Пример из bus.jpg для одного из обнаруженных person объекты класса показаны справа.

    Изображение бинарной маски

    import cv2
    
    # Create binary mask
    b_mask = np.zeros(img.shape[:2], np.uint8)
    
    # (1) Extract contour result
    contour = c.masks.xy.pop()
    # (2) Changing the type
    contour = contour.astype(np.int32)
    # (3) Reshaping
    contour = contour.reshape(-1, 1, 2)
    
    
    # Draw contour onto mask
    _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    
    1. Для получения дополнительной информации о c.masks.xy см. Раздел масок из режима Predict.

    2. Здесь значения приводятся к np.int32 для совместимости с drawContours() функция из OpenCV.

    3. OpenCV drawContours() функция ожидает, что контуры будут иметь форму [N, 1, 2] разверните раздел ниже для получения более подробной информации.

    Разверните, чтобы понять, что происходит при определении contour .

    - c.masks.xy :: Предоставляет координаты точек контура маски в формате (x, y). Для получения более подробной информации обратитесь к Раздел масок из режима Predict. - .pop() :: Как masks.xy - это список, содержащий один элемент, этот элемент извлекается с помощью pop() метод. - .astype(np.int32) :: Используя masks.xy вернет тип данных float32, но это не будет совместимо с OpenCV drawContours() функцию, поэтому это изменит тип данных на int32 для совместимости. - .reshape(-1, 1, 2) :: Преобразует данные в требуемую форму [N, 1, 2] где N это количество точек контура, где каждая точка представлена одной записью 1, и запись состоит из 2 values. The -1 обозначает, что количество значений по этому измерению является гибким.

    Разверните для объяснения drawContours() конфигурация.

    - Инкапсуляция contour переменная в квадратных скобках, [contour], эффективно генерировала желаемую маску контура во время тестирования. - Значение -1 указанный для drawContours() параметр указывает функции нарисовать все контуры, присутствующие на изображении. - tuple (255, 255, 255) представляет белый цвет, который является желаемым цветом для рисования контура в этой бинарной маске. - Добавление cv2.FILLED закрасит все пиксели, заключенные контуром, одним и тем же цветом, в данном случае все заключенные пиксели будут белыми. - Смотрите Документация OpenCV на drawContours() для получения дополнительной информации.


  5. Далее есть 2 варианта дальнейших действий с изображением из этой точки и последующий вариант для каждого.

    Параметры изоляции объектов

    Пример

    # Create 3-channel mask
    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    
    # Isolate object with binary mask
    isolated = cv2.bitwise_and(mask3ch, img)
    
    Как это работает?
    • Сначала бинарная маска преобразуется из одноканального изображения в трехканальное. Это преобразование необходимо для последующего шага, где маска и исходное изображение объединяются. Оба изображения должны иметь одинаковое количество каналов, чтобы быть совместимыми с операцией смешивания.

    • Исходное изображение и трехканальная бинарная маска объединяются с использованием функции OpenCV. bitwise_and(). Эта операция сохраняет только значения пикселей, которые больше нуля (> 0) из обоих изображений. Поскольку пиксели маски больше нуля (> 0) только внутри контурной области пиксели, оставшиеся от исходного изображения, — это те, которые перекрываются с контуром.

    Изоляция с черными пикселями: Подпараметры

    Полноразмерное изображение

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

    Пример полноразмерного изолированного объекта, изображение, черный фон
    Пример полноразмерного вывода

    Обрезанное изображение объекта

    Дополнительные шаги, необходимые для обрезки изображения, чтобы включить только область объекта.

    Пример кадрирования изолированного объекта, изображение, черный фон

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2]
    

    1. Для получения дополнительной информации о результатах ограничивающих рамок см. Раздел «Рамки» в режиме прогнозирования.
    Что делает этот код?
    • Параметр c.boxes.xyxy.cpu().numpy() вызов возвращает ограничивающие рамки в виде массива NumPy в xyxy формат, где xmin, ymin, xmaxи ymax представляют координаты прямоугольника ограничивающей рамки. Смотрите Раздел ограничивающих прямоугольников из режима Predict для получения более подробной информации.

    • Параметр squeeze() операция удаляет все ненужные измерения из массива NumPy, гарантируя, что он имеет ожидаемую форму.

    • Преобразование значений координат с использованием .astype(np.int32) изменяет тип данных координат ограничивающего прямоугольника с float32 в int32, что делает их совместимыми для обрезки изображений с использованием индексных срезов.

    • Наконец, область ограничивающего прямоугольника вырезается из изображения с использованием нарезки индексов. Границы определяются [ymin:ymax, xmin:xmax] координаты ограничивающего прямоугольника обнаружения.

    # Isolate object with transparent background (when saved as PNG)
    isolated = np.dstack([img, b_mask])
    
    Как это работает?
    • Использование NumPy dstack() функция (стекирование массивов вдоль оси глубины) в сочетании с созданной бинарной маской создаст изображение с четырьмя каналами. Это позволяет сделать все пиксели за пределами контура объекта прозрачными при сохранении в формате PNG файле.

    Изоляция с прозрачными пикселями: Подпараметры

    Полноразмерное изображение

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

    Пример полноразмерного изолированного объекта, изображение, без фона
    Пример полноразмерного вывода + прозрачный фон

    Обрезанное изображение объекта

    Дополнительные шаги, необходимые для обрезки изображения, чтобы включить только область объекта.

    Пример кадрирования изолированного объекта, изображение, без фона

    # (1) Bounding box coordinates
    x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
    # Crop image to object region
    iso_crop = isolated[y1:y2, x1:x2]
    

    1. Для получения дополнительной информации о результатах ограничивающих рамок см. Раздел «Рамки» в режиме прогнозирования.
    Что делает этот код?
    • При использовании c.boxes.xyxy.cpu().numpy(), ограничивающие рамки возвращаются в виде массива NumPy, используя xyxy формат координат ограничивающего прямоугольника, которые соответствуют точкам xmin, ymin, xmax, ymax для ограничивающего прямоугольника, см. Раздел ограничивающих прямоугольников из режима Predict для получения дополнительной информации.

    • Добавление squeeze() гарантирует, что все посторонние измерения будут удалены из массива NumPy.

    • Преобразование значений координат с использованием .astype(np.int32) изменяет тип данных координат ограничивающего прямоугольника с float32 в int32 который будет совместим при обрезке изображения с использованием индексных срезов.

    • Наконец, область изображения для ограничивающего прямоугольника обрезается с использованием нарезки индексов, где границы устанавливаются с использованием [ymin:ymax, xmin:xmax] координаты ограничивающего прямоугольника обнаружения.

    Что, если я хочу получить вырезанный объект включая фон?

    Это встроенная функция для библиотеки Ultralytics. Смотрите save_crop аргумент для Аргументы вывода режима predict для получения подробной информации.


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

    • ПРИМЕЧАНИЕ: этот шаг является необязательным и может быть пропущен, если он не требуется для вашего конкретного случая использования.
    Пример заключительного шага
    # Save isolated object to file
    _ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)
    
    • В этом примере, img_name это базовое имя исходного файла изображения, label это обнаруженное имя класса, и ci это индекс обнаружения объектов (в случае нескольких экземпляров с одинаковым именем класса).

Полный пример кода

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

from pathlib import Path

import cv2
import numpy as np

from ultralytics import YOLO

m = YOLO("yolo11n-seg.pt")  # (4)!
res = m.predict()  # (3)!

# Iterate detection results (5)
for r in res:
    img = np.copy(r.orig_img)
    img_name = Path(r.path).stem

    # Iterate each object contour (6)
    for ci, c in enumerate(r):
        label = c.names[c.boxes.cls.tolist().pop()]

        b_mask = np.zeros(img.shape[:2], np.uint8)

        # Create contour mask (1)
        contour = c.masks.xy.pop().astype(np.int32).reshape(-1, 1, 2)
        _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)

        # Choose one:

        # OPTION-1: Isolate object with black background
        mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
        isolated = cv2.bitwise_and(mask3ch, img)

        # OPTION-2: Isolate object with transparent background (when saved as PNG)
        isolated = np.dstack([img, b_mask])

        # OPTIONAL: detection crop (from either OPT1 or OPT2)
        x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
        iso_crop = isolated[y1:y2, x1:x2]

        # TODO your actions go here (2)
  1. Строка, заполняющая contour объединено в одну строку здесь, хотя выше было разделено на несколько.
  2. Что здесь будет, решать вам!
  3. Для получения дополнительной информации см. Режим прогнозирования.
  4. Для получения дополнительной информации см. Задачу сегментации.
  5. Узнайте больше о Работе с результатами
  6. Узнайте больше о Результатах сегментации масок

Часто задаваемые вопросы

Как изолировать объекты с помощью Ultralytics YOLO11 для задач сегментации?

Чтобы изолировать объекты с помощью Ultralytics YOLO11, выполните следующие действия:

  1. Загрузите модель и запустите вывод:

    from ultralytics import YOLO
    
    model = YOLO("yolo11n-seg.pt")
    results = model.predict(source="path/to/your/image.jpg")
    
  2. Создайте бинарную маску и нарисуйте контуры:

    import cv2
    import numpy as np
    
    img = np.copy(results[0].orig_img)
    b_mask = np.zeros(img.shape[:2], np.uint8)
    contour = results[0].masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
    cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    
  3. Изолируйте объект, используя бинарную маску:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    

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

Какие варианты доступны для сохранения изолированных объектов после сегментации?

Ultralytics YOLO11 предлагает два основных варианта сохранения изолированных объектов:

  1. С черным фоном:

    mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
    isolated = cv2.bitwise_and(mask3ch, img)
    
  2. С прозрачным фоном:

    isolated = np.dstack([img, b_mask])
    

Для получения более подробной информации посетите раздел Режим Predict.

Как я могу вырезать отдельные объекты по ограничивающим рамкам, используя Ultralytics YOLO11?

Чтобы обрезать изолированные объекты до ограничивающих рамок:

  1. Получение координат ограничивающего прямоугольника:

    x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
    
  2. Обрежьте изолированное изображение:

    iso_crop = isolated[y1:y2, x1:x2]
    

Узнайте больше о результатах ограничивающих рамок в документации Режима прогнозирования.

Почему мне следует использовать Ultralytics YOLO11 для изоляции объектов в задачах сегментации?

Ultralytics YOLO11 предоставляет:

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

Узнайте о преимуществах использования YOLO в документации по задаче сегментации.

Могу ли я сохранить изолированные объекты, включая фон, с помощью Ultralytics YOLO11?

Да, это встроенная функция в Ultralytics YOLO11. Используйте save_crop аргумент в predict() метод. Например:

results = model.predict(source="path/to/your/image.jpg", save_crop=True)

Узнайте больше о save_crop аргумент в Аргументы вывода режима predict раздел.



📅 Создано 1 год назад ✏️ Обновлено 2 месяца назад

Комментарии