ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于 Ultralytics YOLO 的分割对象隔离指南:从推理结果中提取纯净目标图像

基于 Ultralytics YOLO 的分割对象隔离指南:从推理结果中提取纯净目标图像 基于 Ultralytics YOLO 的分割对象隔离指南从推理结果中提取纯净目标图像【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10导读本指南讲解如何在使用 Ultralytics YOLO 完成分割任务推理之后将检测到的各个目标对象从原始图像中抠出来——生成仅含目标的二值掩码并输出黑底、透明背景PNG或裁剪后的纯净目标图像。这是一份通用的实战配方读完本文你将掌握Results结果对象中masks、boxes的底层数据结构能够用 OpenCV NumPy 自主实现目标提取管线并了解内置save_crop参数等更省事的替代方案。该能力在电商素材抠图、目标数据集裁剪、图像预处理等场景中非常实用。1. 前置知识分割推理的产出物YOLOv8 分割模型yolov8n-seg.pt等-seg后缀模型的输出不仅是目标框还包括每个目标的像素级掩码mask。在 Ultralytics 框架中predict()返回的是Results对象列表其核心属性定义于 ultralytics/engine/results.py属性类型含义orig_imgnumpy.ndarray原始图像BGR未被缩放boxesBoxes检测框支持xyxy、xywh、conf、cls等属性masksMasks分割掩码提供xy、xyn等轮廓坐标属性namesdict类别名称映射如{0: person, ...}pathstr输入图像的文件路径从源码看分割推理的后处理由 ultralytics/models/yolo/segment/predict.py 中的SegmentationPredictor.postprocess()完成先经 NMS 得到预测框再通过ops.process_mask()将掩码上采样回原始尺寸最终以Results(orig_img, path, names, boxespred[:, :6], masksmasks)的形式打包返回。也就是说results[i].masks中的掩码数据已经对齐到原始图像尺寸这正是我们能直接用它做像素级隔离的基础。2. 逐步配方目标隔离的完整流程2.1 导入依赖from pathlib import Path import cv2 import numpy as np from ultralytics import YOLOcv2OpenCV用于绘制轮廓、位运算与保存图像numpy用于数组类型转换、形状变换与通道堆叠YOLOUltralytics 推理入口。2.2 加载模型并执行推理from ultralytics import YOLO # 加载一个预训练分割模型 model YOLO(yolov8n-seg.pt) # 运行推理 results model.predict()模型选择仓库支持yolov8n-seg.pt、yolov8s-seg.pt、yolov8m-seg.pt、yolov8l-seg.pt、yolov8x-seg.pt等分割模型详见分割任务文档中的模型性能表。模型权重在首次使用时自动下载。不传 source 参数时predict()会使用库自带的示例图片ultralytics/assets/bus.jpg与ultralytics/assets/zidane.jpg见 assets 目录非常适合快速验证流程。如需指定数据源可传图片路径、目录、URL 或视频流完整参数见 Predict 模式文档。2.3 迭代结果与轮廓# 迭代检测结果对多张图片同样适用 for r in results: img np.copy(r.orig_img) img_name Path(r.path).stem # 源图片的 base-name后续保存文件时用 # 迭代每个目标轮廓同一张图可能有多个检测目标 for ci, c in enumerate(r): # 获取检测类别名称 label c.names[c.boxes.cls.tolist().pop()]说明外层for r in results每张输入图片对应一个Results内层for ci, c in enumerate(r)遍历该图上的每个检测目标ci是该目标的索引同一类别出现多个实例时用来区分c.boxes.cls返回类别索引张量Boxes.cls在 results.py 中定义为self.data[:, -1].tolist().pop()取出其中的整型类别号再用c.names[...]映射为类别名称单张图片时外层循环只执行一次单张图且只有一个检测目标时两层循环都只执行一次。2.4 生成二值掩码并绘制填充轮廓隔离目标的关键一步从原图尺寸生成一张全零的二值图把目标轮廓以白色255填充进去其余区域保持 0。# 创建与原图同尺寸的二值掩码单通道 b_mask np.zeros(img.shape[:2], np.uint8) # 提取轮廓坐标点 contour c.masks.xy.pop() # (x, y) 像素坐标点集 contour contour.astype(np.int32) # float32 - int32兼容 drawContours contour contour.reshape(-1, 1, 2) # 整理为 [N, 1, 2] 形状 # 将轮廓填充绘制到掩码上 _ cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)contour三步处理的内部原理c.masks.xy返回掩码轮廓点坐标列表格式为(x, y)像素坐标。底层实现见 results.py 的Masks.xy属性——它调用ops.masks2segments()将每个掩码张量转换为轮廓点序列再通过ops.scale_coords()缩放到原图坐标。.pop()masks.xy是只含一个元素的列表当前目标的轮廓用pop()取出该元素得到轮廓点数组。注意masks2segments()默认采用largest策略见 ops.py即单个掩码只保留面积最大的外部轮廓由cv2.findContours以RETR_EXTERNAL模式提取因此单目标场景下取单个轮廓是合理的。.astype(np.int32)masks.xy返回的坐标是float32类型而 OpenCV 的drawContours()不接受浮点坐标必须先转为int32。.reshape(-1, 1, 2)drawContours()要求轮廓形状为[N, 1, 2]——N为轮廓点数每个点用1个条目承载2个坐标值x, y-1表示该维度长度自动推断。drawContours()配置解读[contour]把轮廓包一层列表多个轮廓可同时传入经测试能正确生成目标轮廓掩码-1表示绘制传入的所有轮廓(255, 255, 255)绘制颜色为白色cv2.FILLED将轮廓包围的所有像素统一填充为白色其余像素保持 0——这正是二值掩码的含义也是后续隔离操作的依据。3. 两种隔离方案与各自的裁剪子选项拿到二值掩码b_mask后根据期望的背景表现有两种主流方案每种方案又分保持整图尺寸与裁剪到目标区域两个子选项。3.1 方案一黑色背景像素# 将单通道二值掩码转为三通道 mask3ch cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) # 用按位与运算隔离目标 isolated cv2.bitwise_and(mask3ch, img)工作原理二值掩码原本是单通道灰度图像而原图是三通道 BGR。cv2.cvtColor(..., cv2.COLOR_GRAY2BGR)先把掩码广播为三通道使两张图通道数一致满足后续混合运算的兼容性要求cv2.bitwise_and()逐像素按位与只有两个输入在同一位置像素值都大于 0 时结果才大于 0。掩码只在目标轮廓内部为 2550因此保留下来的恰好是原图中与轮廓区域重叠的像素轮廓之外全部变为 0呈现黑色。子选项 A保持整图尺寸无需额外步骤isolated即为原图尺寸、目标以外区域全黑的图像。子选项 B裁剪到目标区域利用检测框坐标做数组切片仅保留目标所在矩形区域# 获取边框坐标xmin, ymin, xmax, ymax x1, y1, x2, y2 c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32) # 裁剪到目标区域 iso_crop isolated[y1:y2, x1:x2]这行代码的三段式处理c.boxes.xyxy返回[xmin, ymin, xmax, ymax]格式的边框张量Boxes.xyxy在 results.py 中定义为self.data[:, :4]单位为原始图像像素.cpu().numpy().squeeze()从 GPU 移至 CPU、转为 NumPy 数组、去掉多余维度单目标时为形状(1, 4)→(4,).astype(np.int32)浮点坐标转整数才能用于数组切片isolated[y1:y2, x1:x2]按[ymin:ymax, xmin:xmax]切出目标区域。3.2 方案二透明背景像素# 将 BGR 三通道图与单通道二值掩码沿深度方向堆叠为四通道 isolated np.dstack([img, b_mask])工作原理np.dstack()沿第三维通道/深度方向堆叠数组。原图是 H×W×3二值掩码是 H×W×1堆叠后得到 H×W×4 的图像——即 BGRA 四通道。目标区域对应的 alpha 通道值为 255不透明轮廓之外的 alpha 为 0全透明保存为 PNG 格式时背景即呈现为透明。注意JPEG 不支持透明通道务必使用 PNG 保存。子选项 A保持整图尺寸无需额外步骤保存为 PNG 后整图尺寸、背景透明。子选项 B裁剪到目标区域与方案一完全相同# 获取边框坐标 x1, y1, x2, y2 c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32) # 裁剪到目标区域 iso_crop isolated[y1:y2, x1:x2]3.3 内置替代直接使用save_crop如果你只是想得到包含背景的裁剪图目标周围保留原背景不做二值隔离无需手写上述流程——这是 Ultralytics 的内置能力在predict()中设置save_cropTrue即可自动把每个检测目标按框裁剪保存该参数与完整推理参数列表见 Predict 模式文档。在结果对象层面Results.save_crop()方法也已内置见 results.py 的方法列表。4. 可选收尾将结果保存到文件隔离或裁剪完成后的下一步完全由你的业务决定。一个最基本的收尾是把结果写盘# 将隔离出的目标保存为 PNG 文件 _ cv2.imwrite(f{img_name}_{label}-{ci}.png, iso_crop)命名规则img_name是源图片 base-name来自Path(r.path).stemlabel是检测类别名ci是同一类下目标的序号三者组合可保证同一张图、同一类别、多个实例时文件名不冲突。此步骤可选不需要保存时可跳过。5. 完整示例代码以下将全部步骤合并为一个可直接运行的脚本。需要说明对要保存三通道BGR图像时用cv2.imwrite即可若选择了透明背景方案四通道OpenCV 写 PNG 也能保留 alpha 通道。实际使用中把两个for循环体封装为函数会更利于复用此处留作练习。from pathlib import Path import cv2 import numpy as np from ultralytics import YOLO model YOLO(yolov8n-seg.pt) # 加载分割模型 results model.predict() # 执行推理默认使用示例图片 # 迭代检测结果支持多张图片 for r in results: img np.copy(r.orig_img) # 原始图像副本 img_name Path(r.path).stem # 源图片 base-name # 迭代每个目标轮廓多个检测目标 for ci, c in enumerate(r): label c.names[c.boxes.cls.tolist().pop()] # 类别名称 # 创建二值掩码 b_mask np.zeros(img.shape[:2], np.uint8) # 提取轮廓并整理为 drawContours 所需格式合并为一行 contour c.masks.xy.pop().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) # 方案二透明背景需保存为 PNG 才能看到透明效果 isolated np.dstack([img, b_mask]) # 可选按检测框裁剪到目标区域对以上任一方案都适用 x1, y1, x2, y2 c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32) iso_crop isolated[y1:y2, x1:x2] # TODO: 在这里编写你的后续处理逻辑 # 例如cv2.imwrite(f{img_name}_{label}-{ci}.png, iso_crop)提示运行前请确认已安装ultralytics、opencv-python、numpy。安装引导参见快速开始文档。6. 源码级原理速查为便于深入理解与排查问题下面汇总本指南涉及的关键实现位置关注点源码位置关键说明分割推理后处理ultralytics/models/yolo/segment/predict.pyNMS →process_mask上采样 → 组装Results(boxes, masks)结果对象结构ultralytics/engine/results.pyorig_img、boxes、masks、names、path等属性掩码轮廓坐标ultralytics/engine/results.pyMasks.xy像素坐标与Masks.xyn归一化坐标掩码转轮廓算法ultralytics/utils/ops.pymasks2segments()cv2.findContourslargest策略检测框属性ultralytics/engine/results.pyBoxes.xyxy、Boxes.conf、Boxes.cls内置裁剪保存ultralytics/engine/results.pyResults.save_crop()方法7. 常见问题与注意事项为什么masks.xy取到的轮廓只有一个因为masks2segments()默认strategylargest每个掩码只保留最大外部轮廓ops.py。对绝大多数目标单个连通区域够用若目标本身有孔洞或由多个分离区域组成可关注concat策略或自行扩展。透明背景必须存 PNGnp.dstack([img, b_mask])产生的四通道图仅在 PNG 等支持 alpha 通道的格式下才保留透明效果。坐标系必须一致masks.xy与boxes.xyxy都基于原始图像坐标后处理时已用scale_boxes/scale_coords回缩因此可以直接与r.orig_img一起使用无需再次缩放。修改推理默认行为若想过滤低置信度目标或限定类别可在predict(conf0.25, classes[0])中传入参数完整参数说明见 Predict 模式文档。【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表