分离分割对象
在执行分割任务后,有时需要从推理结果中提取孤立的对象。本指南提供了一个通用方法,说明如何使用 Ultralytics 预测模式来实现此目的。
配方演练
-
请参阅Ultralytics 快速入门安装部分,以快速了解如何安装所需的库。
-
加载模型并运行
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 模式 文档的章节。
-
现在,迭代处理结果和轮廓。对于希望将图像保存到文件的workflow,可以使用源图像
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()]
For-Loop(循环)
单个图像只会迭代第一个循环一次。仅具有单个检测的单个图像将仅迭代每个循环一次。
-
首先从源图像生成二元掩码,然后在掩码上绘制填充轮廓。这将允许对象与其他图像部分隔离。来自的示例
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
参见 预测模式中的掩码部分. -
此处,这些值被转换为
np.int32
为了兼容drawContours()
function,来自 OpenCV. -
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()
更多信息。
-
-
接下来,对于从此时开始如何处理图像,以及每个图像的后续选项,有 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
表示边界框矩形的坐标。 见 预测模式中的“框”部分 了解更多详情。 -
字段
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()
结合生成的二值掩码,使用 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]
- 有关边界框结果的更多信息,请参见预测模式中的框选部分
这段代码是做什么的?
-
当使用时
c.boxes.xyxy.cpu().numpy()
,边界框将作为 NumPy 数组返回,使用xyxy
框坐标格式,对应于点xmin, ymin, xmax, ymax
有关边界框(矩形),请参见 预测模式中的“框”部分 更多信息。 -
添加
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])
有关更多详细信息,请访问预测模式部分。
如何使用 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()
method。例如:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)
阅读更多关于 save_crop
中的参数 Predict 模式推理参数 部分。