当你想要识别图片中特定物体的精确轮廓时,现成的公开数据集往往无法满足需求。比如你想区分农田里的不同作物,或者识别工业场景中的特定零件,这时候就需要构建自己的语义分割数据集。Deeplabv3+作为当前最先进的语义分割框架之一,对数据格式有着特定要求,而Labelme恰好是最适合个人开发者使用的标注工具。
我在处理农业遥感图像时就遇到过这个痛点。公开数据集里的"植物"类别根本无法区分玉米和小麦,只能自己动手标注。整个过程最耗时的不是模型训练,而是前期数据准备——从原始图片标注到生成Deeplabv3+可识别的PNG掩码,中间要经历多次格式转换。下面我就把踩坑后总结的最佳实践分享给大家。
推荐使用Anaconda快速搭建Python3.7环境:
bash复制conda create -n labelme python=3.7
conda activate labelme
pip install labelme
启动标注界面只需执行:
bash复制labelme
右键菜单中最重要的三个功能:
实测标注效率提升技巧:
对于复杂场景,建议采用分层标注法:
处理遮挡关系的黄金法则:
Labelme生成的JSON文件其实包含三个关键信息:
转换脚本的核心工作就是:
改进版的转换脚本增加了以下实用功能:
python复制def validate_labels(json_path, label_names):
"""检查是否有未定义标签"""
with open(json_path) as f:
data = json.load(f)
for shape in data['shapes']:
if shape['label'] not in label_names:
raise ValueError(f"发现未定义标签: {shape['label']}")
def batch_convert(input_dir, output_dir):
"""处理嵌套文件夹结构"""
for root, _, files in os.walk(input_dir):
rel_path = os.path.relpath(root, input_dir)
os.makedirs(os.path.join(output_dir, rel_path), exist_ok=True)
for file in files:
if file.endswith('.json'):
convert_single_file(
os.path.join(root, file),
os.path.join(output_dir, rel_path)
)
错误1:KeyError: '__ignore__'
__ignore__错误2:生成的PNG全是黑色
错误3:内存不足
python复制# 在处理大图时添加
import gc
gc.collect()
必须包含的文件夹:
code复制PV/
├── ImageSets/
│ └── Segmentation/
│ ├── train.txt
│ ├── val.txt
│ └── trainval.txt
├── JPEGImages/
│ ├── 0001.jpg
│ └── 0002.jpg
└── SegmentationClass/
├── 0001.png
└── 0002.png
进阶目录建议添加:
SegmentationClassRaw/:存储未经过颜色映射的单通道PNGAnnotations/:备份原始JSON文件preview/:存放标注可视化对比图不同于分类任务,语义分割的数据集划分需要特别注意:
改进版划分代码示例:
python复制def stratified_split(files, class_distribution, test_ratio=0.2):
"""保持类别分布的划分方法"""
from collections import defaultdict
class_groups = defaultdict(list)
# 按类别分组
for f in files:
class_id = get_dominant_class(f) # 需要实现该函数
class_groups[class_id].append(f)
# 分层抽样
train_files = []
test_files = []
for class_id, items in class_groups.items():
split_idx = int(len(items) * (1 - test_ratio))
train_files.extend(items[:split_idx])
test_files.extend(items[split_idx:])
return train_files, test_files
在datasets/目录下新建PV.py时,需要特别注意三个参数:
python复制class VOCSegmentation(data.Dataset):
NUM_CLASSES = 5 # 包含背景类
CLASS_NAMES = ['background', 'road', 'car', 'person', 'building']
COLOR_MAP = [(0,0,0), (128,0,0), (0,128,0), (128,128,0), (0,0,128)]
调试技巧:
__getitem__的输出palette与COLOR_MAP是否一致推荐使用Albumentations库进行高效增强:
python复制import albumentations as A
train_transform = A.Compose([
A.RandomCrop(512, 512),
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
A.ShiftScaleRotate(scale_limit=0.1, rotate_limit=10),
A.OneOf([
A.GaussNoise(),
A.Blur(),
], p=0.3),
])
特别注意:所有空间变换必须同时作用于图像和掩码
python复制transformed = train_transform(image=img, mask=mask)
img, mask = transformed['image'], transformed['mask']
现象:边缘分割不精确
python复制criterion = nn.CrossEntropyLoss(
weight=torch.tensor([1.0, 3.0]) # 边缘类别权重更高
)
现象:小目标识别效果差
加速数据加载的三种方法:
python复制env = lmdb.open('dataset.lmdb', map_size=1e12)
with env.begin(write=True) as txn:
txn.put(key.encode(), img_png.tobytes())
python复制DataLoader(..., num_workers=4, pin_memory=True)
内存优化配置:
python复制torch.backends.cudnn.benchmark = True # 加速卷积运算
torch.cuda.empty_cache() # 训练循环开始前释放缓存
建立质量检查闭环:
自动化测试脚本示例:
python复制def test_pipeline():
# 1. 生成虚拟标注
create_mock_data()
# 2. 执行格式转换
run_conversion()
# 3. 验证输出格式
verify_output()
# 4. 训练微型模型
train_dummy_model()
# 5. 检查预测结果
assert evaluate() > 0.9
在工业质检项目中,这套流程帮我们发现了3类典型问题:标注工具版本不一致导致的解析错误、图像EXIF方向信息丢失、以及中文路径引起的编码问题。