Runlength编码掩码与解码后掩码不一致问题排查求助
问题排查与修复
针对你在Severstal钢铁异常检测任务中遇到的增强后掩码编解码不一致问题,核心问题出在形状逻辑不匹配和掩码数值类型干扰这两个点,以下是具体排查和修复方案:
1. 核心问题分析
形状与转置的不匹配
你的rle_to_mask函数最终返回mask.reshape(shape).T,也就是将(width, height)的数组转置为(height, width)(即默认的(256,1600)),但mask_to_rle函数没有对应处理形状的逻辑,再加上测试代码中额外的cv2.resize操作,彻底打乱了编解码的形状对应关系:
- 增强后的
transformed_mask形状应为(256,1600) - 你执行
mask=cv2.resize(mask,(1600,256))将其改为(1600,256),此时mask_to_rle处理的是变形后的掩码,而rle_to_mask(lre)默认返回(256,1600)的掩码,自然内容和形状都无法匹配。
掩码数值类型的潜在干扰
数据增强后的掩码可能是浮点型(比如0.0/1.0),如果增强过程引入了模糊、插值导致的非0非1中间值,np.where(padded[1:] != padded[:-1])会错误识别更多边界,导致RLE编码错误。
2. 修复方案
调整mask_to_rle函数,统一形状逻辑
让mask_to_rle接收形状参数,确保编码的展平顺序和rle_to_mask的还原顺序完全对应:
import numpy as np def mask_to_rle(mask, shape=(1600, 256)): """ params: mask - numpy array (height, width),即(256,1600) shape - (width, height),对应原始图像尺寸(1600,256) returns: run-length encoding string (pairs of start & length of encoding) """ # 先转置为(width, height),和rle_to_mask的还原逻辑对齐 mask_transposed = mask.T flat = mask_transposed.flatten() # 强制转换为0/1整数,避免浮点精度问题 flat = flat.astype(np.uint8) padded = np.concatenate([[0], flat, [0]]) runs = np.where(padded[1:] != padded[:-1])[0] runs += 1 # 转换为从1开始的像素编号 runs[1::2] -= runs[0::2] return ' '.join(str(x) for x in runs)
修正测试代码中的无效操作
去掉打乱形状的cv2.resize,确保编解码使用一致的形状:
img, mask = augmentation_test(train_df) # 直接对增强后的掩码执行编解码 lre = mask_to_rle(mask) lree = rle_to_mask(lre) # 验证一致性 print(np.array_equal(mask, lree)) # 正常应返回True # 可视化对比 plt.subplot(121) plt.imshow(mask) plt.title('原增强掩码') plt.subplot(122) plt.imshow(lree) plt.title('解码后掩码') plt.show()
增强后掩码的二值化处理
在augmentation_test中添加二值化步骤,确保掩码只有0和1两种值:
import cv2 import pandas as pd import os from albumentations import transform def augmentation_test(dataframe:pd.DataFrame): record = dataframe.loc[np.random.randint(10)] image = cv2.imread(os.path.join("./train_images", record['ImageId']), 0) image = cv2.resize(image, (1600, 256)) mask = rle_to_mask(record['EncodedPixels']) transformed = transform(image=image, mask=mask) transformed_image = transformed['image'] # 二值化掩码,避免增强带来的中间值 transformed_mask = (transformed['mask'] > 0.5).astype(np.uint8) return transformed_image, transformed_mask
3. 验证逻辑
- 确认
rle_to_mask返回的掩码形状是(256,1600),与mask_to_rle接收的输入形状一致 - 增强后的掩码必须经过二值化处理,杜绝非0非1的中间值
- 编解码过程中不要随意修改掩码形状,保持形状对应关系
内容的提问来源于stack exchange,提问作者SANJAY. R
相关产品推荐
相关产品推荐

