| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- def convert_internal_to_labelme(image_path: str, internal_json: dict) -> dict:
- """
- 将系统内部的 detection_json/modified_json 转换为 LabelMe 格式
- """
- result = internal_json.get("result", {})
- img_h = result.get("imageHeight", 0)
- img_w = result.get("imageWidth", 0)
- labelme_data = {
- "version": "5.5.0",
- "flags": {},
- "shapes": [],
- "imagePath": image_path.lstrip("/\\"), # 去除开头的斜杠
- "imageData": None,
- "imageHeight": img_h,
- "imageWidth": img_w
- }
- # 1. 处理框 (Center Result -> Inner/Outer Box)
- # inner_box 放在第二个,outer_box 放在最上面
- center_result = result.get("center_result", {})
- box_result = center_result.get("box_result", {})
- inner_shape = None
- outer_shape = None
- # 提取 Inner Box
- if "inner_box" in box_result:
- shapes = box_result["inner_box"].get("shapes", [])
- if shapes and len(shapes) > 0:
- points = shapes[0].get("points", [])
- if points:
- inner_shape = {
- "label": "inner_box",
- "points": points,
- "group_id": None,
- "shape_type": "polygon",
- "flags": {}
- }
- # 提取 Outer Box
- if "outer_box" in box_result:
- shapes = box_result["outer_box"].get("shapes", [])
- if shapes and len(shapes) > 0:
- points = shapes[0].get("points", [])
- if points:
- outer_shape = {
- "label": "outer_box",
- "points": points,
- "group_id": None,
- "shape_type": "polygon",
- "flags": {}
- }
- # 添加到列表头部
- if outer_shape:
- labelme_data["shapes"].append(outer_shape)
- if inner_shape:
- labelme_data["shapes"].append(inner_shape)
- # 2. 处理缺陷 (Defects)
- defect_result = result.get("defect_result", {})
- defects = defect_result.get("defects", [])
- for defect in defects:
- shape = {
- "label": defect.get("label", "unknown"),
- "points": defect.get("points", []),
- "group_id": None,
- "description": "",
- "shape_type": "polygon",
- "flags": {},
- # 我们将系统特有的字段暂存到 extra_info 中,或者直接放在 shape 根目录下
- # LabelMe 打开时会忽略这些额外字段,但保存时通常会保留它们 (取决于版本)
- # 为了安全,关键信息最好也保留
- "system_data": {
- "confidence": defect.get("confidence"),
- "defect_type": defect.get("defect_type"),
- "score": defect.get("score"),
- "edit_type": defect.get("edit_type", "edit")
- }
- }
- labelme_data["shapes"].append(shape)
- return labelme_data
- def convert_labelme_to_internal(original_json: dict, labelme_json: dict) -> dict:
- """
- 将 LabelMe JSON 还原为系统内部格式结构。
- 注意:我们只构建 '结构',具体的面积/分数计算交给 Project 1 的重计算接口。
- 我们需要保留 original_json 中的一些元数据 (如 imageHeight, etc.)
- """
- # 基础结构复制
- new_internal = {
- "result": {
- "imageHeight": labelme_json.get("imageHeight", original_json["result"].get("imageHeight")),
- "imageWidth": labelme_json.get("imageWidth", original_json["result"].get("imageWidth")),
- "center_result": {},
- "defect_result": {"defects": []}
- }
- }
- # 准备容器
- defects_list = []
- inner_box_data = None
- outer_box_data = None
- # 遍历 LabelMe 的 shapes
- for shape in labelme_json.get("shapes", []):
- label = shape.get("label")
- points = shape.get("points", [])
- if not points:
- continue
- if label == "outer_box":
- # 重构 outer_box 结构
- outer_box_data = {
- "shapes": [{"label": "outer_box", "points": points, "shape_type": "polygon"}]
- }
- elif label == "inner_box":
- # 重构 inner_box 结构
- inner_box_data = {
- "shapes": [{"label": "inner_box", "points": points, "shape_type": "polygon"}]
- }
- else:
- # 这是一个缺陷
- # 尝试从 shape 中读取我们之前暂存的 system_data,如果没有则初始化默认值
- sys_data = shape.get("system_data", {})
- defect_obj = {
- "label": label,
- "points": points,
- "shape_type": "polygon",
- # 如果是新加的缺陷,这些可能是 None,重计算服务应该处理它
- "confidence": sys_data.get("confidence", 1.0),
- "defect_type": sys_data.get("defect_type", "face"), # 默认为 face, 服务端会重新校验
- "edit_type": "edit", # 标记为编辑过
- # score 字段由服务端计算,这里可以不传或者传旧的
- "score": sys_data.get("score")
- }
- defects_list.append(defect_obj)
- # 组装 Center Result
- # 只有当原始数据里有 box_result 或者 labelme 里画了 box 时才构造
- # 保持原有的层级结构: center_result -> box_result -> inner_box/outer_box
- if inner_box_data or outer_box_data:
- new_internal["result"]["center_result"] = {
- "box_result": {}
- }
- if inner_box_data:
- new_internal["result"]["center_result"]["box_result"]["inner_box"] = inner_box_data
- if outer_box_data:
- new_internal["result"]["center_result"]["box_result"]["outer_box"] = outer_box_data
- else:
- # 如果没有框的信息(例如面部图),保持 center_result 为空或复制原始的非 box 信息
- new_internal["result"]["center_result"] = {}
- # 组装 Defect Result
- new_internal["result"]["defect_result"]["defects"] = defects_list
- # 复制 statistics 等其他可能的字段,或者留给服务端重新生成
- # 建议只传核心数据,让服务端全权处理统计
- return new_internal
|