news 2026/4/16 15:21:48

DAMO-YOLO实操手册:导出检测结果为COCO格式并用于下游训练流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DAMO-YOLO实操手册:导出检测结果为COCO格式并用于下游训练流程

DAMO-YOLO实操手册:导出检测结果为COCO格式并用于下游训练流程

1. 为什么需要把DAMO-YOLO的检测结果转成COCO格式

你刚跑通DAMO-YOLO,看着界面上跳动的霓虹绿框,心里挺美——人、车、猫、椅子全被框得明明白白。但很快问题来了:你想拿这些检测结果去微调另一个模型,比如训练一个更专精的工业缺陷检测器;或者想把标注数据喂给Label Studio做人工校验;又或者要接入MMDetection做模型对比实验……这时候你会发现,DAMO-YOLO默认输出的JSON结构,和主流训练框架认的COCO格式压根对不上。

不是它不好,是它“太完整”了——带UI状态、带渲染参数、带时间戳、还带赛博朋克配色配置。而COCO只要干净的三样东西:图片信息、类别定义、检测框坐标(归一化或绝对像素)加置信度。这篇手册不讲原理、不画架构图,就干一件事:用最少的代码,把DAMO-YOLO跑出来的原始结果,变成下游训练工具能直接读、能直接训、不报错的COCO JSON文件

整个过程不需要重装环境,不改源码,不碰前端,只在后端Python层加一个轻量转换脚本。实测从拿到原始输出到生成标准COCO文件,5分钟内搞定。

2. 理解DAMO-YOLO的原始输出结构

在动手前,先看清它到底吐出了什么。当你上传一张test.jpg,DAMO-YOLO后端(Flask路由)返回的JSON长这样:

{ "status": "success", "timestamp": "2026-01-26T13:48:22.105Z", "image_info": { "filename": "test.jpg", "width": 1920, "height": 1080, "format": "JPEG" }, "detections": [ { "category": "person", "bbox": [124.5, 89.2, 312.8, 456.7], "score": 0.923, "id": 1 }, { "category": "car", "bbox": [782.1, 210.4, 1120.6, 598.3], "score": 0.871, "id": 2 } ], "ui_config": { "threshold": 0.5, "color": "#00ff7f", "render_mode": "neon" } }

注意几个关键点:

  • bbox[x_min, y_min, x_max, y_max]格式,单位是像素,不是归一化值;
  • category是字符串,但COCO要求所有类别必须映射到整数ID(person=1, car=2…);
  • detections里没有图片ID字段,而COCO的annotations数组必须关联到images里的id
  • image_info里有宽高,但COCO的images数组需要file_namewidthheightid四个字段;
  • 没有全局的categories定义——这是COCO最核心的元信息,必须手动补全。

所以转换不是简单复制粘贴,而是做三件事:
① 构建标准imagescategories列表;
② 把每个detection转成COCO的annotation格式(加image_idcategory_idareaiscrowd等);
③ 保证所有ID连续、无重复、可追溯。

3. 实现COCO导出:三步走,代码全贴

我们不新建项目,直接复用DAMO-YOLO已有的Python环境。所有代码都放在/root/ai-models/iic/cv_tinynas_object-detection_damoyolo/目录下,新建一个coco_exporter.py文件。

3.1 第一步:定义COCO类别映射表

COCO官方80类顺序是固定的。DAMO-YOLO支持全部80类,但它的category字符串和COCO官方命名完全一致(比如都是personbicyclecar),所以我们可以直接按字母序生成ID。但为保险起见,还是显式定义——这样以后增删类别也方便。

# coco_exporter.py COCO_CATEGORIES = [ {"id": 1, "name": "person", "supercategory": "person"}, {"id": 2, "name": "bicycle", "supercategory": "vehicle"}, {"id": 3, "name": "car", "supercategory": "vehicle"}, {"id": 4, "name": "motorcycle", "supercategory": "vehicle"}, {"id": 5, "name": "airplane", "supercategory": "vehicle"}, {"id": 6, "name": "bus", "supercategory": "vehicle"}, {"id": 7, "name": "train", "supercategory": "vehicle"}, {"id": 8, "name": "truck", "supercategory": "vehicle"}, {"id": 9, "name": "boat", "supercategory": "vehicle"}, {"id": 10, "name": "traffic light", "supercategory": "outdoor"}, # ... 中间省略50行,保持到80类 {"id": 80, "name": "hair drier", "supercategory": "accessory"} ] # 建立 name → id 的快速查找字典 NAME_TO_ID = {cat["name"]: cat["id"] for cat in COCO_CATEGORIES}

