当前位置: 首页 > news >正文

从TT100K到YOLO:一份完整的交通标志数据集转换与实战指南

1. 为什么需要转换TT100K数据集格式

第一次接触TT100K数据集时,我完全被它复杂的目录结构和标注格式搞懵了。这个由清华大学和腾讯联合发布的交通标志数据集,包含了10万张图片和3万多个标注实例,但它的JSON标注格式和YOLO完全不兼容。当时为了训练YOLOv5模型,我不得不花了两周时间研究格式转换的问题。

TT100K数据集最大的特点是采用层级式JSON标注,所有标注信息都存放在一个巨大的annotations_all.json文件里。这种设计虽然节省了存储空间,但在实际使用时非常不方便。相比之下,YOLO需要的格式就简单多了——每个图片对应一个.txt文件,每行记录一个目标的类别和归一化坐标。

举个具体例子,TT100K中一个停车标志的标注可能是这样的:

{ "objects": [{ "category": "p12", "bbox": {"xmin": 100, "ymin": 200, "xmax": 150, "ymax": 250} }] }

而YOLO需要的格式则是:

0 0.325 0.417 0.104 0.083

这种转换不仅仅是格式变化,还涉及到坐标系的转换(从绝对坐标到相对坐标)、类别ID的重新映射(从字符串标签到数字索引)以及数据集划分策略的调整。我在第一次尝试时,就因为忽略了图像尺寸的读取顺序,导致所有检测框都偏移了位置。

2. 数据预处理的关键步骤

2.1 筛选有效类别

TT100K原始数据集包含221个交通标志类别,但实际项目中我们往往只需要其中的一部分。我的经验是先用以下代码统计各类别的实例数量:

with open('annotations_all.json') as f: data = json.load(f) class_count = {} for img_id, img_info in data['imgs'].items(): for obj in img_info['objects']: class_count[obj['category']] = class_count.get(obj['category'], 0) + 1 # 按数量排序 sorted_classes = sorted(class_count.items(), key=lambda x: x[1], reverse=True)

建议保留实例数超过100的类别,这样可以保证每个类别都有足够的训练样本。在我的实践中,最终筛选出了45个主要类别,包括:

  • 禁令标志(如p1、p10)
  • 警告标志(如ph4、pl5)
  • 指示标志(如i2、i4)

2.2 处理破损和无效数据

数据集里总会有些"问题儿童"需要特别处理:

  1. 标注错误:有些边界框完全超出图像范围,需要用clamp函数限制坐标
  2. 图像损坏:约0.3%的JPEG文件无法正常读取,建议用OpenCV的imread检查
  3. 长宽比异常:极少数图片的宽高比超过10:1,这类样本最好剔除

这里分享一个实用的图像验证代码片段:

def validate_image(img_path): try: img = cv2.imread(img_path) if img is None: return False h, w = img.shape[:2] return w > 16 and h > 16 # 过滤掉过小的图像 except: return False

3. 从TT100K到COCO的格式转换

3.1 构建COCO格式的中间层

为什么需要COCO格式作为中转?因为直接从TT100K转到YOLO格式会丢失很多结构化信息。我的转换脚本主要处理以下几个部分:

  1. 类别信息:将筛选后的类别建立数字ID映射
  2. 图像信息:记录每张图片的路径、尺寸和唯一ID
  3. 标注信息:转换边界框格式并关联到对应图像

核心的数据结构如下:

coco_format = { "info": {...}, "licenses": [...], "categories": [ {"id": 0, "name": "p1", "supercategory": "prohibitory"}, ... ], "images": [ {"id": 0, "file_name": "test/100.jpg", "width": 640, "height": 480}, ... ], "annotations": [ { "id": 0, "image_id": 0, "category_id": 0, "bbox": [100, 200, 50, 50], "area": 2500, "iscrowd": 0 }, ... ] }

3.2 数据集划分策略

TT100K原本的划分方式不适合目标检测任务。我采用了分层抽样的方法,确保每个类别在训练集、验证集和测试集中都有代表:

  1. 按7:2:1的比例划分
  2. 对样本数较少的类别,适当增加其在训练集中的比例
  3. 确保同一张图片不会出现在多个子集中

实现代码的关键部分:

for cls in class_list: cls_images = get_images_by_class(cls) random.shuffle(cls_images) train_end = int(0.7 * len(cls_images)) val_end = train_end + int(0.2 * len(cls_images)) train_set.update(cls_images[:train_end]) val_set.update(cls_images[train_end:val_end]) test_set.update(cls_images[val_end:])

4. COCO到YOLO格式的终极转换

4.1 坐标归一化处理

这是最容易出错的环节。YOLO要求的是中心坐标+宽高的归一化格式,计算时需要特别注意:

def coco_to_yolo_bbox(bbox, img_width, img_height): # bbox格式:[x_min, y_min, width, height] x_center = bbox[0] + bbox[2] / 2 y_center = bbox[1] + bbox[3] / 2 # 归一化 x_center /= img_width y_center /= img_height width = bbox[2] / img_width height = bbox[3] / img_height return [x_center, y_center, width, height]

4.2 生成YOLO格式的标签文件

每个图片对应一个.txt文件,格式要求非常严格:

  • 每行一个目标
  • 空格分隔的五个数值:类别ID、中心x、中心y、宽度、高度
  • 数值精度保留6位小数

实际操作时我建议使用这个模板:

def save_yolo_label(file_path, class_id, bbox): with open(file_path, 'a') as f: line = f"{class_id} {bbox[0]:.6f} {bbox[1]:.6f} {bbox[2]:.6f} {bbox[3]:.6f}\n" f.write(line)

4.3 创建数据集配置文件

