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

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

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

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

Просмотр рецептов

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


  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() метод, см. Режим предсказания в разделе Документация.


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

    from pathlib import Path
    
    import numpy as np
    
    #  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):
            #  Get detection class name
            label = c.names[c.boxes.cls.tolist().pop()]
    
    For-Loop

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


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

    Двоичное масочное изображение

    import cv2
    
    # Create binary mask
    b_mask = np.zeros(img.shape[:2], np.uint8)
    
    #  Extract contour result
    contour = c.masks.xy.pop()
    #  Changing the type
    contour = contour.astype(np.int32)
    #  Reshaping
    contour = contour.reshape(-1, 1, 2)
    
    
    # Draw contour onto mask
    _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
    

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

    • c.masks.xy :: Предоставляет координаты точек контура маски в формате (x, y). Для получения более подробной информации см. Раздел "Маски" из режима прогнозирования.

    • .pop() :: Как masks.xy является списком, содержащим один элемент, этот элемент извлекается с помощью pop() метод.

    • .astype(np.int32) :: Использование masks.xy вернется с типом данных float32но это не будет совместимо с OpenCV. drawContours() функция изменит тип данных на int32 для совместимости.

    • .reshape(-1, 1, 2) :: Переформатирует данные в требуемую форму [N, 1, 2] где N количество точек контура, каждая из которых представлена одной записью 1, и запись состоит из 2 ценности. Сайт -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) только В области контура остаются пиксели, перекрывающие контур исходного изображения.

    Изолировать с помощью черных пикселей: Подварианты

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

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

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

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

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

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

    #  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]
    

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

    • Сайт 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 файл.

    Изолировать с помощью прозрачных пикселей: Подварианты

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

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

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

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

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

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

    #  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]
    

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

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

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

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

    А если мне нужен обрезанный объект , включая фон?

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


  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")  
res = m.predict()  

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

    # Iterate each object contour 
    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 
        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 

ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ

Как выделить объекты с помощью 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])
    

Более подробную информацию можно найти в разделе "Режим прогнозирования ".

Как обрезать изолированные объекты до их ограничительных рамок с помощью 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]
    

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

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

Ultralytics YOLO11 обеспечивает:

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

Изучите преимущества использования YOLO в документации Segment Task.

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

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

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

Подробнее о save_crop аргумент в Аргументы для умозаключений в режиме предсказания раздел.

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

Комментарии