小技巧:如果你只用其中10个类别(比如只检人、车、狗、包),就把COCO_CATEGORIES列表剪裁成这10个,并重新编号为1~10。下游训练时显存和速度都会明显提升。

3.2 第二步:写核心转换函数

这个函数接收DAMO-YOLO原始JSON路径,输出标准COCO JSON路径。逻辑清晰,每行都有注释:

import json import os from pathlib import Path def damoyolo_to_coco(damoyolo_json_path: str, output_coco_path: str): """ 将DAMO-YOLO单次推理的JSON输出,转换为标准COCO格式 Args: damoyolo_json_path: DAMO-YOLO返回的原始JSON文件路径 output_coco_path: 输出的COCO JSON文件路径 """ # 1. 读原始JSON with open(damoyolo_json_path, "r", encoding="utf-8") as f: raw = json.load(f) # 2. 初始化COCO结构 coco = { "info": { "description": "DAMO-YOLO COCO Export", "version": "1.0", "year": 2026, "contributor": "Wuli-Art Visual Lab", "date_created": raw.get("timestamp", "2026-01-01T00:00:00Z") }, "licenses": [{"id": 1, "name": "MIT", "url": "https://opensource.org/licenses/MIT"}], "images": [], "annotations": [], "categories": COCO_CATEGORIES # 直接复用上面定义的 } # 3. 处理单张图片信息 → images数组 img_info = raw["image_info"] image_id = 1 # 单图场景,固定为1;多图批量处理时用循环+自增 coco_image = { "id": image_id, "file_name": img_info["filename"], "width": img_info["width"], "height": img_info["height"], "date_captured": raw.get("timestamp", ""), "license": 1 } coco["images"].append(coco_image) # 4. 处理所有检测框 → annotations数组 annotation_id = 1 for det in raw["detections"]: # bbox转COCO格式:[x,y,width,height] x1, y1, x2, y2 = det["bbox"] width = round(x2 - x1, 1) height = round(y2 - y1, 1) x = round(x1, 1) y = round(y1, 1) # 计算area(必须是正数) area = max(1.0, width * height) # category映射 category_id = NAME_TO_ID.get(det["category"], 0) if category_id == 0: print(f" 警告:未知类别 '{det['category']}',已跳过") continue annotation = { "id": annotation_id, "image_id": image_id, "category_id": category_id, "bbox": [x, y, width, height], "area": area, "segmentation": [], # DAMO-YOLO不输出mask,留空 "iscrowd": 0 } # 可选:添加score作为annotation的额外字段(非COCO标准,但部分训练框架支持) if "score" in det: annotation["score"] = round(det["score"], 3) coco["annotations"].append(annotation) annotation_id += 1 # 5. 写入文件 with open(output_coco_path, "w", encoding="utf-8") as f: json.dump(coco, f, indent=2, ensure_ascii=False) print(f" 已生成COCO格式文件:{output_coco_path}") print(f" 图片数:{len(coco['images'])},标注数:{len(coco['annotations'])}") # 示例调用(测试用) if __name__ == "__main__": damoyolo_to_coco( damoyolo_json_path="/root/ai-models/iic/cv_tinynas_object-detection_damoyolo/output/test_result.json", output_coco_path="/root/ai-models/iic/cv_tinynas_object-detection_damoyolo/output/test_coco.json" )

3.3 第三步:批量处理与自动化集成

实际工作中,你不会只导一张图。DAMO-YOLO通常会把一批图片的检测结果存在/output/目录下,文件名如img_001.jsonimg_002.json……这时只需加个循环:

def batch_export(input_dir: str, output_dir: str): """批量转换整个目录下的DAMO-YOLO JSON""" input_path = Path(input_dir) output_path = Path(output_dir) output_path.mkdir(exist_ok=True) json_files = list(input_path.glob("*.json")) print(f" 找到 {len(json_files)} 个JSON文件") for i, json_file in enumerate(json_files, 1): # 生成对应COCO文件名:img_001.json → img_001_coco.json coco_name = json_file.stem + "_coco.json" coco_path = output_path / coco_name try: damoyolo_to_coco(str(json_file), str(coco_path)) except Exception as e: print(f" 处理 {json_file.name} 失败:{e}") print(f" 批量导出完成!COCO文件已保存至:{output_dir}") # 在__main__里调用 if __name__ == "__main__": batch_export( input_dir="/root/ai-models/iic/cv_tinynas_object-detection_damoyolo/output/", output_dir="/root/ai-models/iic/cv_tinynas_object-detection_damoyolo/coco_annotations/" )

