Как изолировать объекты сегментации с помощью Ultralytics YOLO#
Сегментация экземпляров создаёт маску с точностью до пикселя для каждого обнаруженного объекта, поэтому каждый объект можно отдельно извлечь из изображения. В этом руководстве показано, как преобразовать результаты сегментации Ultralytics YOLO в изолированные объекты с помощью режима Predict и OpenCV — на сплошном чёрном или прозрачном фоне, чтобы сохранить результат в PNG.
Смотри: Как удалить фон и выделить объекты с помощью сегментации Ultralytics YOLO и OpenCV в Python 🚀
Зачем изолировать объекты сегментации?#
Извлечение отдельных объектов из изображения открывает множество возможностей для дальнейшей обработки:
- Удаление фона на фотографиях товаров, в каталогах или при творческой обработке.
- Кадрирование отдельных объектов для создания наборов данных классификации на основе результатов детекции.
- Целевая обработка, чтобы на следующих этапах, например при OCR, анализе цвета или измерениях, обрабатывался только объект, а не окружающая сцена.
- Экспорт в PNG с прозрачностью, чтобы разместить объекты на новом фоне.
Этот способ подходит для любой модели сегментации Ultralytics YOLO и состоит из четырёх этапов: выполни инференс → извлеки каждый контур → изолируй объект → сохрани результат.
Выполнение инференса сегментации#
Установи необходимые библиотеки, затем загрузи модель сегментации (суффикс -seg необходим для создания масок) и выполни предсказание для исходного изображения:
from ultralytics import YOLO
# Загрузи модель сегментации
model = YOLO("yolo26n-seg.pt")
# Выполни инференс для исходного изображения
results = model.predict(source="path/to/image.jpg")Если вызвать model.predict() без source, Ultralytics использует примеры изображений, поставляемые вместе с пакетом (bus.jpg и zidane.jpg). Это удобно для быстрой проверки рабочего процесса.
Извлечение контуров объектов#
Каждый элемент results соответствует одному изображению, а при переборе результатов возвращается по одной детекции за раз. Для каждой детекции скопируй исходное изображение, прочитай метку класса и нарисуй контур маски объекта на пустой бинарной маске. Белая область этой маски точно показывает, какие пиксели принадлежат объекту.
Фрагменты кода в этом и следующем разделах выполняются внутри цикла детекции ниже; полный скрипт, который можно скопировать и запустить, приведён в разделе Полный пример.
from pathlib import Path
import cv2
import numpy as np
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem # базовое имя исходного изображения
# Перебери все обнаруженные объекты на изображении
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()] # имя класса
# Создай бинарную маску и нарисуй на ней контур объекта
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)c.masks.xy[0]возвращает контур маски в виде координат точек(x, y)объекта в результате с одной детекцией..astype(np.int32)преобразует точки изfloat32, которые OpenCVdrawContours()не принимает..reshape(-1, 1, 2)изменяет форму массива точек, приводя его к формату[N, 1, 2], который ожидаетdrawContours(), гдеN— количество точек контура.
Передача [contour] с индексом -1 рисует все точки указанного контура, а cv2.FILLED закрашивает белым каждый пиксель внутри него.
Изоляция объекта#
Когда бинарная маска готова, объедини её с исходным изображением. В зависимости от желаемого фона обычно используют один из двух вариантов:
Преобразуй маску в три канала и оставь только пиксели, которые пересекаются с объектом. Всё за пределами контура станет чёрным:
# Изолируй объект на чёрном фоне
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)
Чтобы оставить только область объекта, а не изображение целиком, обрежь его по ограничивающей рамке детекции:
# Координаты ограничивающей рамки
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# Обрежь изолированное изображение по области объекта
iso_crop = isolated[y1:y2, x1:x2]
Эта возможность встроена. Передай save_crop=True в predict(), и Ultralytics автоматически сохранит обрезанные области по ограничивающим рамкам — маска не нужна.
Сохранение результата (необязательно)#
Что делать с каждым изолированным объектом — решать тебе. Часто его записывают на диск для дальнейшего использования:
# Save the isolated object to file
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)Здесь img_name — основная часть имени исходного изображения, label — имя класса, а ci — индекс детекции, поэтому экземпляры одного класса получают уникальные имена файлов. Замени isolated на iso_crop, если выше ты применил необязательную обрезку.
Полный пример#
Приведённый ниже скрипт объединяет все этапы в один готовый к запуску блок. По умолчанию он использует чёрный фон; замени отмеченную строку на np.dstack([img, b_mask]), чтобы вместо этого получить PNG с прозрачностью:
from pathlib import Path
import cv2
import numpy as np
from ultralytics import YOLO
model = YOLO("yolo26n-seg.pt")
results = model.predict(source="path/to/image.jpg")
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()]
# Build a binary mask from the object contour
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
# Isolate the object (black background)
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img) # transparent PNG: isolated = np.dstack([img, b_mask])
# Save or add your custom post-processing here
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)
# Optional: crop to the bounding box before saving
# x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated[y1:y2, x1:x2])Если ты собираешься использовать этот код многократно, оберни тело цикла в функцию, чтобы вызывать её для множества изображений.
Заключение#
Теперь у тебя есть полный способ изолировать сегментированные объекты с помощью Ultralytics YOLO: выполни инференс, создай бинарную маску по каждому контуру, а затем извлеки объект на чёрном или прозрачном фоне и при желании обрежь его по ограничивающей рамке. Изучи полную документацию по задаче сегментации и режиму Predict, чтобы адаптировать рабочий процесс к своим классам.
Часто задаваемые вопросы#
Загрузи модель сегментации, выполни инференс, создай бинарную маску по контуру каждой детекции и объедини её с исходным изображением:
import cv2 import numpy as np from ultralytics import YOLO model = YOLO("yolo26n-seg.pt") results = model.predict(source="path/to/your/image.jpg") 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)Полный цикл для каждой детекции приведён в разделе Полный пример.
Есть два основных способа. Для чёрного фона преобразуй маску в три канала и используй
cv2.bitwise_and(). Для прозрачного фона (при сохранении в PNG) добавь маску четвёртым альфа-каналом с помощьюnp.dstack([img, b_mask]). Оба способа показаны в разделе Изоляция объекта.Прочитай координаты ограничивающей рамки из детекции и обрежь изолированное изображение:
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32) iso_crop = isolated[y1:y2, x1:x2]Подробнее о результатах с ограничивающими рамками читай в документации по режиму Predict.
Ultralytics YOLO обеспечивает быструю сегментацию экземпляров в реальном времени с точным созданием масок и ограничивающих рамок, а простой Python API позволяет выделять объекты по результатам инференса всего несколькими строками кода OpenCV.
Да. Используй аргумент
save_cropвpredict(), чтобы сохранять фрагменты ограничивающих рамок с исходным фоном:results = model.predict(source="path/to/your/image.jpg", save_crop=True)Подробнее см. в разделе Аргументы инференса в режиме Predict.