最后需要准备YOLO模型训练必需的data.yaml文件:

train: ../images/train val: ../images/val test: ../images/test nc: 45 # 类别数量 names: ['p1', 'p10', 'ph4', ...] # 按类别ID顺序排列

5. 实战中的常见问题与解决方案

5.1 标签错位问题

第一次训练时,模型完全学不会任何东西。排查后发现是因为:

  1. 图像尺寸读取错误(OpenCV的shape返回的是高度在前)
  2. 归一化时混淆了宽高顺序

解决方法是在转换时统一添加尺寸检查:

height, width = img.shape[:2] assert width > 0 and height > 0, f"Invalid image size: {img_path}"

5.2 类别不平衡处理

某些常见标志(如限速标志)的样本数是不常见标志的100倍以上。我采用了这些策略:

  1. 过采样少数类别
  2. 使用带权重的损失函数
  3. 在数据增强时对少数类别使用更强的变换

5.3 数据增强技巧

针对交通标志的特点,这些增强方式特别有效:

  1. 模拟天气变化:添加雾、雨、雪效果
  2. 透视变换:模拟不同拍摄角度
  3. 色彩抖动:考虑白平衡变化的影响

示例增强代码:

import albumentations as A transform = A.Compose([ A.RandomBrightnessContrast(p=0.5), A.HueSaturationValue(p=0.5), A.RandomFog(fog_coef_lower=0.1, fog_coef_upper=0.3, p=0.1), A.RandomRain(p=0.1) ])

6. 完整代码结构与使用指南

我的项目目录结构是这样的:

tt100k2yolo/ ├── configs/ │ ├── classes.txt # 筛选后的类别列表 │ └── data.yaml # YOLO数据集配置 ├── datasets/ │ ├── images/ # 图片文件夹 │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── labels/ # 标签文件夹 │ ├── train/ │ ├── val/ │ └── test/ └── scripts/ ├── convert.py # 主转换脚本 └── utils.py # 工具函数

转换流程只需三步:

  1. 修改configs/classes.txt定义需要的类别
  2. 运行转换脚本:
python scripts/convert.py \ --input_dir /path/to/tt100k \ --output_dir ./datasets \ --config ./configs/classes.txt
  1. 检查生成的data.yaml文件

7. 模型训练与效果验证

使用转换后的数据集训练YOLOv8,关键配置参数:

model = YOLO('yolov8n.yaml') results = model.train( data='configs/data.yaml', epochs=300, imgsz=640, batch=16, optimizer='AdamW' )

在我的RTX 3090上训练300个epoch大约需要8小时。最终在测试集上的指标:

  • mAP@0.5: 0.87
  • mAP@0.5:0.95: 0.63
  • 推理速度:8ms/张(640x640)

特别要注意的是,交通标志检测需要更高的召回率。我通过调整置信度阈值和NMS参数,将漏检率控制在5%以下:

results = model.predict( source='test.jpg', conf=0.3, # 降低置信度阈值 iou=0.4, # 放宽IoU阈值 augment=True )

经过三个版本迭代,这套转换流程已经稳定支持各种YOLO系列模型。最大的收获是认识到数据质量比模型结构更重要——合理的格式转换和数据处理能让普通模型也表现出色。

http://www.jsqmd.com/news/1124694/

相关文章:

  • PIC18F86J50驱动WS2812 LED的嵌入式开发指南
  • AI安全实战:从MITRE ATLAS威胁建模到政策合规的防御体系构建
  • OpenCore Legacy Patcher终极实用指南:让老款Mac焕发新生
  • Python+CNN实现图像识别:从数据准备到模型部署
  • 基于25CSM04 EEPROM与PIC18F86J50的数据存储检索系统设计
  • 开源DPS分析器:三分钟解锁《碧蓝幻想》战斗数据可视化
  • STM32与25CSM04 EEPROM的高效数据存储与检索方案
  • CS2200-CP与PIC18LF4553高精度时钟方案解析
  • TPAFE0808与PIC32MZ实现多通道信号采集与实时控制
  • 开源量子计算全栈工作流NWQWorkflow解析与应用
  • 山区汽车维修实战:机油泄漏诊断与应急处理指南
  • 【Java毕业设计】花园景观方案设计与素材管理系统的设计与实现 园林设计项目进度管控管理系统(源码+文档+远程调试,全bao定制等)
  • 五种归一化技术选型指南:BatchNorm、LayerNorm、InstanceNorm、GroupNorm与RMSNorm实战解析
  • Java Web应用XSS漏洞审计实战:从原理到修复的完整指南
  • AI模型选型新范式:从能力比拼到成本结构优化
  • AI产品经理必备:业务量身定制的评估计分板实战指南
  • AI如何助力科研开题报告撰写:选题、文献与格式优化
  • DexHunter安卓脱壳实战:从ART虚拟机源码修改到内存Dex捕获
  • Navicat重置试用期终极指南:3种方法无限延长14天限制
  • 基于HSV颜色特征的杂草识别系统设计与实现
  • Seedance 2.0与飞书机器人安全集成:RBAC加固与租户隔离实战
  • CEEMDAN-VMD-Transformer-LSTM多模态时间序列预测实战
  • 3分钟完成B站视频转文字:免费开源工具bili2text深度解析指南
  • 基于OpenCV的疲劳检测系统设计与实现
  • LTC6904与PIC32构建高精度方波发生器设计指南
  • Python属性测试利器Hypothesis:从原理到实战,提升代码健壮性
  • 基于Hu不变矩的轻量级人脸识别系统实现
  • AI驱动的高频攻击与智能主动防御体系构建实战
  • Three.js 科技粒子教程
  • 基于AI Agent工作流构建自动化行业趋势报告生成器