把标注团队给的检测框直接喂给 YOLOv8 训练,第一轮 loss 正常但预测框全部偏到左上角,检查发现一半文件是 0 到 1 的归一化坐标,另一半是像素值。
这类报错背后常见的原因有几处,逐个排除就行。不同标注工具导出的坐标系不统一;归一化时用了图片原始尺寸而不是缩放后尺寸;坐标顺序 x1y1x2y2 与 xywh 混用;图片被 EXIF 旋转,宽高与实际像素方向不符。
动手时先抽样看坐标的取值范围
python -c "import json;d=json.load(open('ann.json'));print(d['boxes'][:3])"
然后按值域判断并统一转成归一化 xywh
python -c "import json;d=json.load(open('ann.json'));print([1 if max(b)>1.5 else 0 for b in d['boxes'][:5]])"
随后用 PIL 读实际尺寸做归一
python -c "from PIL import Image;im=Image.open('a.jpg');print(im.size, im.getexif().get(274))"
可视化 20 张叠加框确认对齐
python draw_boxes.py --images imgs/ --ann ann.json --sample 20
这次没动代码,只在配置和运行环境上找原因。
恢复的判定其实很直接。统一坐标系后可视化叠加的框与目标完全贴合,训练 loss 下降曲线正常,mAP 从 0.12 回到 0.71。
坐标问题的表现是模型学不动而不是报错,训练前必须做一次可视化抽检,比盯 loss 曲线有效得多。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
