U-Net训练用JSON转Mask图像异常:仅生成细线问题修复求助
问题描述
需要将Labelme导出的JSON标注数据转换为U-Net训练用的Mask图像,使用一段Python代码后出现异常:首次运行仅部分Mask生成正常,其余仅呈现细线;再次运行后所有Mask都只剩细线。
原代码
import json import numpy as np import cv2 import os # Path to the folder containing JSON files json_folder = os.path.expanduser('~/Desktop/jeson') # Folder with JSON files # Path to the folder for saving mask images mask_folder = os.path.expanduser('~/Desktop/masks') # Folder to save masks # Ensure the folder for saving masks exists os.makedirs(mask_folder, exist_ok=True) # List all JSON files in the folder for filename in os.listdir(json_folder): if filename.endswith('.json'): json_file = os.path.join(json_folder, filename) # Load data from the JSON file with open(json_file) as f: data = json.load(f) # Create an empty mask mask = np.zeros((data['imageHeight'], data['imageWidth']), dtype=np.uint8) # Add regions to the mask for shape in data['shapes']: points = np.array(shape['points'], dtype=np.int32) if len(points) > 0: # Fill the area defined by the points with white color cv2.fillPoly(mask, [points], 49) # Save the mask as a PNG image using OpenCV mask_filename = os.path.splitext(filename)[0] + '_mask.png' cv2.imwrite(os.path.join(mask_folder, mask_filename), mask) print("Conversion completed, and mask images have been saved in the 'masks' folder!")
问题原因
- 坐标精度丢失:Labelme导出的标注坐标是浮点数,直接强制转换为
int32会截断小数部分,导致多边形顶点错位,无法形成可填充的闭合区域,cv2.fillPoly只能画出边缘细线。 - 多边形未闭合:部分标注的多边形首尾点未重合,
cv2.fillPoly对非闭合多边形的填充行为不稳定,容易出现填充失败。 - 无效形状处理:代码未过滤顶点数不足3的无效形状,这类形状无法形成多边形,自然无法填充。
修复方案
修正后的代码
import json import numpy as np import cv2 import os json_folder = os.path.expanduser('~/Desktop/jeson') mask_folder = os.path.expanduser('~/Desktop/masks') os.makedirs(mask_folder, exist_ok=True) for filename in os.listdir(json_folder): if filename.endswith('.json'): json_file = os.path.join(json_folder, filename) with open(json_file) as f: data = json.load(f) # 创建空掩码,匹配原图像尺寸 mask = np.zeros((data['imageHeight'], data['imageWidth']), dtype=np.uint8) for shape in data['shapes']: # 对浮点坐标四舍五入后转int,避免精度丢失导致顶点偏移 points = np.round(np.array(shape['points'])).astype(np.int32) # 确保多边形闭合:首尾点不重合时,补全首点到末尾 if len(points) >= 3 and not np.array_equal(points[0], points[-1]): points = np.vstack([points, points[0]]) # 仅处理有效多边形(至少3个顶点) if len(points) >= 3: # 填充多边形区域,这里用255(白色),若需49可直接替换 cv2.fillPoly(mask, [points], 255) # 无损保存PNG掩码 mask_filename = os.path.splitext(filename)[0] + '_mask.png' cv2.imwrite(os.path.join(mask_folder, mask_filename), mask, [cv2.IMWRITE_PNG_COMPRESSION, 0]) print("转换完成,掩码已保存到masks文件夹!")
关键修改点
- 坐标精度修正:用
np.round()处理浮点坐标后再转整数,避免截断导致的顶点错位。 - 多边形闭合处理:自动补全首尾点,确保多边形严格闭合,保证填充功能正常工作。
- 无效形状过滤:只处理顶点数≥3的有效多边形,排除无法填充的无效标注。
- 保存优化:添加PNG无损压缩参数,避免图像保存时的质量损失;填充值默认用255(U-Net训练通用的掩码白色值),需保留49可直接修改。
内容的提问来源于stack exchange,提问作者user25377348
相关产品推荐
相关产品推荐

