YOLO 训练车牌定位模型 + OpenCV C++ 部署完整步骤

YOLO 训练车牌定位模型 + OpenCV C++ 部署完整步骤

一、前期准备(核心工具 / 环境)

  1. 硬件:GTX 1060 及以上显卡(显存≥6G),避免训练卡顿
  2. 软件:
    • 训练端:Windows/Linux + Python 3.8~3.10 + PyTorch 1.10~2.0 + YOLOv8(ultralytics 库,适配性最优)
    • 部署端:Windows + VS2019/2022 + OpenCV 4.5~4.8(需带 DNN 模块,默认编译已包含)
  3. 数据集:标注好的车牌数据集(格式为 YOLO txt,含 train/val 集,比例 8:2)

二、步骤 1:车牌数据集制作 / 整理(关键:标注精准 + 场景全覆盖)

1. 数据集收集

  • 来源:网络公开车牌数据集(如 CCPD、CALTech)+ 实拍图(多角度、逆光、雨雾、遮挡、不同车牌颜色),总量≥1000 张(越多精度越高,建议 2000+)
  • 规格:统一缩放至 640×640(适配 YOLO 默认输入,减少训练失真)

2. 标注(用 LabelImg,简单易操作)

  1. 安装 LabelImg:pip install labelImg,终端输入labelImg启动
  2. 标注设置:
    • 点击「Change Save Dir」选标注文件保存路径
    • 顶部「View」勾选「Auto Save mode」「YOLO」,切换为 YOLO 标注格式
  3. 标注流程:
    • 打开图片文件夹,框选车牌区域,标签名统一为「plate」(仅 1 类,简化模型)
    • 标注后自动生成 txt 文件(与图片同名),txt 内容格式:0 x1 y1 x2 y2(0 为 plate 类别 ID,坐标为归一化后值,无需手动换算)

3. 数据集目录结构(严格按 YOLO 要求)

plaintext

plate_dataset/ ├─ images/ # 所有图片 │ ├─ train/ # 训练集图片(80%) │ └─ val/ # 验证集图片(20%) └─ labels/ # 所有标注txt ├─ train/ # 训练集标注(对应images/train) └─ val/ # 验证集标注(对应images/val) 

4. 生成数据集配置文件(plate.yaml)

新建 txt 改名为plate.yaml,内容如下(路径填自己的数据集绝对路径):

yaml

# 数据集路径 path: D:/plate_dataset # 数据集根目录 train: images/train # 训练集图片路径(相对path) val: images/val # 验证集图片路径(相对path) # 类别 names: 0: plate # 仅车牌1类,ID=0 

三、步骤 2:YOLOv8 训练车牌定位模型

1. 安装 YOLOv8 库

终端执行:pip install ultralytics(自动适配 PyTorch 环境)

2. 启动训练(单类定位,参数精简高效)

新建train_plate.py,代码如下(直接运行,无需改太多参数):

python

运行

from ultralytics import YOLO # 1. 加载预训练模型(用yolov8n.pt,轻量化,适配C++部署) model = YOLO('yolov8n.pt') # 2. 训练配置(核心参数,按需微调) results = model.train( data='D:/plate_dataset/plate.yaml', # 数据集配置文件路径 epochs=50, # 训练轮数(1000张图50轮足够,多了易过拟合) batch=8, # 批次大小(显卡显存6G设8,8G设16) imgsz=640, # 输入图片尺寸 lr0=0.01, # 初始学习率 classes=[0], # 仅训练第0类(plate) save=True, # 保存模型 device=0, # 用GPU训练(0为GPU编号,CPU填cpu) patience=10 # 10轮精度无提升停止训练,防过拟合 ) 

3. 训练完成后取模型

训练结束后,在runs/detect/train/weights/目录下,取best.pt(最优精度模型),后续转 ONNX 格式供 C++ 调用。

四、步骤 3:将 YOLOv8.pt 模型转 ONNX 格式(OpenCV DNN 支持)

YOLO 原生 pt 模型 OpenCV 不兼容,需转 ONNX(通用格式,DNN 模块可直接加载)