运行后,你会得到一个标准COCO JSON文件,开头长这样:

{ "info": { "description": "DAMO-YOLO COCO Export", "version": "1.0", "year": 2026, "contributor": "Wuli-Art Visual Lab", "date_created": "2026-01-26T13:48:22.105Z" }, "licenses": [...], "images": [ { "id": 1, "file_name": "test.jpg", "width": 1920, "height": 1080, "date_captured": "2026-01-26T13:48:22.105Z", "license": 1 } ], "annotations": [ { "id": 1, "image_id": 1, "category_id": 1, "bbox": [124.5, 89.2, 188.3, 367.5], "area": 69172.5, "segmentation": [], "iscrowd": 0 } ], "categories": [...] }

完全符合pycocotools、MMDetection、Detectron2等所有主流框架的输入要求。

4. 下游训练实测:用导出的COCO数据微调YOLOv8

光有COCO文件还不够,得验证它真能训。我们用最轻量的方式——用Ultralytics的YOLOv8,在RTX 4090上微调3个epoch,看是否报错、是否收敛。

4.1 准备训练目录结构

COCO标准要求数据集按以下结构组织:

coco_dataset/ ├── annotations/ │ └── instances_train2017.json ← 你的导出文件放这里 ├── train2017/ │ └── test.jpg ← 原始图片必须同名放这里 └── ...

所以你需要:

  • test.jpg复制到coco_dataset/train2017/
  • test_coco.json重命名为instances_train2017.json,放进coco_dataset/annotations/

4.2 一行命令启动训练

确保已安装Ultralytics(pip install ultralytics),然后执行:

yolo detect train \ data=coco_dataset \ model=yolov8n.pt \ epochs=3 \ imgsz=640 \ batch=16 \ name=damoyolo_finetune

训练日志里如果出现:

Class names: ['person', 'bicycle', 'car', ...] Found 1 images in train2017 Loaded 1 labels from coco_dataset/annotations/instances_train2017.json

说明COCO文件被正确加载。3个epoch后,你就能得到一个基于DAMO-YOLO检测结果微调的新模型,专门适配你的场景。

实测提示:如果训练卡在Loading annotations...,90%是JSON里file_name和图片实际文件名不一致(比如大小写、空格、扩展名.JPGvs.jpg),用ls -l核对即可。

5. 常见问题与避坑指南

5.1 “KeyError: 'category'” 错误

原因:DAMO-YOLO某些版本在无检测目标时,detections数组为空,但代码仍尝试遍历。修复很简单:

# 在damoyolo_to_coco函数里,处理detections前加判断 if "detections" not in raw or not raw["detections"]: print(f" {damoyolo_json_path} 中无检测结果,跳过") # 仍生成空COCO结构(images有,annotations为空),保证格式合法 coco["annotations"] = [] return

5.2 导出的bbox坐标错位

现象:COCO文件里框的位置和DAMO-YOLO界面上显示的不一致。
原因:DAMO-YOLO前端做了图像缩放(比如把1920x1080图缩放到800px宽显示),但后端返回的bbox原始尺寸坐标。而你的图片如果被预处理过(比如resize、pad),就必须在导出前做逆变换。
解决:确认你传给DAMO-YOLO的图片就是原始尺寸。如果必须缩放,记录缩放比例,在导出时反向计算:

# 假设你上传前把图resize到了640x360,原始是1920x1080 scale_x = 1920 / 640 scale_y = 1080 / 360 x1, y1, x2, y2 = [v * scale_x if i % 2 == 0 else v * scale_y for i, v in enumerate(det["bbox"])]

5.3 类别ID对不上下游框架

现象:训练时报错category_id 81 is out of range
原因:你的COCO JSON里categories写了80类,但下游框架(比如MMDetection)默认只加载前20类。
解决:两种方式任选其一
推荐:在导出脚本里,只保留你实际用到的类别(比如只检人、车、狗),COCO_CATEGORIES只写这3个,ID为1/2/3;
② 修改下游配置:在MMDetection的config里加num_classes = 80,并确保classes列表和你的categories顺序严格一致。

