Ultralytics YOLO27:
Get Started

如何使用 Ultralytics YOLO 隔离分割对象#

实例分割会为每个检测到的对象生成像素级精确的掩码,因此你可以将每个对象单独从图像中提取出来。本指南将介绍如何使用 Predict 模式和 OpenCV,将 Ultralytics YOLO 分割结果转换为独立对象,并使用纯黑背景或透明背景保存为 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")
没有源图像?YOLO 会使用捆绑的示例图像

如果调用 model.predict() 时未指定 source,Ultralytics 会回退到随软件包附带的示例图像(bus.jpg 和 zidane.jpg),方便你快速测试工作流。

提取对象轮廓#

results 中的每个元素都对应一张图像,遍历结果时每次会得到一个检测对象。对于每个检测结果,复制原始图像,读取类别标签,并将对象的掩码轮廓绘制到空白二值掩码上。该掩码中的白色区域准确标示了属于该对象的像素。

本节和下一节中的代码片段都在下方的检测循环内部运行;完整的可直接复制粘贴的脚本见完整示例。

Binary Mask Image
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].astype(np.int32).reshape(-1, 1, 2)` 有什么作用?
  • c.masks.xy[0] 会以 (x, y) 点坐标的形式,返回此单个检测结果中对象的掩码轮廓。
  • .astype(np.int32) 会转换 float32 中的点,因为 OpenCV 的 drawContours() 不接受这种格式。
  • .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)
Example Full size Isolated Object Image Black Background
黑色背景上的完整尺寸对象
裁剪到边界框

如果只想保留对象区域,而不是完整尺寸的图像,可以按检测结果的边界框对图像进行切片:

# 边界框坐标
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# 将隔离后的图像裁剪到对象区域
iso_crop = isolated[y1:y2, x1:x2]
Example Crop Isolated Object Image Black Background
裁剪至边界框的对象
需要保留原始背景的裁剪图吗?

此功能已内置。将 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 隔离分割对象的完整方法:运行推理,根据每个轮廓创建二值掩码,然后在黑色或透明背景上提取对象,并可选择将对象裁剪到其边界框。你可以查看完整的 Segment 任务和 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 时),将掩码作为第四个 alpha 通道叠加,并使用 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 代码即可从推理结果中提取独立目标。

  • 可以。在 predict() 中使用 save_crop 参数,即可保存保留原始背景的边界框裁剪图:

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

    更多信息请参阅预测模式推理参数部分。

评论