1. 模型转换

新建pt2onnx.py,代码如下:

python

运行

from ultralytics import YOLO # 加载最优模型 model = YOLO('runs/detect/train/weights/best.pt') # 转ONNX,简化模型(opset=12适配OpenCV 4.5+) model.export(format='onnx', opset=12, simplify=True) 

运行后,在best.pt同目录下生成best.onnx,即部署用模型。

2. 提取类别名(可选,用于显示标签)

新建class_names.txt,仅写 1 行:plate(与训练时标签一致)

五、步骤 4:OpenCV C++ 部署 YOLOv8 ONNX 模型(核心代码,可直接跑)

1. VS 项目配置(关键:关联 OpenCV)

  1. 新建 VS 控制台项目(空项目,x64 Debug/Release)
  2. 配置属性(右键项目→属性→配置属性):
    • 包含目录:添加 OpenCV 安装目录下includeinclude/opencv2(如D:/opencv4.6/build/include
    • 库目录:添加 OpenCVx64/vc16/lib(如D:/opencv4.6/build/x64/vc16/lib
    • 链接器→输入→附加依赖项:
      • Debug 模式:opencv_world460d.lib(460 对应 OpenCV 版本,改自己的)
      • Release 模式:opencv_world460.lib
  3. 复制 OpenCV 动态库到项目 exe 目录:
    • opencv/build/x64/vc16/bin下的opencv_world460d.dll(Debug)/opencv_world460.dll(Release),粘贴到 VS 项目x64/Debugx64/Release目录(与 exe 同路径)

2. 核心 C++ 代码(完整可运行,含预处理 + 推理 + 后处理)

新建main.cpp,代码如下(注释详细,直接替换模型 / 图片路径即可):

cpp

运行

#include <opencv2/opencv.hpp> #include <opencv2/dnn.hpp> #include <iostream> #include <vector> #include <string> using namespace cv; using namespace cv::dnn; using namespace std; // YOLOv8配置参数(需根据自己模型微调) const float CONF_THRESH = 0.5f; // 置信度阈值(低于0.5过滤) const float NMS_THRESH = 0.4f; // NMS阈值(去重重叠框) const int INPUT_W = 640; // 输入宽 const int INPUT_H = 640; // 输入高 const string MODEL_PATH = "D:/best.onnx"; // ONNX模型路径 const string CLASS_PATH = "D:/class_names.txt"; // 类别名路径 // 读取类别名 vector<string> readClassNames(const string& path) { vector<string> classes; ifstream file(path); string line; while (getline(file, line)) { classes.push_back(line); } return classes; } // YOLOv8推理+后处理(解析结果,画框) void yoloDetect(Mat& img, Net& net, vector<string>& classes) { int img_w = img.cols; int img_h = img.rows; // 1. 图像预处理(归一化+转Blob,YOLOv8输入格式:RGB、0-1归一化) Mat blob; blobFromImage(img, blob, 1.0 / 255.0, Size(INPUT_W, INPUT_H), Scalar(0, 0, 0), true, false); net.setInput(blob); // 2. 模型推理(YOLOv8输出层名固定为"output0") Mat outputs = net.forward("output0"); // outputs尺寸:1×8400×6(8400个预测框,6=xywh+conf+class_id) // 3. 结果解析(过滤低置信度,提取有效框) vector<int> class_ids; // 类别ID vector<float> confs; // 置信度 vector<Rect> boxes; // 检测框(像素坐标) float* data = (float*)outputs.data; int num_boxes = outputs.size[1]; // 8400个预测框 for (int i = 0; i < num_boxes; i++) { float conf = data[4]; // 置信度(当前框是目标的概率) if (conf < CONF_THRESH) continue; // 提取类别ID(取最大概率对应的类别) float max_class_conf = 0; int class_id = 0; for (int j = 5; j < 6; j++) { // 仅1类(plate),j从5到5(6-1) float class_conf = data[j]; if (class_conf > max_class_conf) { max_class_conf = class_conf; class_id = j - 5; // 类别ID=0 } } // 计算检测框像素坐标(YOLO输出为归一化xywh,转像素xyxy) float cx = data[0] * img_w; // 框中心x float cy = data[1] * img_h; // 框中心y float w = data[2] * img_w; // 框宽 float h = data[3] * img_h; // 框高 int x1 = max(0, int(cx - w / 2)); // 框左上角x int y1 = max(0, int(cy - h / 2)); // 框左上角y int x2 = min(img_w - 1, int(cx + w / 2)); // 框右下角x int y2 = min(img_h - 1, int(cy + h / 2)); // 框右下角y // 保存结果 class_ids.push_back(class_id); confs.push_back(conf * max_class_conf); // 最终置信度=目标置信度×类别置信度 boxes.push_back(Rect(x1, y1, x2 - x1, y2 - y1)); // 移动到下一个预测框(每框6个参数) data += 6; } // 4. NMS非极大值抑制(去重重叠框) vector<int> indices; NMSBoxes(boxes, confs, CONF_THRESH, NMS_THRESH, indices); // 5. 画框+显示结果 Scalar color(0, 255, 0); // 绿色框 for (int idx : indices) { Rect box = boxes[idx]; int class_id = class_ids[idx]; float conf = confs[idx]; // 画检测框 rectangle(img, box, color, 2, 8); // 显示标签+置信度 string label = classes[class_id] + ":" + format("%.2f", conf); int label_h = 25; Rect label_rect(box.x, box.y - label_h, box.width, label_h); rectangle(img, label_rect, color, -1); // 标签背景 putText(img, label, Point(box.x + 5, box.y - 5), FONT_HERSHEY_SIMPLEX, 0.6, Scalar(255, 255, 255), 1); } } int main() { // 1. 加载ONNX模型和类别名 Net net = readNetFromONNX(MODEL_PATH); vector<string> classes = readClassNames(CLASS_PATH); if (net.empty() || classes.empty()) { cout << "模型或类别名加载失败!" << endl; return -1; } // 启用GPU加速(有GPU必开,速度提升10倍+) net.setPreferableBackend(DNN_BACKEND_CUDA); net.setPreferableTarget(DNN_TARGET_CUDA); // 2. 读取图片/视频(二选一,按需切换) // 方式1:图片检测 Mat img = imread("D:/test_plate.jpg"); // 测试图片路径 if (img.empty()) { cout << "图片读取失败!" << endl; return -1; } yoloDetect(img, net, classes); imshow("Plate Detection", img); waitKey(0); // 按任意键关闭窗口 // 方式2:视频/摄像头检测(注释图片检测,打开下方代码) // VideoCapture cap(0); // 0=电脑摄像头,也可填视频路径(如"D:/test.mp4") // if (!cap.isOpened()) { // cout << "摄像头/视频打开失败!" << endl; // return -1; // } // Mat frame; // while (cap.read(frame)) { // yoloDetect(frame, net, classes); // imshow("Plate Detection", frame); // if (waitKey(1) == 27) break; // ESC键退出 // } // cap.release(); destroyAllWindows(); return 0; } 

3. 运行测试

  1. 替换代码中MODEL_PATH(best.onnx 路径)、CLASS_PATH(class_names.txt 路径)、test_plate.jpg(测试图路径)
  2. 选择 x64 Debug/Release 模式,点击运行,即可看到车牌定位结果(绿色框 + plate 标签 + 置信度)

六、常见问题排查

  1. 模型加载失败:检查 ONNX 路径是否正确,OpenCV 版本是否≥4.5,opset 是否为 12
  2. 无检测结果:置信度阈值设太低(可降为 0.3),数据集场景与测试图差异大,训练轮数不足
  3. 速度慢:未启用 GPU 加速(确认 VS 配置 CUDA,代码中已加setPreferableBackend/Target
  4. 框不准:标注框未紧贴车牌,数据集不足,可增加训练轮数或扩充数据

Read more

Git常用指令

Git 常用50个核心操作命令(附详细说明) 以下按仓库初始化与配置、文件状态与暂存、提交与日志、分支管理、远程仓库、合并与变基、标签、撤销与回滚、LFS大文件、高级实用十大场景分类,覆盖开发全流程高频操作,命令简洁且标注适用场景,新手也能直接套用。 一、仓库初始化与全局配置(5个) 主要用于首次使用Git的环境配置、本地仓库创建,配置后全局生效(除非单独修改仓库配置)。 1. git config --global user.name "你的用户名" 配置Git全局提交用户名(GitHub/GitLab的用户名,必填)。 2. git config --global user.email "你的邮箱" 配置Git全局提交邮箱(与GitHub/GitLab绑定的邮箱,必填)。 3.

By Ne0inhk

PETRV2-BEV开源大模型训练:BEV空间目标检测与BEV分割联合训练

PETRV2-BEV开源大模型训练:BEV空间目标检测与BEV分割联合训练 你是否在尝试复现BEV(Bird's Eye View)感知模型时,被环境配置卡住半天?是否在训练PETR系列模型时,反复遇到数据准备失败、评估指标异常、可视化无法访问等问题?别担心——这篇实操笔记不是照搬文档的“翻译器”,而是一份从真实训练现场抠出来的经验总结。我们全程基于Paddle3D框架,在星图AI算力平台上完整跑通PETRV2-BEV模型的训练流程,覆盖环境搭建、数据准备、精度验证、模型训练、结果可视化到推理部署全链路。所有命令均经实测可运行,每一步都标注了“为什么这么做”和“不这么做会怎样”。 1. 为什么是PETRV2-BEV?BEV空间里的双任务协同价值 在自动驾驶感知系统中,“看得清”只是第一步,“看得准、判得明、用得上”才是关键。传统方法常将目标检测与语义分割拆成两个独立模型,但这样不仅增加计算开销,还容易导致空间定位不一致——比如检测框画在车头,分割掩码却偏到车尾。PETRV2-BEV的突破点,正在于它把这两件事放在同一个BEV特征空间里统一建模。 简单说,它不像普通模型那样先“

By Ne0inhk

【个人经验】使用 MobaXterm 连接服务器 + 环境配置 + 运行github代码

文章目录 * 使用 MobaXterm 连接服务器 + 环境配置 + 运行github代码 * 下载 MobaXterm * SSH 连接服务器 * 情况一:直接 SSH 到服务器 * 情况二:需要 VPN 或跳板机(如不在校园内) * 修改密码(如账号由管理员创建) * 常见问题及解决方法 * 问题一:连接超时 * 问题二:域名无法解析 * 问题三:学校 VPN 检查不通过(compliance check) * 问题四:连接过程中突然断开或出现 keep-alive 信息 * 其他:测试本地 SSH 是否正常 * 配置环境 * 安装 Anaconda * 创建虚拟环境 * 查看 CUDA 信息 * 安装对应版本的 PyTorch * 测试是否安装成功

By Ne0inhk
开源杀疯了!Qwen3.5 Plus + OpenClaw,性能对标GPT-5.2还免费商用

开源杀疯了!Qwen3.5 Plus + OpenClaw,性能对标GPT-5.2还免费商用

文章目录 * 一、先唠明白:Qwen3.5 Plus到底是什么来头 * 二、OpenClaw:给大模型装个「万能插件底座」 * 三、实测对比:凭什么说对标GPT-5.2? * 四、零门槛上手:5行代码调用Qwen3.5 Plus * 五、OpenClaw集成:让大模型更听话、更能打 * 六、本地部署方案:离线也能用,隐私拉满 * 七、商用无忧:开源授权+免费额度全解析 * 八、常见问题踩坑指南 目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步,增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.ZEEKLOG.net/jiangjunshow,教程通俗易懂,高中生都能看懂,还有各种段子风趣幽默,从深度学习基础原理到各领域实战应用都有讲解,我22年的AI积累全在里面了。注意,教程仅限真正想入门AI的朋友,

By Ne0inhk