5.4 如何把COCO结果再可视化回DAMO-YOLO风格

你导出了COCO,训好了新模型,现在想看看效果?不用重写UI。直接用OpenCV读COCO JSON,画霓虹绿框:

import cv2 import json def draw_coco_on_image(coco_json: str, image_path: str, output_path: str): with open(coco_json) as f: coco = json.load(f) img = cv2.imread(image_path) # 遍历annotations画框 for ann in coco["annotations"]: x, y, w, h = map(int, ann["bbox"]) cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 127), 2) # Neon Green: BGR(0,255,127) cv2.imwrite(output_path, img) print(f" 可视化结果已保存:{output_path}") draw_coco_on_image( coco_json="/root/.../test_coco.json", image_path="/root/.../test.jpg", output_path="/root/.../test_visualized.jpg" )

6. 总结:一条从检测到训练的闭环链路

这篇手册没讲TinyNAS怎么搜索、没讲BFloat16怎么加速、也没讲赛博朋克UI的CSS动画怎么实现。它只聚焦一个工程师每天都会遇到的真实断点:检测结果如何变成训练数据

你现在拥有了:

  • 一份开箱即用的coco_exporter.py,5分钟接入现有DAMO-YOLO部署;
  • 清晰的三步转换逻辑(映射→构建→写入),可读、可调、可debug;
  • 批量处理能力,支撑小规模数据集构建;
  • 下游训练实测路径,证明导出结果100%可用;
  • 四个高频问题的解决方案,覆盖90%的落地报错。

真正的AI工程,不在于模型多炫酷,而在于让数据在不同环节之间零损耗、零歧义、零摩擦地流动。DAMO-YOLO的霓虹绿框,今天是你眼中的结果;明天,它就是另一个模型进步的起点。

--- > **获取更多AI镜像** > > 想探索更多AI镜像和应用场景?访问 [CSDN星图镜像广场](https://ai.csdn.net/?utm_source=mirror_blog_end),提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 13:05:20

3大革新!Blender3mfFormat插件如何彻底改变3D打印工作流

3大革新!Blender3mfFormat插件如何彻底改变3D打印工作流 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat Blender3mfFormat是一款专为Blender设计的开源插件&a…

作者头像 李华
网站建设 2026/4/16 14:03:06

CAPL定时器数组高效管理:多CAN报文同步发送与负载测试实战

1. CAPL定时器数组基础概念 在CANoe开发中,定时器是实现周期性操作的核心工具。CAPL提供了两种定时器类型:基于秒的timer和基于毫秒的msTimer。对于需要精确控制时序的场景,msTimer显然是更好的选择。我曾在多个车载ECU测试项目中&#xff0…

作者头像 李华
网站建设 2026/4/16 12:58:06

深蓝词库转换:一站式输入法词库跨平台迁移工具

深蓝词库转换:一站式输入法词库跨平台迁移工具 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 当你从Windows切换到macOS时,多年积累的个人词…

作者头像 李华
网站建设 2026/4/16 13:02:08

7步解锁原神高帧率:从卡顿到丝滑的实战指南

7步解锁原神高帧率:从卡顿到丝滑的实战指南 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock 一、为什么需要帧率解锁? 你是否曾遇到这样的情况:花重金…

作者头像 李华
网站建设 2026/4/16 14:06:17

HsMod炉石插件全方位实战指南:从配置到精通的完整路径

HsMod炉石插件全方位实战指南:从配置到精通的完整路径 【免费下载链接】HsMod Hearthstone Modify Based on BepInEx 项目地址: https://gitcode.com/GitHub_Trending/hs/HsMod 一、系统环境配置与基础部署 ⚙️ 开发环境准备 目标:完成HsMod插…

作者头像 李华
网站建设 2026/4/15 20:54:30

Qwen3-ASR-0.6B环境配置:Ubuntu 22.04 + PyTorch 2.3 + Transformers 4.45适配指南

Qwen3-ASR-0.6B环境配置:Ubuntu 22.04 PyTorch 2.3 Transformers 4.45适配指南 语音识别不再是高不可攀的技术门槛。如果你正打算在本地部署一个轻量但能力扎实的ASR模型,Qwen3-ASR-0.6B很可能就是你要找的那个“刚刚好”的选择——它不占太多显存&…

作者头像 李华