基于树莓派4B的YOLOv5-Lite轻量级目标检测系统部署与迷宫寻宝应用
引言
本文聚焦于在树莓派4B平台部署轻量化目标检测模型YOLOv5-Lite,并将其应用于"迷宫寻宝"智能小车系统。该系统融合计算机视觉、光电传感与路径规划技术,实现对复杂环境的实时感知与自主决策。通过模型压缩与边缘推理优化,使原本依赖高性能GPU的深度学习任务得以在资源受限的嵌入式设备上稳定运行。
模型选型与轻量化设计
YOLOv5-Lite是YOLOv5系列的精简变体,专为边缘设备设计。其核心改进包括:
- 移除Focuss层,以标准卷积替代,提升ONNX导出兼容性
- 简化C3模块结构,减少重复Bottleneck堆叠,降低内存占用
- 采用SPPF(快速空间金字塔池化)替代传统SPP,提升特征提取效率
- 对FPN+PAN结构实施通道剪枝,统一各层特征通道数为96,优化缓存访问模式
- 将PAN中的通道拼接(concat)替换为逐元素叠加(add),减少数据搬运开销
上述优化使模型体积缩减约40%,推理速度提升3倍以上,在保持85%以上原始mAP的前提下,实现5 FPS以上的稳定推理,满足嵌入式实时性需求。
训练与模型转换
训练数据通过树莓派摄像头采集,涵盖三类目标:drrug、glue、prime。使用LabelMe进行标注后,通过脚本将JSON格式转换为YOLO标准的TXT格式(归一化中心坐标+宽高)。
训练配置如下:
python train.py \
--weights v5lite-s.pt \
--cfg models/v5Lite-s.yaml \
--data data/mydata.yaml \
--img-size 320 \
--batch-size 16 \
--device cpu
训练完成后,使用官方export脚本将PyTorch权重转换为ONNX格式:
python export.py --weights best.pt --include onnx
生成的best.onnx模型可在树莓派端直接加载,无需依赖PyTorch环境,仅需安装ONNX Runtime:
pip install onnxruntime==1.16.0 numpy>=1.21.0
边缘推理实现
在树莓派端,推理流程分为预处理、推理、后处理三阶段:
1. 图像预处理
def preprocess(img, model_h=320, model_w=320):
img_resized = cv2.resize(img, (model_w, model_h), interpolation=cv2.INTER_AREA)
img_rgb = cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB)
img_normalized = img_rgb.astype(np.float32) / 255.0
blob = np.expand_dims(img_normalized.transpose(2, 0, 1), axis=0)
return blob
2. ONNX推理
session = ort.InferenceSession("best.onnx", providers=['CPUExecutionProvider'])
outputs = session.run(None, {session.get_inputs()[0].name: blob})[0]
3. 输出解码与NMS
模型输出为三维张量,需进行坐标还原与非极大值抑制:
def decode_outputs(outputs, anchors, strides, nl=3, na=3, model_h=320, model_w=320):
predictions = []
for i in range(nl):
h, w = model_h // strides[i], model_w // strides[i]
grid = np.meshgrid(np.arange(w), np.arange(h))
grid = np.stack(grid, axis=-1).astype(np.float32).reshape(-1, 2)
# 解码中心坐标与宽高
xy = (outputs[i, :, :2] * 2 - 0.5 + grid) * strides[i]
wh = (outputs[i, :, 2:4] * 2) ** 2 * anchors[i]
# 拼接为 [x1, y1, x2, y2, conf, class_probs]
x1y1 = xy - wh / 2
x2y2 = xy + wh / 2
box = np.concatenate([x1y1, x2y2, outputs[i, :, 4:]], axis=1)
predictions.append(box)
return np.concatenate(predictions, axis=0)
def nms_boxes(boxes, scores, class_ids, conf_thres=0.5, iou_thres=0.4):
indices = cv2.dnn.NMSBoxes(boxes, scores, conf_thres, iou_thres)
if len(indices) > 0:
return boxes[indices], scores[indices], class_ids[indices]
return [], [], []
4. 实时视频推理主循环
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret: break
blob = preprocess(frame)
raw_out = session.run(None, {input_name: blob})[0]
# 解码与NMS
det = decode_outputs(raw_out, anchors, strides)
boxes, confs, ids = nms_boxes(det[:, :4], det[:, 4], det[:, 5:].argmax(axis=1))
# 绘制结果
for box, conf, cls_id in zip(boxes, confs, ids):
x1, y1, x2, y2 = map(int, box)
label = f"{labels[cls_id]}: {conf:.2f}"
cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 0), 2)
cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
cv2.imshow("Detection", frame)
if cv2.waitKey(1) == ord('q'): break
在树莓派4B上,该系统可稳定实现4.8–5.3 FPS,满足实时控制需求。
迷宫寻宝系统集成
系统以树莓派4B为核心,集成以下模块:
1. 宝藏地图识别
采用OpenCV实现:
- 灰度化 + Cenny边缘检测
- 轮廓筛选(长宽比≈1:1)定位四个角点
- 透视变换校正图像畸变
- 二值化 + 轮廓外接圆检测定位8个宝藏点
- 左下角色块识别(HSV掩膜)确定队伍颜色
识别结果以JSON格式持久化存储:{ "matrix": [[x1,y1],...], "TC": 1, "count": 2 }
2. 自适应路径规划
采用广度优先搜索(BFS)实现最短路径:
- 将地图建模为0(可通行)/1(障碍)二维数组
- 从当前位置出发,BFS搜索最近未访问宝藏点
- 依据对称规则剪枝:若某点为真宝藏,则其对称点及同象限另一点自动排除
- 路径输出为坐标序列 → 位移向量 → 转向指令序列(直行/左转/右转)
系统最多仅需访问6个点,最少3个点即可完成任务,显著优于全遍历方案。
3. 灰度传感器循迹
采用8路光电传感器阵列,工作原理:
- 白色地面反射率高 → 传感器输出高电平
- 黑色胶带吸收光 → 传感器输出低电平
- 通过读取8通道高低电平组合,计算中心偏移量:offset = (start + end)/2 - 8
引入位置式PID控制:
def pid_control(offset):
P = 1.2
I = 0.02
D = 0.3
integral += offset
derivative = offset - last_offset
output = P * offset + I * integral + D * derivative
left_speed = base_speed - output
right_speed = base_speed + output
set_motor_speed(left_speed, right_speed)
传感器安装高度2cm,实现稳定巡线,抗干扰能力强。
4. 超声波避障与停止
使用HC-SR04模块检测前方障碍物距离:
def measure_distance():
GPIO.output(TRIG, GPIO.HIGH)
time.sleep(0.00001)
GPIO.output(TRIG, GPIO.LOW)
start = time.time()
while GPIO.input(ECHO) == 0: start = time.time()
stop = time.time()
while GPIO.input(ECHO) == 1: stop = time.time()
distance = (stop - start) * 34300 / 2
return distance if distance < 400 else -1
当距离小于15cm时触发停止,用于精准停靠宝藏点。
5. 中断恢复机制
系统重启时自动读取treasure.json,仅对未访问点执行目标检测与路径规划,避免重复识别,提升系统鲁棒性与效率。
系统性能与成果
整套系统在树莓派4B(2GB RAM)上稳定运行,综合性能如下:
- 地图识别耗时:≤45秒
- 目标检测帧率:5.1 FPS
- 路径规划响应:≤100ms
- 循迹精度:±1.5cm
- 平均寻宝时间:78秒(8点迷宫)
相较传统全遍历方案(平均180秒),效率提升57%,且具备断点续跑能力,显著提升竞赛实用性。