跳转至内容

分离分割对象

在执行分割任务后,有时需要从推理结果中提取孤立的对象。本指南提供了一个通用方法,说明如何使用 Ultralytics 预测模式来实现此目的。



观看: 如何使用Python 中的Ultralytics YOLO Segmentation 和OpenCV 移除背景并隔离物体 🚀

食谱攻略

  1. 请参阅Ultralytics 快速入门安装部分,以快速了解如何安装所需的库。


  2. 加载模型并运行 predict() source 上的 method。

    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() method,请参阅 Predict 模式 文档的章节。


  3. 现在,迭代处理结果和轮廓。对于希望将图像保存到文件的workflow,可以使用源图像 base-name 以及检测 class-label 被检索以供后续使用(可选)。

    from pathlib import Path
    
    import numpy as np
    
    # (2) Iterate detection results (helpful for multiple images)
    for r in results:
        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()]
    
    1. 要了解更多关于如何使用检测结果的信息,请参阅预测模式的框选部分
    2. 要了解更多关于 predict() 结果请参见 处理预测模式的结果
    For-Loop(循环)

    单个图像只会迭代第一个循环一次。仅具有单个检测的单个图像将迭代每个循环一次。


  4. 首先从源图像生成二元掩码,然后在掩码上绘制填充轮廓。这将允许对象与其他图像部分隔离。来自的示例 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)
    
    1. 有关更多信息 c.masks.xy 参见 预测模式中的掩码部分.

    2. 此处,这些值被转换为 np.int32 为了兼容 drawContours() function,来自 OpenCV.

    3. OpenCV drawContours() function 期望轮廓的形状为 [N, 1, 2] 下方展开部分的更多详细信息。

    展开以了解定义 contour 变量中。

    - c.masks.xy ::以格式提供掩码轮廓点的坐标 (x, y)。更多详情,请参考 预测模式中的掩码部分。 - .pop() ::作为 masks.xy 是一个包含单个元素的列表,该元素使用以下方式提取 pop() 方法。 - .astype(np.int32) ::使用 masks.xy 将返回数据类型 float32,但这将与 OpenCV 不兼容 drawContours() function,因此这将更改数据类型为 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) 在轮廓区域内,原始图像中剩余的像素是与轮廓重叠的像素。

    使用黑色像素隔离:子选项

    全尺寸图像

    如果保持全尺寸图像,则无需其他步骤。

    全尺寸隔离对象图像黑色背景示例
    全尺寸输出示例

    裁剪后的对象图像

    需要执行其他步骤才能裁剪图像以仅包含对象区域。

    示例:裁剪隔离对象图像(黑色背景)

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

    1. 有关边界框结果的更多信息,请参见预测模式中的框选部分
    这段代码是做什么的?
    • 字段 c.boxes.xyxy.cpu().numpy() 调用会以NumPy 数组的形式在 xyxy 格式,其中 xmin, ymin, xmaxymax 表示边界框矩形的坐标。 见 预测模式中的“框”部分 了解更多详情。

    • 字段 squeeze() 操作会删除NumPy 数组中不必要的维数,确保数组具有预期的形状。

    • 使用以下方法转换坐标值 .astype(np.int32) 将框坐标数据类型从以下类型更改为 float32int32,使其兼容使用索引切片进行图像裁剪。

    • 最后,使用索引切片从图像中裁剪边界框区域。边界由以下因素定义 [ymin:ymax, xmin:xmax] 检测边界框的坐标。

    # Isolate object with transparent background (when saved as PNG)
    isolated = np.dstack([img, b_mask])
    
    这是如何运作的?
    • 使用NumPy dstack() 结合生成的二值掩码,使用 function(沿深度轴堆叠数组)将创建一个具有四个通道的图像。这允许在保存为以下格式时,对象轮廓外的所有像素都是透明的 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]
    

    1. 有关边界框结果的更多信息,请参见预测模式中的框选部分
    这段代码是做什么的?
    • 当使用时 c.boxes.xyxy.cpu().numpy(),边界框将作为 NumPy 数组返回,使用 xyxy 框坐标格式,对应于点 xmin, ymin, xmax, ymax 有关边界框(矩形),请参见 预测模式中的“框”部分 更多信息。

    • 添加 squeeze() 确保从NumPy 数组中删除任何无关的维数。

    • 使用以下方法转换坐标值 .astype(np.int32) 将框坐标数据类型从以下类型更改为 float32int32 这将在使用索引切片裁剪图像时兼容。

    • 最后,使用索引切片裁剪边界框的图像区域,其中边界使用以下方式设置 [ymin:ymax, xmin:xmax] 检测边界框的坐标。

    如果我想要裁剪后的对象包括背景,该怎么办?

    这是Ultralytics 库的内置功能。请参见 save_crop 参数用于 Predict 模式推理参数 详情请见。


  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")  # (4)!
res = m.predict(source="path/to/image.jpg")  # (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]

        # Add your custom post-processing here (2)
  1. 填充的行 contour 在此处合并为单行,而在上面它被拆分为多行。
  2. 这里的内容由你决定!
  3. 有关更多信息,请参阅预测模式
  4. 有关更多信息,请参阅分割任务
  5. 了解更多关于 处理结果 的信息
  6. 了解更多关于 分割掩码结果 的信息

常见问题

如何使用 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]
    

了解更多关于 预测模式 文档中的边界框结果。

为什么我应该使用 Ultralytics YOLO11 在分割任务中进行对象隔离?

Ultralytics YOLO11 提供:

  • 高速实时对象检测和分割。
  • 精确的边界框和掩码生成,用于精确定位目标。
  • 全面的文档 和易于使用的API,可实现高效开发。

分割任务文档中,了解使用 YOLO 的优势。

是否可以使用 Ultralytics YOLO11 保存包括背景在内的孤立对象?

是的,这是 Ultralytics YOLO11 中的一个内置功能。使用 save_crop 中的参数 predict() method。例如:

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

阅读更多关于 save_crop 中的参数 Predict 模式推理参数 部分。



📅 2 年前创建 ✏️ 0 天前更新
glenn-jocherRizwanMunawarjk4epderrengerY-T-Gwillie.maddox@gmail.comUltralyticsAssistantIvorZhu331Burhan-Q

评论