如何在Python(Jupyter)中从SAM生成的CVAT XML提取标注为掩码文件
在Jupyter Notebook中加载CVAT XML并提取SAM生成的掩码
所需依赖库
先安装并导入必要的工具库:
import xml.etree.ElementTree as ET import numpy as np from PIL import Image
核心实现步骤
1. 解析CVAT XML标注文件
用Python内置XML解析库读取文件,遍历每个图片的标注节点:
# 替换为你的标注XML路径 tree = ET.parse('cvat_annotations.xml') root = tree.getroot() # 遍历所有图片的标注信息 for image_node in root.findall('image'): # 获取图片基本信息 img_name = image_node.get('name') img_w = int(image_node.get('width')) img_h = int(image_node.get('height')) # 遍历当前图片下的所有掩码标注(重点:找<mask>节点而非<box>) for mask_node in image_node.findall('mask'): target_label = mask_node.get('label') rle_raw = mask_node.get('rle') # 清理RLE字符串中的换行、多余空格,转成整数列表 rle_list = [int(num.strip()) for num in rle_raw.replace('\n', '').split(',') if num.strip()]
2. 解码RLE格式为二维掩码
CVAT中SAM生成的掩码用**行程长度编码(RLE)**存储,规则是交替记录「跳过的背景像素数」和「保留的前景像素数」,解码代码如下:
# 初始化一维掩码数组 mask_flat = np.zeros(img_w * img_h, dtype=np.uint8) current_idx = 0 rle_idx = 0 while rle_idx < len(rle_list): # 跳过背景像素 skip_pixels = rle_list[rle_idx] current_idx += skip_pixels # 标记前景像素(用255表示) keep_pixels = rle_list[rle_idx + 1] if current_idx + keep_pixels <= len(mask_flat): mask_flat[current_idx:current_idx + keep_pixels] = 255 current_idx += keep_pixels rle_idx += 2 # 转成与原图尺寸一致的二维掩码 mask_2d = mask_flat.reshape((img_h, img_w))
3. 掩码的保存与可视化
在Jupyter中可以直接显示掩码,或者保存为文件:
# 可视化掩码(Jupyter环境下) display(Image.fromarray(mask_2d)) # 保存掩码到本地(可选) mask_img = Image.fromarray(mask_2d) mask_img.save(f'{img_name}_{target_label}_mask.png')
关键注意事项
- 你之前得到边界框是因为多数教程默认提取
<box>节点,但SAM生成的标注存在<mask>节点中,必须遍历<mask>而非<box>。 - 如果只需要提取特定类别掩码,添加判断条件:
if target_label == '你的目标类别':再执行后续解码逻辑。 - 若RLE字符串存在格式异常(比如多余空值),清理步骤要确保过滤无效数据。
内容的提问来源于stack exchange,提问作者user23281936
相关产品推荐
相关产品推荐

