第五章:计算机视觉(Computer Vision)- 项目实战之目标检测实战
第二部分:目标检测实战:中国交通标志检测
第二节:中国交通标志检测数据格式转化与读取
在目标检测实战中,数据集的格式和读取方式直接决定了后续模型能否顺利训练。由于深度学习框架(如 PyTorch、TensorFlow)以及检测算法(如 YOLO、Faster R-CNN)通常要求统一的数据格式,因此需要对原始交通标志数据进行 格式转化。本节我们将详细介绍中国交通标志检测数据集的格式说明、转化流程以及数据读取方法。
1. 数据集来源与特点
常用的交通标志检测数据集包括:
-
TT100K (Tsinghua-Tencent 100K)
-
由清华大学与腾讯联合发布,包含超过 10 万张中国交通场景图片。
-
支持 200+ 类交通标志类别,覆盖常见的限速、禁止、警告、指示标志。
-
原始标注为 JSON 文件,包含边界框坐标与类别标签。
-
-
自建数据集(例如拍摄或采集的交通标志图片):
- 格式可能为 VOC (XML)、COCO (JSON) 或纯文本文件,需要根据算法需求统一。
2. 常见目标检测标注格式
在转化之前,我们需要了解常见的几种标注格式:
-
Pascal VOC 格式 (XML)
-
每张图像对应一个 XML 文件。
-
边界框坐标为
(xmin, ymin, xmax, ymax)
。
-
-
COCO 格式 (JSON)
-
所有标注集中在一个 JSON 文件中。
-
边界框坐标为
(x, y, width, height)
。
-
-
YOLO 格式 (TXT)
-
每张图像对应一个 TXT 文件。
-
每行标注格式为:
class_id x_center y_center width height
(所有数值均归一化到
[0, 1]
)
-
3. 数据格式转化流程
在中国交通标志检测实战中,我们选用 YOLOv8 ,因此需要将数据集转化为 YOLO 格式。
3.1 转化步骤
-
下载原始数据集
- 获取 TT100K 或其他交通标志数据集,解压缩。
-
解析原始标注
- TT100K 的标注文件为 JSON,需要编写脚本读取。
-
统一类别文件
-
创建
classes.txt
,存放所有交通标志类别,如:pythonspeedlimit stop noentry warning ...
-
-
转化为 YOLO TXT 格式
-
读取每张图像的边界框坐标,将其归一化:
pythonx_center = (xmin + xmax) / 2 / image_width y_center = (ymin + ymax) / 2 / image_height w = (xmax - xmin) / image_width h = (ymax - ymin) / image_height
-
按照 YOLO 格式写入 TXT 文件。
-
-
目录结构整理
-
YOLO 要求的数据集目录如下:
pythondatasets/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml
-
-
编写 data.yaml
-
data.yaml
文件用于指定数据路径和类别信息,例如:pythontrain: ./datasets/images/train val: ./datasets/images/val test: ./datasets/images/test nc: 10 # 类别数量 names: ['speedlimit', 'stop', 'noentry', 'warning', ...]
-
4. 数据读取与可视化
转化完成后,我们需要验证数据是否正确。
4.1 使用 Python 读取标签
python
import cv2
import os
img_path = "datasets/images/train/example.jpg"
label_path = "datasets/labels/train/example.txt"
# 读取图片
img = cv2.imread(img_path)
h, w, _ = img.shape
# 读取标签
with open(label_path, "r") as f:
labels = f.readlines()
for label in labels:
cls, x, y, bw, bh = map(float, label.strip().split())
# 反归一化
x1 = int((x - bw/2) * w)
y1 = int((y - bh/2) * h)
x2 = int((x + bw/2) * w)
y2 = int((y + bh/2) * h)
# 绘制边界框
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
4.2 可视化检查
运行后应能在图片上看到交通标志的检测框,确保:
-
边界框位置正确。
-
类别和
classes.txt
对应无误。 -
数据集划分合理(训练集、验证集、测试集)。
4.3 完整代码
python
import json
import os
import cv2
from tqdm import tqdm
# 配置路径
json_file = "annotations.json" # TT100K 原始 JSON 标注文件路径
img_dir = "images/" # 原始图像文件夹
save_dir = "datasets/" # 转换后保存的目标文件夹
# 读取 JSON 文件
with open(json_file, "r", encoding="utf-8") as f:
data = json.load(f)
# 类别映射表(TT100K 有 200+ 类,这里示例)
# 实际使用时可根据需要过滤或重命名类别
classes = list(data["types"].keys())
cls2id = {cls: i for i, cls in enumerate(classes)}
# 保存类别文件
os.makedirs(save_dir, exist_ok=True)
with open(os.path.join(save_dir, "classes.txt"), "w", encoding="utf-8") as f:
for cls in classes:
f.write(cls + "\n")
# 创建目录结构
for split in ["train", "val", "test"]:
os.makedirs(os.path.join(save_dir, "images", split), exist_ok=True)
os.makedirs(os.path.join(save_dir, "labels", split), exist_ok=True)
# 处理数据集
for split in ["train", "val", "test"]:
print(f"Processing {split} set...")
image_list = data[split]
for img_name in tqdm(image_list):
img_path = os.path.join(img_dir, img_name + ".jpg")
label_path = os.path.join(save_dir, "labels", split, img_name + ".txt")
save_img_path = os.path.join(save_dir, "images", split, img_name + ".jpg")
# 确保图片存在
if not os.path.exists(img_path):
continue
# 复制图片到新目录
if not os.path.exists(save_img_path):
os.system(f"cp {img_path} {save_img_path}")
# 读取图片尺寸
img = cv2.imread(img_path)
if img is None:
continue
h, w, _ = img.shape
# 写 YOLO 标签
with open(label_path, "w", encoding="utf-8") as f:
if img_name in data["annotations"]:
anns = data["annotations"][img_name]
for ann in anns:
cls = ann["category"]
if cls not in cls2id:
continue
# TT100K bbox 是 [xmin, ymin, xmax, ymax]
xmin, ymin, xmax, ymax = ann["bbox"]
# 转 YOLO 格式 (归一化)
x_center = (xmin + xmax) / 2 / w
y_center = (ymin + ymax) / 2 / h
bw = (xmax - xmin) / w
bh = (ymax - ymin) / h
f.write(f"{cls2id[cls]} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}\n")
print("转换完成!YOLO 数据集已生成在 datasets/ 文件夹下。")
转换结果目录结构
运行后会生成如下目录:
datasets/
├── classes.txt
├── images/
│ ├── train/
│ ├── val/
│ └── test/
└── labels/
├── train/
├── val/
└── test/
其中:
-
classes.txt
保存类别名 -
labels/*.txt
是 YOLO 格式的标签 -
images/*.jpg
是对应图片
5. 小结
-
交通标志检测数据集常见格式包括 VOC、COCO、YOLO。
-
YOLOv8 推荐采用 YOLO TXT 格式,需进行坐标归一化。
-
数据转化后应整理为标准目录结构,并通过可视化验证标签正确性。
-
格式转化是目标检测实战的第一步,为后续训练打下基础。