149 lines
4.6 KiB
Python
149 lines
4.6 KiB
Python
|
|
"""CVAT 标注配置:为 DMS / ADAS / Lane 生成 label schema(唯一标注引擎)。"""
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
from typing import Any
|
|||
|
|
|
|||
|
|
from as_platform.config import WORKSPACE
|
|||
|
|
from as_platform.labeling.scope import labeling_profile_key, load_dms_registry, load_labeling_registry
|
|||
|
|
|
|||
|
|
# Lane 车道线 — 折线
|
|||
|
|
LANE_LABELS: list[dict[str, Any]] = [
|
|||
|
|
{
|
|||
|
|
"name": "lane_line",
|
|||
|
|
"type": "polyline",
|
|||
|
|
"attributes": [
|
|||
|
|
{
|
|||
|
|
"name": "type",
|
|||
|
|
"mutable": False,
|
|||
|
|
"input_type": "select",
|
|||
|
|
"values": ["solid", "dashed", "double_solid", "double_dashed", "solid_dashed"],
|
|||
|
|
"default_value": "solid",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "color",
|
|||
|
|
"mutable": False,
|
|||
|
|
"input_type": "select",
|
|||
|
|
"values": ["white", "yellow", "blue", "other"],
|
|||
|
|
"default_value": "white",
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "curb",
|
|||
|
|
"type": "polyline",
|
|||
|
|
"attributes": [
|
|||
|
|
{
|
|||
|
|
"name": "type",
|
|||
|
|
"mutable": False,
|
|||
|
|
"input_type": "select",
|
|||
|
|
"values": ["high", "low", "none"],
|
|||
|
|
"default_value": "low",
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
{"name": "stop_line", "type": "polyline"},
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# ADAS cuboid_7cls — 单目图像 cuboid
|
|||
|
|
ADAS_CUBOID_7CLS_LABELS: list[dict[str, Any]] = [
|
|||
|
|
{"name": "car", "type": "cuboid"},
|
|||
|
|
{"name": "pedestrian", "type": "cuboid"},
|
|||
|
|
{"name": "truck", "type": "cuboid"},
|
|||
|
|
{"name": "bus", "type": "cuboid"},
|
|||
|
|
{"name": "motorcycle", "type": "cuboid"},
|
|||
|
|
{"name": "tricycle", "type": "cuboid"},
|
|||
|
|
{"name": "traffic cone", "type": "cuboid"},
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _rect_label(name: str, **attrs: Any) -> dict[str, Any]:
|
|||
|
|
lb: dict[str, Any] = {"name": name, "type": "rectangle"}
|
|||
|
|
if attrs:
|
|||
|
|
lb["attributes"] = attrs
|
|||
|
|
return lb
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _dms_registry_task_config(task: str, mode: str | None) -> dict[str, Any]:
|
|||
|
|
import sys
|
|||
|
|
|
|||
|
|
scripts = WORKSPACE / "datasets" / "dms" / "scripts"
|
|||
|
|
if str(scripts) not in sys.path:
|
|||
|
|
sys.path.insert(0, str(scripts))
|
|||
|
|
from task_registry import get_mode_config, resolve_task_id
|
|||
|
|
|
|||
|
|
reg = load_dms_registry()
|
|||
|
|
task_r, mode_r = resolve_task_id(task, mode)
|
|||
|
|
return get_mode_config(task_r, mode_r, reg)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _labels_from_class_names(names: list[str] | dict[int | str, str]) -> list[dict[str, Any]]:
|
|||
|
|
if isinstance(names, dict):
|
|||
|
|
ordered = [names[k] for k in sorted(names, key=lambda x: int(x))]
|
|||
|
|
else:
|
|||
|
|
ordered = list(names)
|
|||
|
|
return [_rect_label(str(n)) for n in ordered]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _dms_pose_labels() -> list[dict[str, Any]]:
|
|||
|
|
labels: list[dict[str, Any]] = [_rect_label("face")]
|
|||
|
|
labels.extend({"name": f"kp_{i:02d}", "type": "points"} for i in range(37))
|
|||
|
|
return labels
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _dms_labels(task: str, mode: str | None) -> list[dict[str, Any]]:
|
|||
|
|
tcfg = _dms_registry_task_config(task, mode)
|
|||
|
|
ttype = tcfg.get("type") or "detect"
|
|||
|
|
if ttype == "pose":
|
|||
|
|
return _dms_pose_labels()
|
|||
|
|
names = tcfg.get("names")
|
|||
|
|
if names:
|
|||
|
|
return _labels_from_class_names(names)
|
|||
|
|
return [_rect_label("object")]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def _labels_from_registry_profile(project: str, task: str, mode: str | None) -> list[dict[str, Any]] | None:
|
|||
|
|
reg = load_dms_registry() if project == "dms" else None
|
|||
|
|
pk = labeling_profile_key(project, task, mode, reg)
|
|||
|
|
prof = (load_labeling_registry().get("profiles") or {}).get(pk) or {}
|
|||
|
|
cvat_names = prof.get("cvat_labels")
|
|||
|
|
if cvat_names:
|
|||
|
|
return [{"name": str(n), "type": "cuboid"} for n in cvat_names]
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
|
|||
|
|
def build_cvat_labels(
|
|||
|
|
project: str,
|
|||
|
|
task: str | None = None,
|
|||
|
|
mode: str | None = None,
|
|||
|
|
annotation_types: list[str] | None = None,
|
|||
|
|
) -> list[dict[str, Any]]:
|
|||
|
|
"""根据 HSAP project/task/mode 生成 CVAT Task 的 labels 定义。"""
|
|||
|
|
task = task or ""
|
|||
|
|
prof_labels = _labels_from_registry_profile(project, task, mode)
|
|||
|
|
if prof_labels is not None:
|
|||
|
|
return prof_labels
|
|||
|
|
|
|||
|
|
if project == "adas":
|
|||
|
|
if task == "cuboid_7cls":
|
|||
|
|
return ADAS_CUBOID_7CLS_LABELS
|
|||
|
|
return ADAS_CUBOID_7CLS_LABELS
|
|||
|
|
|
|||
|
|
if project == "lane":
|
|||
|
|
return LANE_LABELS
|
|||
|
|
|
|||
|
|
if project == "dms":
|
|||
|
|
return _dms_labels(task, mode)
|
|||
|
|
|
|||
|
|
return [_rect_label("object")]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def resolve_annotation_types(project: str, task: str | None = None, mode: str | None = None) -> list[str]:
|
|||
|
|
mapping = {
|
|||
|
|
"dms": ["bbox", "keypoint"],
|
|||
|
|
"adas": ["cuboid"],
|
|||
|
|
"lane": ["polyline"],
|
|||
|
|
}
|
|||
|
|
if project == "adas" and task == "cuboid_7cls":
|
|||
|
|
return ["cuboid"]
|
|||
|
|
return mapping.get(project, ["bbox"])
|