YOLO11实战笔记:从准备数据到输出结果
目标检测是计算机视觉最基础也最实用的任务之一。YOLO系列模型以速度快、精度高、部署便捷著称,而YOLO11作为最新迭代版本,在保持实时性的同时进一步提升了小目标识别能力与多尺度泛化性能。本文不讲抽象理论,不堆砌参数,而是带你从零开始走完一个完整的目标检测项目闭环:从原始图片出发,完成标注、格式转换、环境配置、模型训练,到最后生成带框图和结构化结果——每一步都可复制、可验证、可落地。
你不需要提前掌握深度学习框架细节,只要会用文件夹、写几行Python、看懂终端输出,就能跟着做完。所有操作均基于已预装YOLO11完整环境的镜像,省去90%的环境踩坑时间。
1. 数据准备:从一张图到标准标签
1.1 标注工具选择与实操要点
我们推荐使用轻量、开源、中文支持好的Labelme(v5.4.1+)。它不依赖复杂IDE,单个Python脚本即可启动,且导出JSON结构清晰,便于后续转换。
安装命令(镜像中已预装,此步仅作说明):
pip install labelme启动后点击【Open Dir】加载你的图像文件夹,然后:
- 点击【Create Rectangle】框选目标物体
- 在弹出输入框中填写类别名(如
car、person、bicycle) - 每张图可标注多个目标,支持重叠、遮挡场景
- 标注完成后务必点击【Save】,生成同名
.json文件(如img001.jpg→img001.json)
关键提醒:Labelme默认保存坐标为像素值,而YOLO11要求归一化坐标(0~1区间)。这一步不能跳过,必须通过脚本转换——后面会提供稳定可用的转换代码。
1.2 JSON转YOLO11标准txt:一行代码解决
YOLO11使用的标签格式是纯文本.txt,每行代表一个目标,格式为:
<class_id> <x_center_norm> <y_center_norm> <width_norm> <height_norm>其中所有坐标和尺寸均已除以图像宽高,范围严格在[0,1]内。
下面这段代码已在镜像中验证通过,直接复制粘贴到Jupyter或.py文件中即可运行:
import json import os from pathlib import Path # 自定义类别映射表(按需修改) label_map = { "person": 0, "car": 1, "bus": 2, "truck": 3, "bicycle": 4, "motorcycle": 5 } def convert_labelme_to_yolo(json_path: str, output_dir: str): with open(json_path, 'r', encoding='utf-8') as f: data = json.load(f) img_w = data['imageWidth'] img_h = data['imageHeight'] annotations = [] for shape in data.get('shapes', []): label = shape['label'] if label not in label_map: continue class_id = label_map[label] points = shape['points'] if len(points) < 2: continue # 取矩形左上+右下两点(Labelme矩形固定为2点) (x1, y1), (x2, y2) = points[0], points[1] x_min, x_max = min(x1, x2), max(x1, x2) y_min, y_max = min(y1, y2), max(y1, y2) # 归一化计算 x_center = (x_min + x_max) / 2.0 / img_w y_center = (y_min + y_max) / 2.0 / img_h width = (x_max - x_min) / img_w height = (y_max - y_min) / img_h annotations.append(f"{class_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}") # 输出路径:同名txt,存入指定目录 txt_name = Path(json_path).stem + '.txt' output_path = os.path.join(output_dir, txt_name) os.makedirs(output_dir, exist_ok=True) with open(output_path, 'w', encoding='utf-8') as f: f.write('\n'.join(annotations)) def batch_convert(input_folder: str, output_folder: str): for json_file in Path(input_folder).glob("*.json"): convert_labelme_to_yolo(str(json_file), output_folder) print(f" 已完成 {len(list(Path(input_folder).glob('*.json')))} 个JSON文件转换") # ▶ 执行转换(请按实际路径修改) batch_convert( input_folder="/mnt/data/json_labels", # 替换为你存放json的路径 output_folder="/mnt/data/yolo11_labels" # 转换后txt将存于此 )运行后,你会在/mnt/data/yolo11_labels/下看到与图片一一对应的.txt文件,例如:
/mnt/data/yolo11_labels/img001.txt /mnt/data/yolo11_labels/img002.txt ...验证小技巧:打开任意一个txt,检查是否每行都是5个数字,且第2~5位都在0~1之间。若出现负数或大于1的值,说明标注时坐标顺序异常,需回Labelme重新框选。
2. 目录结构搭建:让YOLO11“认得清”你的数据
YOLO11(基于ultralytics 8.3.9)对数据组织有明确约定。镜像中已预置ultralytics-8.3.9/工程目录,你只需在其同级创建标准数据结构即可。
2.1 推荐项目根目录结构
your_project/ ├── ultralytics-8.3.9/ # 镜像自带,勿动 ├── datasets/ # 你新建的主数据目录 │ └── my_custom_dataset/ # 自定义数据集名(可改) │ ├── train/ │ │ ├── images/ # 存放训练图(jpg/png) │ │ └── labels/ # 存放对应txt标签(与images同名) │ ├── val/ │ │ ├── images/ │ │ └── labels/ │ └── test/ # 可选,推理用 ├── weights/ # 存放预训练权重(镜像已含yolo11m.pt等) ├── train.py # 训练脚本(你新建) └── infer.py # 推理脚本(你新建)提示:
datasets/my_custom_dataset/是你整个任务的“工作区”,后续所有路径都基于它定义。
2.2 创建数据集YAML配置文件
在ultralytics-8.3.9/cfg/datasets/下新建文件my_custom_dataset.yaml,内容如下:
# Ultralytics YOLO , AGPL-3.0 license train: ../datasets/my_custom_dataset/train/images # 相对于yaml文件的路径 val: ../datasets/my_custom_dataset/val/images test: ../datasets/my_custom_dataset/test/images # 可选 # 类别数量与名称(顺序必须与label_map完全一致) nc: 6 names: ["person", "car", "bus", "truck", "bicycle", "motorcycle"]注意:train和val的路径是相对于该yaml文件所在位置(即ultralytics-8.3.9/cfg/datasets/)的相对路径。../表示向上一级,再进入你的datasets/目录。
3. 模型训练:三步启动,全程可控
镜像已预装全部依赖(PyTorch 1.13.1 + CUDA 11.7),无需额外安装。你只需专注训练逻辑。
3.1 进入工作目录并确认环境
cd ultralytics-8.3.9/ python -c "from ultralytics import YOLO; print(' YOLO11环境就绪')"若输出YOLO11环境就绪,说明一切正常。
3.2 编写精简版训练脚本(train.py)
在ultralytics-8.3.9/同级目录创建train.py,内容如下(已剔除冗余参数,保留最常用12项):
from ultralytics import YOLO # 1⃣ 加载模型结构 + 预训练权重 model = YOLO("yolo11m.yaml").load("weights/yolo11m.pt") # 2⃣ 定义核心训练参数(中文注释版,开箱即用) train_args = { "data": "cfg/datasets/my_custom_dataset.yaml", # 指向你刚写的yaml "epochs": 100, # 训练轮次(小数据集建议50~100) "imgsz": 640, # 输入分辨率(显存紧张可降为320) "batch": 8, # 每批图像数(A30卡推荐8~16) "name": "my_custom_v1", # 实验名称,结果将存于 runs/detect/my_custom_v1/ "project": "runs/detect", "save": True, "save_period": -1, # -1=只存最终best.pt和last.pt "device": "0", # 使用GPU 0(填"cpu"则用CPU) "workers": 4, # 数据加载线程数(根据CPU核数调整) "cache": "ram", # 将数据集缓存到内存,加速训练 "optimizer": "auto", # 自动选择SGD/Adam(小数据集建议"sgd") "lr0": 0.01, # 初始学习率(大模型可设0.001) "box": 7.5, # 边界框损失权重(默认值,一般不调) "cls": 0.5, # 分类损失权重(默认值) "dfl": 1.5, # 分布焦点损失权重(默认值) "val": True, # 训练中自动验证 "plots": True, # 自动生成loss曲线、PR曲线等图表 } # 3⃣ 开始训练(执行后终端将实时打印进度) if __name__ == "__main__": results = model.train(**train_args) print(" 训练完成!模型已保存至:", results.save_dir)3.3 运行训练并解读关键日志
执行命令:
python train.py你会看到类似输出:
Transferred 649/649 items from pretrained weights Ultralytics 8.3.9 Python-3.9.16 torch-1.13.1 CUDA:0 (NVIDIA A30, 24062MiB) Starting training for 100 epochs... Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 1/100 4.7G 2.102 1.587 2.311 128 640: 100%|████| 24/24 [00:03<00:00, 7.2it/s] Class Images Instances Box(P R mAP50 mAP50-95): 100%|████| 12/12 [00:00<00:00, 15.3it/s] all 256 1842 0.752 0.698 0.771 0.523 ... 100/100 4.5G 0.821 0.4123 0.987 42 640: 100%|████| 24/24 [00:02<00:00, 9.8it/s] all 256 1842 0.867 0.851 0.892 0.601 100 epochs completed in 0.042 hours. Optimizer stripped from runs/detect/my_custom_v1/weights/last.pt, 40.7MB Optimizer stripped from runs/detect/my_custom_v1/weights/best.pt, 40.7MB关键指标解读:
Box(P):边界框精确率(Precision)R:召回率(Recall)mAP50:IoU=0.5时的平均精度(工业界常用指标)mAP50-95:IoU从0.5到0.95步长0.05的平均值(学术界标准)best.pt:验证集mAP最高的模型权重(用于推理)last.pt:最后一轮训练的模型权重(可用于断点续训)
健康训练信号:
mAP50从首轮0.4~0.5逐步升至0.8+,且box_loss持续下降;若loss震荡剧烈或不降,需检查标注质量或降低学习率。
4. 模型推理:一张图输入,多种结果输出
训练完成后,best.pt就是你专属的检测模型。推理阶段支持图片、视频、文件夹、摄像头等多种输入源,结果可可视化、可保存、可结构化提取。
4.1 快速验证:单图检测(Jupyter友好)
在Jupyter中运行以下代码,立即看到带框效果图:
from ultralytics import YOLO from IPython.display import display, Image # 加载训练好的最佳模型 model = YOLO("runs/detect/my_custom_v1/weights/best.pt") # 对单张图推理(自动保存带框图到 runs/detect/predict/) results = model.predict( source="datasets/my_custom_dataset/test/images/sample01.jpg", conf=0.5, # 置信度过滤(0.3~0.7常用) save=True, # 保存带框图 save_txt=True, # 保存检测结果txt(含类别、坐标、置信度) show_conf=True,# 显示置信度数值 show_labels=True, line_width=2 # 边框粗细 ) # 在Jupyter中直接显示结果图 display(Image("runs/detect/predict/sample01.jpg", width=600))运行后,你将在runs/detect/predict/下看到:
sample01.jpg:原图叠加检测框与标签sample01.txt:结构化结果,每行格式为class_id center_x center_y width height confidence
4.2 批量处理:文件夹推理与结果解析
创建infer.py脚本,实现自动化批量推理:
from ultralytics import YOLO import os from pathlib import Path model = YOLO("runs/detect/my_custom_v1/weights/best.pt") # 推理整个文件夹(支持jpg/png) results = model.predict( source="datasets/my_custom_dataset/test/images/", conf=0.45, iou=0.6, save=True, save_txt=True, save_conf=True, # 保存置信度到txt project="runs/detect", name="inference_results" ) print(f" 推理完成!共处理 {len(results)} 张图像") print(f" 结果保存在:runs/detect/inference_results/") # 可选:打印首张图的检测详情(调试用) first_result = results[0] boxes = first_result.boxes print(f"\n 首张图检测到 {len(boxes)} 个目标:") for i, box in enumerate(boxes): cls_id = int(box.cls.item()) conf = float(box.conf.item()) xyxy = box.xyxy[0].tolist() # [x1,y1,x2,y2] 像素坐标 print(f" {i+1}. 类别: {model.names[cls_id]}, 置信度: {conf:.3f}, 位置: {xyxy}")运行后,runs/detect/inference_results/下将生成:
image_001.jpg,image_002.jpg, ...(带框图)labels/image_001.txt,labels/image_002.txt, ...(结构化文本)results.csv(汇总统计表,含每图检测数、平均置信度等)
进阶提示:
results[0].boxes.xyxy返回的是归一化坐标(0~1),若需像素坐标,请用results[0].boxes.xyxy * [img_w, img_h, img_w, img_h]还原。
5. 效果优化与避坑指南:来自真实训练经验
5.1 三类高频问题与解法
| 问题现象 | 可能原因 | 快速验证方式 | 推荐解法 |
|---|---|---|---|
| 训练loss不下降,mAP始终低于0.3 | 标注错误(漏标、错标、坐标反向)、类别名与yaml不一致 | 检查yolo11_labels/中任意txt文件,确认每行5个数字且第2~5位∈[0,1];对比my_custom_dataset.yaml中names顺序与label_map是否一致 | 用脚本重跑标注转换;用labelme打开原图+json,人工抽检10张 |
| 验证时大量误检(背景被框) | 数据增强过强(尤其mosaic=1.0)、学习率过高 | 临时关闭mosaic:mosaic=0.0;降低lr0至0.001 | 在train_args中添加"mosaic": 0.0, "lr0": 0.001 |
| 推理结果框偏移、尺寸不准 | 训练imgsz与推理imgsz不一致、模型未收敛 | 查看训练日志末尾mAP50是否≥0.8;确保model.predict(imgsz=640)与训练一致 | 重新训练(增加epochs);严格统一imgsz参数 |
5.2 性能与精度平衡建议
- 显存不足(OOM):优先调小
batch=4+imgsz=320,而非降低epochs - 小目标漏检严重:启用P2层输出(修改
yolo11.yaml中head部分,增加P2分支)或使用--augment增强小目标 - 推理速度慢:导出ONNX后用ONNX Runtime推理(
model.export(format="onnx")),速度提升2~3倍
6. 总结:你已掌握YOLO11工程化落地全链路
回顾本文,你已完成一个端到端的目标检测项目:
- 数据侧:用Labelme完成标注 → 用Python脚本批量转为YOLO11标准txt → 搭建符合规范的
datasets/目录 - 配置侧:编写
my_custom_dataset.yaml定义数据路径与类别 → 确认yolo11m.yaml结构可用 - 训练侧:运行
train.py启动训练 → 看懂日志中的loss与mAP变化 → 获取best.pt - 推理侧:用
infer.py批量处理图片 → 得到带框图、结构化txt、汇总csv → 提取坐标与置信度供业务系统调用
YOLO11不是黑盒,它的每个环节都透明、可干预、可调试。你不需要成为算法专家,但可以成为能交付结果的CV工程师——而这正是工程实践的核心价值。
下一步,你可以尝试:
🔹 将检测结果接入Web界面(Flask/FastAPI)
🔹 用model.export(format="onnx")导出模型部署到边缘设备
🔹 基于检测框坐标做计数、测距、轨迹分析等上层应用
真正的AI落地,始于一次可复现的训练,成于一个能解决问题的结果。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。