问题:
推理代码:
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博客https://blog.csdn.net/qq_22734027/article/details/134051978