news 2026/4/16 21:32:44

BDD100K数据集标签转换实战:从JSON到YOLO格式的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
BDD100K数据集标签转换实战:从JSON到YOLO格式的完整指南

1. BDD100K数据集与YOLO格式简介

当你第一次接触BDD100K数据集时,可能会被它的JSON标签格式搞得一头雾水。这个由伯克利大学发布的自动驾驶数据集包含10万个视频片段,覆盖了各种天气、光照和道路场景,是训练目标检测模型的绝佳资源。但问题来了——YOLOv5/YOLOv8需要的是TXT格式的标签,每个文件对应一张图片,记录着归一化的目标位置和类别。

我刚开始用这个数据集时,花了一整天研究如何转换格式。后来发现,其实核心就是三步:解析JSON里的box2d坐标、按需筛选类别、将绝对坐标转为相对坐标。举个例子,JSON中一个"car"的坐标可能是{"x1": 320, "y1": 240, "x2": 480, "y2": 360},而YOLO需要的则是"0 0.5 0.5 0.25 0.25"这样的格式(假设类别car对应数字0)。

2. 环境准备与数据目录结构

在开始转换前,建议按这个结构组织你的文件夹:

bdd100k/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── det_annotations/ # 原始JSON标签 │ ├── train/ │ └── val/ └── yolo_labels/ # 转换后的TXT标签 ├── train/ └── val/

需要安装的Python包其实很简单:

pip install json numpy tqdm

我建议用tqdm加个进度条,特别是处理几万张图片时,看着进度条慢慢走完会有种莫名的治愈感。曾经有一次我没用进度条,程序跑了半小时我都不知道是否卡死了,最后忍不住强制终止,结果发现已经处理完了...

3. JSON标签解析实战

BDD100K的JSON结构比COCO复杂些,关键是要找到"frames"下的"objects"数组。每个对象包含:

  • category:类别名称(如"car")
  • box2d:包含x1,y1,x2,y2的边界框
  • attributes:可能有交通灯颜色等额外属性

这里有个坑:不同版本的BDD100K标签结构略有差异。有次我拿到的版本里,"frames"变成了"labels",害我debug了好久。建议先用这个代码检查结构:

import json with open("sample.json") as f: data = json.load(f) print(json.dumps(data, indent=2)[:500]) # 打印前500字符

4. 类别筛选与映射策略

BDD100K有13个基础类别,但你可能只需要其中几个。我整理了这个对照表:

BDD原始类别保留标记YOLO类别ID
car0
pedestrian-
traffic light1
.........

实现时建议用字典管理类别映射:

CLASS_MAP = { "car": 0, "traffic light": 1, "traffic sign": 2 }

处理交通灯时要特别注意,颜色信息藏在attributes里:

if obj["category"] == "traffic light": color = obj["attributes"]["trafficLightColor"] class_name = f"tl_{color}" # 如tl_red

5. 坐标归一化关键细节

这是最容易出错的部分!YOLO要求的是中心点坐标和宽高,且必须是相对于图像尺寸的比例值。计算公式如下:

def normalize_bbox(x1, y1, x2, y2, img_w=1280, img_h=720): x_center = (x1 + x2) / 2 / img_w y_center = (y1 + y2) / 2 / img_h width = (x2 - x1) / img_w height = (y2 - y1) / img_h return x_center, y_center, width, height

注意BDD100K默认分辨率是1280x720,但有些图片可能不同。安全起见,可以检查JSON中的"resolution"字段。我曾经因为忽略这个,导致小目标检测完全失效——所有框都偏移了20%!

6. 完整代码实现与优化

结合上述要点,这是优化后的转换代码:

import json import os from tqdm import tqdm class BDD2YOLO: def __init__(self): self.class_map = { "car": 0, "traffic light": 1, "traffic sign": 2, "person": 3 } def convert(self, json_path, output_dir): os.makedirs(output_dir, exist_ok=True) with open(json_path) as f: data = json.load(f) filename = data["name"] lines = [] for frame in data["frames"]: for obj in frame["objects"]: category = obj["category"] if category not in self.class_map: continue # 处理交通灯颜色 if category == "traffic light": color = obj["attributes"].get("trafficLightColor", "none") category = f"tl_{color}" # 坐标归一化 box = obj["box2d"] xc, yc, w, h = self.normalize_bbox( box["x1"], box["y1"], box["x2"], box["y2"] ) lines.append( f"{self.class_map[category]} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}\n" ) # 保存结果 if lines: with open(f"{output_dir}/{filename}.txt", "w") as f: f.writelines(lines) @staticmethod def normalize_bbox(x1, y1, x2, y2, img_w=1280, img_h=720): xc = (x1 + x2) / 2 / img_w yc = (y1 + y2) / 2 / img_h w = (x2 - x1) / img_w h = (y2 - y1) / img_h return xc, yc, w, h # 批量处理 converter = BDD2YOLO() json_dir = "bdd100k/labels/det_annotations/train" output_dir = "bdd100k/labels/yolo_labels/train" for filename in tqdm(os.listdir(json_dir)): converter.convert( f"{json_dir}/{filename}", output_dir )

