
给摄像头装上检测框OpenCV DNN 加载 YOLO 模型的 30 行最小路径【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv这篇实战直接用 OpenCV 的 DNN 模块深度神经网络推理接口负责加载和运行 ONNX 模型跑一个 YOLO 目标检测流程读入摄像头或图片框出人、车、动物并标上置信度。你不需要 PyTorch 环境不需要 GPU一段 C 代码加上一个现成的 yolov8n.onnx 权重文件就能出结果。跑起来之后你会在窗口里看到绿色的检测框和bus: 0.93这样的标签。先跑起来最小可行路径仓库自带的 samples/dnn/ 示例已经把整个流程封装好了最短路径是直接用官方示例验证环境# 1. 下载 yolov8n 权重会自动存到当前目录 python samples/dnn/download_models.py yolov8 # 2. 运行检测对图片 ./example_dnn_object_detection yolov8 --inputsamples/data/baboon.jpg # 2b. 对摄像头去掉 --input 即可 ./example_dnn_object_detection yolov8如果只想要自己可控的最小版本下面是核心骨架全部逻辑不超过 25 行#include opencv2/dnn.hpp #include opencv2/highgui.hpp #include opencv2/imgproc.hpp int main() { // 加载模型ONNX 格式指定 OpenCV 后端 CPU cv::dnn::Net net cv::dnn::readNet(yolov8n.onnx); net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV); net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU); cv::VideoCapture cap; cap.open(0); // 打开默认摄像头 cv::Mat frame; while (cap frame) { // 预处理640x640、除以255归一化、BGR转RGB cv::Mat blob cv::dnn::blobFromImage( frame, 1.0/255.0, cv::Size(640, 640), cv::Scalar(0,0,0), true, false); net.setInput(blob); // 推理拿到未连接输出的张量 std::vectorcv::Mat outs; net.forward(outs, net.getUnconnectedOutLayersNames()); // 后处理yoloPostProcessing 内做置信度过滤 NMS这里从略 // 完整实现见 samples/dnn/object_detection.cpp cv::imshow(OpenCV 目标检测, frame); cv::waitKey(1); } return 0; }编译g -o detect yolo_min.cpp \pkg-config --cflags --libs opencv4。YOLOYou Only Look Once就是一次前向传播直接吐出所有框的单阶段检测器省掉了先提议再分类的两阶段开销所以才能实时。拆开看每段代码在干什么上面的骨架里真正决定效果的其实就四步。① 模型加载——readNet负责把 ONNX 图结构读进 OpenCV 内部表示setPreferableBackend/Target只是建议指定不了的层会回退到 CPUcv::dnn::Net net cv::dnn::readNet(yolov8n.onnx); net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV); // 也可换 CUDA / OpenVINO net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);改这里可以换硬件加速路径编译时带了 CUDA 就设DNN_BACKEND_CUDADNN_TARGET_CUDAIntel 平台可试 OpenVINO。② 预处理——blobFromImage一步完成缩放、归一化、通道交换。yolov8 系列参数固定640x640、scale1/255、不扣均值、BGR 换 RGBcv::Mat blob cv::dnn::blobFromImage( frame, 1.0/255.0, cv::Size(640, 640), cv::Scalar(0,0,0), true /*swapRB*/, false);改这里的输入尺寸要连模型一起换640 换 320 会更快但小目标基本全丢。③ 推理与解析——forward返回若干张量YOLOv8 输出是[1, 84, 8400]前 4 列是中心坐标和宽高后 80 列是 COCO 类别得分。逐行取最大得分for (int i 0; i preds.rows; i) { cv::Mat scores preds.row(i).colRange(4, preds.cols); // 80类得分 double conf; cv::Point maxLoc; cv::minMaxLoc(scores, 0, conf, 0, maxLoc); // 最大得分及其位置 if (conf 0.5) continue; // 低于阈值直接丢 float* d preds.ptrfloat(i); boxes.push_back(cv::Rect2d(d[0]-d[2]/2, d[1]-d[3]/2, d[2], d[3])); // 中心→左上角 classIds.push_back(maxLoc.x); confidences.push_back((float)conf); }④ NMS 与绘制——一个物体常常被好几个候选框覆盖非极大值抑制NMS就是同类框重叠度高时只留分数最高的那个不做的后果是画面里同一只狗套着三四层框std::vectorint keep; cv::dnn::NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, keep); for (auto idx : keep) { cv::rectangle(frame, boxes[idx], cv::Scalar(0,255,0), 2); cv::putText(frame, cv::format(%.2f, confidences[idx]), boxes[idx].tl(), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0,255,0), 1); }改nmsThreshold就能调框的去重松紧度0.4 是经验默认值。调参、加速与踩过的坑参数默认值调高的效果调低的效果confThreshold0.5框更准、更少误检小目标漏检召回多但误检框刷屏nmsThreshold(IoU)0.4去重更狠密集同类物体可能误杀保留框变多可能一物多框输入分辨率640×640小目标检出率上升推理变慢速度明显提升小目标丢失后端OpenCV/CPU—— 换 CUDA/OpenVINO 是提速主杠杆踩坑记录都是真踩过的输出张量形状和你想的不一样。YOLOv8 是[1,84,8400]YOLOv5 是[1,25200,85]两者解析代码不能互换——官方示例里postprocessing参数区分 yolov5/yolov8/yolov4 就是干这个的直接抄对应分支最稳。窗口能开但框是歪的或全空。九成是预处理对不上忘了swapRBtrue或者把 640 改成了原图尺寸却忘了模型是按 640 训练的。先把参数改回 samples/dnn/models.yml 里该模型别名的默认值。getUnconnectedOutLayersNames拿到空名字。有些导出的 ONNX 有多个输出层但名字不规范改成直接遍历net.getUnconnectedOutLayers()拿索引更保险。往哪儿延伸多模型对比samples/dnn/models.yml 里已经配好 yolov8n/m/l/x、yolov5l、yolov4-tiny 等别名换一行命令就能对比不同体量的速度精度。异步推理与多帧流水线net.forwardAsync()的用法在 samples/dnn/object_detection.cpp 的线程分支里有完整实现适合做摄像头实时场景。类别文件换自定义模型时把 samples/data/dnn/ 下的object_detection_classes_yolo.txt换成你自己训练时的 classes 顺序即可。OpenCV DNN 的目标检测链路就四个动作加载、预处理、前向、NMS 后处理骨架 25 行足够跑通剩下的调优空间全在那几个阈值和后端选择里。跑通之后从 samples/dnn/ 里的分类、分割、跟踪示例继续扩都是一套相同的加载—推理套路。【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考