1. 项目概述今天我要分享一个基于YOLOv5的实时目标检测系统实现方案。这个项目能让你的电脑摄像头变成智能眼睛不仅能识别人脸还能认出80种常见物体从宠物猫狗到日常用品一应俱全。整个过程只需要不到100行Python代码但涉及到的技术细节却非常值得深入探讨。我选择YOLOv5s.onnx模型作为核心主要基于三个考量首先ONNX格式具有极好的跨平台兼容性无论是Windows、Linux还是嵌入式设备都能顺畅运行其次YOLOv5s是YOLO系列中最轻量化的版本在保持不错精度的同时对硬件要求较低最后onnxruntime的推理效率非常高配合CUDA加速能轻松达到实时检测的要求。2. 环境准备与模型获取2.1 基础环境配置要实现这个项目你需要准备以下环境Python 3.7或更高版本OpenCV用于图像处理和摄像头调用ONNX Runtime用于模型推理NumPy用于数值计算安装命令如下pip install opencv-python onnxruntime numpy如果你有NVIDIA显卡并希望使用GPU加速建议安装onnxruntime-gpu版本pip install onnxruntime-gpu注意onnxruntime-gpu需要与CUDA版本严格匹配。当前稳定版本要求CUDA 11.1和cuDNN 8.0。安装前请确认你的CUDA环境配置正确。2.2 模型获取与验证YOLOv5s.onnx模型可以通过官方仓库转换获得克隆YOLOv5官方仓库使用export.py脚本将PyTorch模型转换为ONNX格式转换命令示例python export.py --weights yolov5s.pt --include onnx --opset 12转换完成后建议使用Netron工具可视化模型结构确认输入输出节点是否符合预期。典型的YOLOv5s.onnx模型输入应为1×3×640×640的float32张量输出维度为1×25200×85。3. 核心代码解析3.1 图像预处理实现def letterbox(im, new_shape(640, 640), color(114, 114, 114)): shape im.shape[:2] # 原始图像高宽 r min(new_shape[0] / shape[0], new_shape[1] / shape[1]) new_unpad (int(round(shape[1] * r)), int(round(shape[0] * r))) dw, dh new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] dw, dh dw / 2, dw / 2 if shape[::-1] ! new_unpad: im cv2.resize(im, new_unpad, interpolationcv2.INTER_LINEAR) top, bottom int(round(dh - 0.1)), int(round(dh 0.1)) left, right int(round(dw - 0.1)), int(round(dw 0.1)) im cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, valuecolor) return im, r, (dw, dh)这段预处理代码完成了几个关键操作保持长宽比缩放图像短边缩放到640像素计算需要填充的灰边尺寸确保最终为640×640使用cv2.copyMakeBorder添加灰边返回缩放比例和填充尺寸供后续坐标还原使用实操技巧这里的灰边颜色(114,114,114)是YOLO训练时使用的均值保持一致性有助于提升检测精度。3.2 ONNX Runtime推理配置providers [CUDAExecutionProvider, CPUExecutionProvider] session ort.InferenceSession(yolov5s.onnx, providersproviders)providers列表定义了执行优先级优先尝试使用CUDA GPU加速如果GPU不可用则自动回退到CPU这种配置方式确保了代码在不同硬件环境下的兼容性。在实际部署时可以通过环境变量控制provider选择export ORT_CUDA_DEVICE_ID0 # 指定使用哪块GPU4. 实时检测流程优化4.1 视频流处理循环while True: start_time time.time() ret, frame cap.read() if not ret: break # 预处理 img, ratio, (dw, dh) letterbox(frame) blob img[:, :, ::-1].transpose(2, 0, 1) # BGR→RGB, HWC→CHW blob np.ascontiguousarray(blob).astype(np.float32) / 255.0 blob blob[None] # 添加batch维度 # 推理 outputs session.run(None, {input_name: blob}) predictions outputs[0][0] # 后处理 boxes, scores, class_ids process_predictions(predictions) indices cv2.dnn.NMSBoxes(boxes, scores, conf_threshold, nms_threshold) # 可视化 draw_detections(frame, indices, boxes, scores, class_ids, ratio, (dw, dh)) # 显示FPS fps 1.0 / (time.time() - start_time) cv2.putText(frame, fFPS: {fps:.1f}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) cv2.imshow(Real-time Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break4.2 性能优化技巧异步处理可以使用多线程将图像采集和推理分离避免I/O等待批处理当处理多路视频时合并多个帧一起推理能显著提升吞吐量分辨率调整对于嵌入式设备可适当降低输入分辨率(如320×320)FP16量化导出ONNX模型时使用FP16精度可减少显存占用实测性能对比RTX 3060输入尺寸FP32 FPSFP16 FPS显存占用(MB)640×6401201601024320×3202403202565. 常见问题与解决方案5.1 模型加载失败问题现象[E:onnxruntime:, inference_session.cc:1534 operator()] Exception during initialization: /onnxruntime_src/onnxruntime/core/providers/cuda/cuda_call.cc:122 CUDA failure 3: initialization error解决方案确认CUDA和cuDNN版本匹配尝试仅使用CPU执行session ort.InferenceSession(yolov5s.onnx, providers[CPUExecutionProvider])5.2 检测框位置偏移问题现象检测框与实际物体位置不匹配排查步骤检查letterbox函数的ratio和(dw,dh)计算是否正确确认坐标还原公式x1 int((box[0] - dw) / ratio) y1 int((box[1] - dh) / ratio)5.3 帧率过低优化建议使用cv2.CAP_DSHOW加速摄像头初始化cap cv2.VideoCapture(0, cv2.CAP_DSHOW)降低显示分辨率cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)关闭imshow的GUI加速cv2.namedWindow(Output, cv2.WINDOW_NORMAL)6. 扩展应用方向这个基础框架可以扩展出许多实用场景智能监控系统结合跟踪算法实现人员计数零售分析统计货架商品摆放情况工业质检检测产品缺陷教育应用开发互动教学工具我在实际部署中发现针对特定场景微调模型能大幅提升效果。例如使用自定义数据集训练后的模型在目标场景下的mAP能提升30%以上。微调建议收集至少500张场景相关图片使用LabelImg等工具标注修改模型最后一层输出类别数冻结骨干网络只训练检测头这个项目最让我惊喜的是它的易用性和性能表现。在Jetson Nano这样的边缘设备上经过优化后也能达到15 FPS的实时性能完全满足大多数应用场景的需求。如果你刚开始接触计算机视觉这会是一个非常好的实践项目。