这个版本比原始代码增加了错误处理、进度显示和更清晰的代码结构。用类封装也让后续维护更方便。

7. 验证与调试技巧

转换完成后,强烈建议做这些检查:

  1. 空文件检查:有些图片可能没有目标,确保对应的TXT文件为空或不存在
  2. 坐标范围验证:所有坐标值应在[0,1]范围内
  3. 可视化验证:用OpenCV画框检查是否对齐

这里有个可视化脚本片段:

import cv2 def visualize(img_path, label_path, class_names): img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path) as f: for line in f: cls_id, xc, yc, bw, bh = map(float, line.split()) x1 = int((xc - bw/2) * w) y1 = int((yc - bh/2) * h) x2 = int((xc + bw/2) * w) y2 = int((yc + bh/2) * h) cv2.rectangle(img, (x1,y1), (x2,y2), (0,255,0), 2) cv2.putText(img, class_names[int(cls_id)], (x1,y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1) cv2.imshow("Preview", img) cv2.waitKey(0)

8. 性能优化与批量处理

当处理10万级数据时,我有几个提速心得:

  1. 多进程处理:Python的multiprocessing模块能大幅提升速度
from multiprocessing import Pool def process_file(filename): converter.convert(f"{json_dir}/{filename}", output_dir) with Pool(8) as p: # 8个进程 list(tqdm(p.imap(process_file, os.listdir(json_dir)), total=len(os.listdir(json_dir))))
  1. 缓存机制:如果中断后重新开始,可以跳过已处理的文件
  2. SSD存储:机械硬盘处理小文件速度会慢很多

最后提醒:转换完成后,记得在YOLO的配置文件中正确设置类别数和类别名称。比如在data.yaml中:

names: ["car", "traffic light", "traffic sign", "person"]
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 16:01:03

Z-Image-Turbo_UI界面步数调多少合适?经验分享

Z-Image-Turbo_UI界面步数调多少合适?经验分享 你刚打开 Z-Image-Turbo 的 UI 界面,输入提示词、选好模型,正准备点“生成”——却在“Sampling Steps”(采样步数)这一栏停住了:该填 8?12&…

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

老Mac如何重获新生?开源工具让旧设备升级最新系统

老Mac如何重获新生?开源工具让旧设备升级最新系统 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 旧Mac升级、macOS兼容性工具、老设备系统优化——这些关键词…

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

突破反爬限制:高效数据采集工具的动态加密破解解决方案

突破反爬限制:高效数据采集工具的动态加密破解解决方案 【免费下载链接】dianping_spider 大众点评爬虫(全站可爬,解决动态字体加密,非OCR)。持续更新 项目地址: https://gitcode.com/gh_mirrors/di/dianping_spider…

作者头像 李华
网站建设 2026/4/15 23:36:44

Nano-Banana开源模型部署:支持FP16/INT4量化,显存占用<12GB

Nano-Banana开源模型部署&#xff1a;支持FP16/INT4量化&#xff0c;显存占用<12GB 1. 这不是普通文生图&#xff0c;是专为“拆开看”而生的AI引擎 你有没有遇到过这样的场景&#xff1a; 工程师要快速生成某款智能手表的爆炸图&#xff0c;用于内部培训&#xff1b;电商…

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

阿里通义千问Qwen3-4B:多语言翻译一键搞定

阿里通义千问Qwen3-4B&#xff1a;多语言翻译一键搞定 1. 开门见山&#xff1a;你还在为翻译卡壳吗&#xff1f; 你有没有过这样的经历&#xff1a; 收到一封密密麻麻的英文技术文档&#xff0c;想快速抓住重点&#xff0c;却卡在专业术语上&#xff1b;要把中文产品介绍发给…

作者头像 李华
网站建设 2026/4/16 15:36:32

3步解锁科研绘图自动化:LaTeX代码生成工具DeTikZify全攻略

3步解锁科研绘图自动化&#xff1a;LaTeX代码生成工具DeTikZify全攻略 【免费下载链接】DeTikZify Synthesizing Graphics Programs for Scientific Figures and Sketches with TikZ 项目地址: https://gitcode.com/gh_mirrors/de/DeTikZify 为什么科研工作者常常在图表…

作者头像 李华