Изоляция объектов сегментации
После выполнения задачи сегментации иногда требуется извлечь отдельные объекты из результатов инференса. В этом руководстве представлен общий рецепт того, как это сделать, используя режим Predict Ultralytics.
Пошаговое руководство по рецепту
-
Краткое руководство по установке необходимых библиотек см. в разделе Краткое руководство по установке Ultralytics.
-
Загрузите модель и запустите
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 раздел Документации.
-
Теперь выполните итерацию по результатам и контурам. Для рабочих процессов, которые хотят сохранить изображение в файл, исходное изображение
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()]
- Чтобы узнать больше о работе с результатами обнаружения, см. раздел Раздел Boxes для режима Predict.
- Чтобы узнать больше о
predict()
результаты см. Работа с результатами для режима Predict
For-Loop (цикл for)
Одно изображение будет итерировать первый цикл только один раз. Одно изображение только с одним обнаружением будет итерировать каждый цикл только один раз.
-
Начните с создания бинарной маски из исходного изображения, а затем нарисуйте заполненный контур на маске. Это позволит изолировать объект от других частей изображения. Пример из
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)
-
Для получения дополнительной информации о
c.masks.xy
см. Раздел масок из режима Predict. -
Здесь значения приводятся к
np.int32
для совместимости сdrawContours()
функция из OpenCV. -
OpenCV
drawContours()
функция ожидает, что контуры будут иметь форму[N, 1, 2]
разверните раздел ниже для получения более подробной информации.
Разверните, чтобы понять, что происходит при определении
contour
.-
c.masks.xy
:: Предоставляет координаты точек контура маски в формате(x, y)
. Для получения более подробной информации обратитесь к Раздел масок из режима Predict. -.pop()
:: Какmasks.xy
- это список, содержащий один элемент, этот элемент извлекается с помощьюpop()
метод. -.astype(np.int32)
:: Используяmasks.xy
вернет тип данныхfloat32
, но это не будет совместимо с OpenCVdrawContours()
функцию, поэтому это изменит тип данных на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()
для получения дополнительной информации.
-
-
Далее есть 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]
- Для получения дополнительной информации о результатах ограничивающих рамок см. Раздел «Рамки» в режиме прогнозирования.
Что делает этот код?
-
Параметр
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]
- Для получения дополнительной информации о результатах ограничивающих рамок см. Раздел «Рамки» в режиме прогнозирования.
Что делает этот код?
-
При использовании
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 для получения подробной информации.
-
-
Что делать дальше, полностью зависит от вас как от разработчика. Показан простой пример одного из возможных следующих шагов (сохранение изображения в файл для дальнейшего использования).
- ПРИМЕЧАНИЕ: этот шаг является необязательным и может быть пропущен, если он не требуется для вашего конкретного случая использования.
Пример заключительного шага
# 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)
- Строка, заполняющая
contour
объединено в одну строку здесь, хотя выше было разделено на несколько. - Что здесь будет, решать вам!
- Для получения дополнительной информации см. Режим прогнозирования.
- Для получения дополнительной информации см. Задачу сегментации.
- Узнайте больше о Работе с результатами
- Узнайте больше о Результатах сегментации масок
Часто задаваемые вопросы
Как изолировать объекты с помощью Ultralytics YOLO11 для задач сегментации?
Чтобы изолировать объекты с помощью Ultralytics YOLO11, выполните следующие действия:
-
Загрузите модель и запустите вывод:
from ultralytics import YOLO model = YOLO("yolo11n-seg.pt") results = model.predict(source="path/to/your/image.jpg")
-
Создайте бинарную маску и нарисуйте контуры:
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)
-
Изолируйте объект, используя бинарную маску:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
Для получения дополнительной информации обратитесь к руководству по Режиму предсказания и Задаче сегментации.
Какие варианты доступны для сохранения изолированных объектов после сегментации?
Ultralytics YOLO11 предлагает два основных варианта сохранения изолированных объектов:
-
С черным фоном:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img)
-
С прозрачным фоном:
isolated = np.dstack([img, b_mask])
Для получения более подробной информации посетите раздел Режим Predict.
Как я могу вырезать отдельные объекты по ограничивающим рамкам, используя Ultralytics YOLO11?
Чтобы обрезать изолированные объекты до ограничивающих рамок:
-
Получение координат ограничивающего прямоугольника:
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
-
Обрежьте изолированное изображение:
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 раздел.