确保预处理方式相同。
This commit is contained in:
@@ -97,11 +97,61 @@ class COCOToSegFormerConverter:
|
||||
|
||||
return np.array(mask)
|
||||
|
||||
def _rle_to_mask(self, rle: Dict, image_size: Tuple[int, int]) -> np.ndarray:
|
||||
"""
|
||||
将COCO的RLE (Run-Length Encoding) 格式转换为像素级mask
|
||||
|
||||
RLE格式说明:
|
||||
- counts: [v1, v2, v3, ...] 交替表示背景和前景的像素数量
|
||||
- 从背景(0)开始,然后是前景(1),再是背景(0),依此类推
|
||||
- 像素顺序:从左到右,从上到下(行优先)
|
||||
|
||||
Args:
|
||||
rle: COCO的RLE字典,格式为 {"counts": [n1, n2, ...], "size": [height, width]}
|
||||
image_size: 图像尺寸 (width, height)
|
||||
|
||||
Returns:
|
||||
mask: 二值mask数组 (H, W),1表示目标区域,0表示背景
|
||||
"""
|
||||
width, height = image_size
|
||||
|
||||
# 获取RLE的counts
|
||||
if 'counts' in rle:
|
||||
counts = rle['counts']
|
||||
else:
|
||||
print(f" ⚠️ 警告: RLE格式不包含counts字段")
|
||||
return np.zeros((height, width), dtype=np.uint8)
|
||||
|
||||
# 创建一维数组
|
||||
mask = np.zeros(height * width, dtype=np.uint8)
|
||||
|
||||
current_pos = 0
|
||||
current_value = 0 # 从背景开始
|
||||
|
||||
for count in counts:
|
||||
# 如果当前是前景(1),填充mask
|
||||
if current_value == 1:
|
||||
mask[current_pos:current_pos + count] = 1
|
||||
|
||||
# 移动位置
|
||||
current_pos += count
|
||||
|
||||
# 切换值(0 -> 1 -> 0 -> 1 ...)
|
||||
current_value = 1 - current_value
|
||||
|
||||
# 重塑为2D数组 (H, W)
|
||||
mask = mask.reshape((height, width))
|
||||
|
||||
return mask
|
||||
|
||||
def _merge_annotations(self, image_id: int, image_size: Tuple[int, int]) -> np.ndarray:
|
||||
"""
|
||||
合并一张图像的所有标注为单一mask
|
||||
|
||||
由于用户标注时所有食材区域都是同一类别,我们需要将同一图像的多个标注合并
|
||||
支持两种格式:
|
||||
1. Polygon格式: segmentation 是列表的列表
|
||||
2. RLE格式: segmentation 是包含 'counts' 字段的字典
|
||||
|
||||
Args:
|
||||
image_id: COCO图像ID
|
||||
@@ -120,11 +170,24 @@ class COCOToSegFormerConverter:
|
||||
|
||||
# 将所有标注合并到同一个mask
|
||||
for ann in annotations:
|
||||
if 'segmentation' in ann and isinstance(ann['segmentation'], list):
|
||||
# 转换polygon为mask
|
||||
obj_mask = self._polygon_to_mask(ann['segmentation'], image_size)
|
||||
# 合并到总mask(取并集)
|
||||
merged_mask = np.maximum(merged_mask, obj_mask)
|
||||
if 'segmentation' not in ann:
|
||||
continue
|
||||
|
||||
segmentation = ann['segmentation']
|
||||
|
||||
# 判断是RLE格式还是Polygon格式
|
||||
if isinstance(segmentation, dict) and 'counts' in segmentation:
|
||||
# RLE格式
|
||||
obj_mask = self._rle_to_mask(segmentation, image_size)
|
||||
elif isinstance(segmentation, list) and len(segmentation) > 0:
|
||||
# Polygon格式
|
||||
obj_mask = self._polygon_to_mask(segmentation, image_size)
|
||||
else:
|
||||
print(f" ⚠️ 警告: 未知的segmentation格式: {type(segmentation)}")
|
||||
continue
|
||||
|
||||
# 合并到总mask(取并集)
|
||||
merged_mask = np.maximum(merged_mask, obj_mask)
|
||||
|
||||
return merged_mask
|
||||
|
||||
@@ -247,7 +310,7 @@ def main():
|
||||
"""
|
||||
|
||||
# ==================== 配置区 ====================
|
||||
# TODO: 请根据您的实际路径修改以下三个变量
|
||||
# 请根据您的实际路径修改以下三个变量
|
||||
|
||||
# CVAT导出的COCO标注文件(通常名为instances_default.json)
|
||||
COCO_JSON_PATH = "d:/MyProjects/PythonProjects/FoodClassifier/SegFormer/data/raw_coco/annotations/instances_default.json"
|
||||
|
||||
Reference in New Issue
Block a user