yolov8-seg分割踩坑:关于model保存含掩码结果与返回值results中的mask结果不一致发生偏移的问题及解决方法

问题:

推理代码:

 results = model(r'/root/2_4.jpg', save=True, save_crop=False,
                    imgsz=640, classes=[1], max_det=1, show_labels=False, show_conf=False,
                    show_boxes=False) 

使用如下代码,保存results返回值的masks对象中的二值化掩码结果:

        if result.masks is not None and len(result.masks) > 0:
            masks_data = result.masks.data
            for index, mask in enumerate(masks_data):
                mask = mask.cpu().numpy() * 255
                cv2.imwrite(pred_image_path, mask)

将掩码再进行最小矩形处理并绘制结果:

model保存输出掩码结果:

results中的保存mask绘制结果:


可以发现发生了明显的偏移!!!
反复调试代码,发现不是后处理产生的问题。model的results返回值就已经是偏移后的mask!

原因:

进入源码mask处理的utils/plotting.py中的:

 def masks(self, masks, colors, im_gpu, alpha=0.5, retina_masks=False):
        """Plot masks at once.
        Args:
            masks (tensor): predicted masks on cuda, shape: [n, h, w]
            colors (List[List[Int]]): colors for predicted masks, [[r, g, b] * n]
            im_gpu (tensor): img is in cuda, shape: [3, h, w], range: [0, 1]
            alpha (float): mask transparency: 0.0 fully transparent, 1.0 opaque
        """
        if self.pil:
            # convert to numpy first
            self.im = np.asarray(self.im).copy()
        if len(masks) == 0:
            self.im[:] = im_gpu.permute(1, 2, 0).contiguous().cpu().numpy() * 255
        colors = torch.tensor(colors, device=im_gpu.device, dtype=torch.float32) / 255.0
        colors = colors[:, None, None]  # shape(n,1,1,3)
        masks = masks.unsqueeze(3)  # shape(n,h,w,1)
        masks_color = masks * (colors * alpha)  # shape(n,h,w,3)

        inv_alph_masks = (1 - masks * alpha).cumprod(0)  # shape(n,h,w,1)
        mcs = (masks_color * inv_alph_masks).sum(0) * 2  # mask color summand shape(n,h,w,3)

        im_gpu = im_gpu.flip(dims=[0])  # flip channel
        im_gpu = im_gpu.permute(1, 2, 0).contiguous()  # shape(h,w,3)
        im_gpu = im_gpu * inv_alph_masks[-1] + mcs
        im_mask = (im_gpu * 255)
        im_mask_np = im_mask.byte().cpu().numpy()
        self.im[:] = im_mask_np if retina_masks else scale_image(im_gpu.shape, im_mask_np, self.im.shape)
        if self.pil:
            # convert im back to PIL and update draw
            self.fromarray(self.im)

将mask绘制可视化出来:

可以发现在masks方法处理中:

1、yolo向两边填充了灰色像素!而在results是中并没有处理掉!即产生了偏移。
2、尺寸缩放为640大小。


解决:

开始想尝试自己后处理掉多余像素,但发现masks方法中使用了scale_image方法

scale_image(im_gpu.shape, im_mask_np, self.im.shape)

utils/ops.py中

将results返回值的中的二值化掩码和原图像尺寸放入scale_image方法,返回矫正后的二值化掩码结果。

mask = ops.scale_image(mask, img.shape)

成功解决:

去除了灰边和缩放为原尺寸,矫正后的mask:

model保存结果和results中的mask结果一致:

最后:

感谢@木彳-CSDN博客提供的代码实例解读,免去了debug的麻烦。
yolov8-seg后处理,代码示例解读_yolov8分割结果处理-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_22734027/article/details/134051978

### YOLOv8 图像分割保存掩码文件 为了确保在使用YOLOv8进行图像分割时只保存生成的掩码文件而保存其他输出,可以通过调整代码中的参数设置来实现这一目标。具体来说,在调用模型预测函数时,可以指定`save_masks_only=True`选项。 #### 修改预测脚本以仅保存掩码 当配置YOLOv8用于图像分割任务时,可以在预测过程中通过修改源代码或自定义命令行参数的方式控制输出行为。对于官方提供的Python API接口而言,通常是在实例化检测器对象之后以及启动推理之前加入特定标志位: ```python from ultralytics import YOLO model = YOLO('yolov8n-seg.pt') # 加载预训练权重 results = model.predict(source='path/to/images', save=True, save_txt=False, save_conf=False, save_crop=False, save_masks_only=True) ``` 这段代码设置了多个布尔型变量来决定哪些类型的中间结果应该被记录下来;其中最关键的就是`save_masks_only=True`这一步骤[^1]。它指示程序仅仅保留二值化的蒙版数据而忽略其余任何额外的信息(比如边界框坐标、置信度分数等)。此外,还关闭了文本日志(`save_txt`)、置信度得分存储(`save_conf`)和裁剪区域提取(`save_crop`)等功能模块以免干扰最终所需的纯黑白遮罩效果。 #### 自定义后处理逻辑 有时默认的行为可能无法完全满足需求,这时就需要深入理解框架内部机制并对其实现细节做出适当改动。例如,在某些情况下,可能会希望进一步精简输出内容或者改变其格式。此时可以根据实际情况重写部分核心算法,如引用中提到的`scale_image()`函数就是用来调整大小的一个例子[^2]。过一般情况下,默认提供的API已经能够很好地支持大多数应用场景下的定制化要求。 #### 输出路径管理 关于如何组织这些单独保存下来的mask文件,则取决于个人偏好或是项目规定。按照惯例,所有此类资源会被集中存放在一个专门为此目的创建的新子目录内。该位置可通过传递给`.predict()`方法内的`project``name`两个关键字参数共同确定[^3]。这样做仅有助于保持工作区整洁有序,也便于后续批量操作或分析处理。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值