如何使用 Ultralytics YOLO 分离分割对象#
实例分割会为每个检测到的对象生成像素级的精确掩码,这意味着你可以将每个对象从图像中单独提取出来。本指南将向你展示如何使用预测模式和 OpenCV,将 Ultralytics YOLO 分割结果转换为隔离的对象,并使用纯黑背景或透明背景保存为 PNG。
Watch: How to Remove Background and Isolate Objects with Ultralytics YOLO Segmentation & OpenCV in Python 🚀
为什么要分离分割对象?#
从图像中提取单个对象可以开启一系列下游工作流程:
- 背景去除:用于产品拍摄、目录制作或创意编辑。
- 逐个对象裁剪:从检测结果中构建分类数据集。
- 聚焦处理:确保后续步骤(如 OCR、颜色分析或测量)仅看到对象本身,而非周围场景。
- 透明 PNG 导出:将对象合成到新背景上。
此方法适用于任何 Ultralytics YOLO 分割模型,并包含四个阶段:运行推理 → 提取每个轮廓 → 隔离对象 → 保存结果。
运行分割推理#
安装所需的库,然后加载分割模型(-seg 后缀是生成掩码所必需的)并对源图像运行预测:
from ultralytics import YOLO
# Load a segmentation model
model = YOLO("yolo26n-seg.pt")
# Run inference on a source
results = model.predict(source="path/to/image.jpg")如果在调用 model.predict() 时没有传入 source,Ultralytics 将默认使用随软件包附带的示例图像(bus.jpg 和 zidane.jpg),这对于快速测试工作流非常方便。
提取对象轮廓#
results 中的每个项目对应一张图像,遍历结果每次会产生一个检测结果。对于每个检测,复制原始图像,读取类别标签,并将对象的掩码轮廓绘制到空白的二值掩码上。该掩码的白色区域精确标出了哪些像素属于该对象。
本节和下一节中的代码片段运行在下方检测循环的内部;完整可复制的脚本位于完整示例。
{ width="240", align="right" }
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 # source image base-name
# Iterate each detected object in the image
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()] # class name
# Build a binary mask and draw the object contour onto it
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]返回此单个检测结果中对象的 mask 轮廓作为(x, y)点坐标。.astype(np.int32)转换了来自float32的点,这是 OpenCV 的drawContours()所不接受的。.reshape(-1, 1, 2)将这些点重塑为[N, 1, 2]布局drawContours()所期望的格式,其中N是轮廓点的数量。
传入带有索引 -1 的 [contour] 会绘制所提供轮廓的所有点,并且 cv2.FILLED 会将所有封闭像素填充为白色。
分离对象#
准备好二值掩码后,将其与原始图像结合。根据你想要的背景效果,有两种常见的样式:
将掩码转换为三个通道,并仅保留与对象重叠的像素。轮廓之外的所有区域都会变为黑色:
# Isolate object with a black background
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)如果只想保留对象所在的区域而不是全尺寸图像,可以将其裁剪至检测结果的边界框:
# Bounding box coordinates
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# Crop the isolated image to the object region
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 隔离分割对象的完整方法:运行推理、从每个轮廓构建二值掩码、然后在黑色或透明背景上提取对象,并可选择将其裁剪到边界框。探索完整的分割任务和预测模式文档,以将工作流适配到你自己的类别。
常见问题解答#
如何使用 Ultralytics YOLO 分离分割任务中的对象?#
加载一个分割模型,运行推理,从每个检测结果的轮廓构建二值掩码,并将其与原始图像结合:
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]) 将掩码堆叠为第四个 alpha 通道。两者均在隔离对象中展示。
如何将分离的对象裁剪至其边界框?#
从检测结果中读取边界框坐标并对分离出的图像进行切片:
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
iso_crop = isolated[y1:y2, x1:x2]在预测模式文档中了解有关边界框结果的更多信息。
为什么在分割任务中要使用 Ultralytics YOLO 来进行对象分离?#
Ultralytics YOLO 提供快速、实时的实例分割功能,具备精确的掩码和边界框生成能力,此外还有一个简洁的 Python API,只需几行 OpenCV 代码即可将推理结果转化为独立的对象。
我可以使用 Ultralytics YOLO 保存包含原始背景的分离对象吗?#
是的。在 predict() 中使用 save_crop 参数来保存带有原始背景的边界框裁剪图:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)在预测模式推理参数一节中阅读更多内容。