1. 项目概述:当垃圾桶遇上物联网
去年帮学弟调试这个系统时,我们蹲在宿舍楼下对着智能垃圾桶调试了整整三个通宵。这个看似简单的毕设项目,实际上融合了嵌入式开发、图像识别和云平台三大技术模块。典型的校园场景里,同学们常常站在垃圾桶前犹豫该扔哪个口,而这个系统通过摄像头捕捉垃圾图像,经算法识别后自动开启对应分类的桶盖,同时将投放记录同步到管理后台。
市面上同类产品存在两个痛点:首先是普通红外感应垃圾桶容易误触发,其次是纯视觉方案受光线影响大。我们的方案在树莓派上部署轻量级YOLOv5模型,配合超声波测距模块实现双重校验——只有当物体进入50cm范围内且持续2秒时才会触发识别,实测准确率达到91%以上。整套系统硬件成本控制在300元内,特别适合作为高校物联网专业综合实训项目。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计解析
2.1 硬件选型与成本控制
核心控制器选用树莓派4B而不是更便宜的3B+,主要考虑点在于:
- 需要实时运行目标检测模型(约3TOPS算力需求)
- 同时处理摄像头输入和舵机控制(至少需要2个USB3.0接口)
- 持续运行时的散热要求(实测温度比3B+低15℃)
传感器配置方案经过三次迭代:
- 初版:仅用OV5647摄像头 → 夜间识别率骤降至60%
- 改进版:增加红外补光灯 → 功耗上升导致电源不稳定
- 终版:采用IMX219摄像头(带夜视功能)+ HC-SR04超声波模块 → 实现全天候稳定检测
关键技巧:舵机选用SG90而不是MG996,虽然扭矩较小(1.8kg/cm)但功耗更低,配合PCA9685模块可实现16路PWM控制,方便后续扩展多分类桶。
2.2 软件架构分层设计
系统采用典型的边缘计算架构:
code复制应用层:Flask管理后台(数据可视化)
服务层:MQTT消息中间件(设备状态同步)
算法层:PyTorch模型推理(TensorRT加速)
驱动层:RPi.GPIO控制(硬件接口封装)
特别设计的双缓冲识别机制:
- 预处理线程:将摄像头画面resize到640x640并存入队列
- 推理线程:从队列取帧进行目标检测
- 决策线程:综合最近3次识别结果做投票决策
这种设计使得在树莓派上也能达到8FPS的处理速度,远高于单纯串行处理的2-3FPS。
3. 核心算法实现细节
3.1 数据集构建与增强
自制数据集包含6类校园常见垃圾:
- 可回收:饮料瓶、纸箱
- 厨余:水果皮、剩饭
- 有害:电池、药品
- 其他:纸巾、塑料袋
通过三种方式提升数据多样性:
- 物理增强:不同光照条件下拍摄(正午/傍晚/夜间)
- 数字增强:使用albumentations库做色彩抖动、模糊处理
- 负样本:添加手持物品靠近但未投放的画面
最终构建的数据集规模:
| 类别 | 训练集 | 验证集 | 测试集 |
|---|---|---|---|
| 饮料瓶 | 1200 | 150 | 150 |
| 电池 | 800 | 100 | 100 |
| ... | ... | ... | ... |
| 背景 | 500 | 50 | 50 |
3.2 模型训练与优化
基于YOLOv5s的改进方案:
- 输入端:添加自适应图像增强(AutoAugment)
- Backbone:将Focus模块替换为更高效的Stem模块
- Neck部分:引入BiFPN特征融合
- 输出端:使用SIoU损失函数替代CIoU
训练参数配置示例:
python复制# 使用预训练权重
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
# 冻结前10层参数
for param in model.model[:10].parameters():
param.requires_grad = False
# 自定义优化器配置
optimizer = torch.optim.AdamW([
{'params': model.model[10:].parameters(), 'lr': 0.0001},
{'params': model.head.parameters(), 'lr': 0.0002}
], weight_decay=0.05)
量化部署时发现的问题及解决方案:
- 问题:直接转ONNX后精度下降15%
- 排查:发现PyTorch的Silu激活函数导出异常
- 解决:手动替换为等效的Sigmoid+乘法操作
4. 硬件部署实战记录
4.1 电路连接示意图
主要器件连接关系:
code复制树莓派4B
├─ GPIO12 → 超声波模块Trig
├─ GPIO16 ← 超声波模块Echo
├─ I2C0 → PCA9685(地址0x40)
│ ├─ PWM0 → 舵机1(可回收)
│ └─ PWM1 → 舵机2(厨余)
└─ CSI接口 → 摄像头模块
电源方案选型对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 移动电源供电 | 便携性好 | 持续放电容量衰减快 |
| 5V3A适配器 | 稳定性高 | 需要外接插座 |
| 18650电池组 | 可充电循环使用 | 需要额外保护电路 |
最终选择改装的小米移动电源(支持PD快充),实测可连续工作9小时。
4.2 机械结构设计要点
垃圾桶改造的三个关键位置:
- 开盖角度:经测试55°开启角度最优(平衡开口大小和舵机负荷)
- 防夹手设计:在桶盖边缘添加硅胶缓冲条
- 防水处理:所有电路板喷涂三防漆(特别是厨余垃圾桶)
常见故障排查表:
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 桶盖开启后不闭合 | 限位开关故障 | 更换微动开关或调整安装位置 |
| 频繁误触发 | 超声波模块松动 | 重新固定并校准距离阈值 |
| 管理后台无数据 | MQTT连接断开 | 检查WiFi信号强度及broker状态 |
5. 管理平台开发实录
5.1 后端API设计
采用Flask+SQLite的轻量级方案,主要接口包括:
python复制@app.route('/api/records', methods=['GET'])
def get_records():
# 分页查询投放记录
page = request.args.get('page', 1, type=int)
per_page = 10
records = Record.query.order_by(
Record.timestamp.desc()).paginate(page, per_page)
return jsonify({
'items': [r.to_dict() for r in records.items],
'total': records.total
})
@app.route('/api/stats', methods=['GET'])
def get_stats():
# 获取分类统计信息
today = datetime.now().date()
data = db.session.query(
Record.category,
func.count(Record.id)
).filter(
func.date(Record.timestamp) == today
).group_by(Record.category).all()
return jsonify(dict(data))
性能优化技巧:
- 使用Flask-Caching缓存高频访问的统计接口
- 将SQLite的journal_mode改为WAL提升并发性
- 对时间范围查询添加索引:
CREATE INDEX idx_records_timestamp ON records(timestamp)
5.2 前端数据可视化
使用ECharts实现的三种核心视图:
- 实时监控面板:显示当前各垃圾桶状态(在线/离线/满载)
- 分类统计环图:按小时/天/周维度的投放比例
- 异常检测图表:突增投放量预警(超过平均值的3σ)
一个典型的配置项示例:
javascript复制option = {
tooltip: { trigger: 'item' },
series: [{
type: 'pie',
radius: ['40%', '70%'],
data: [
{ value: 1048, name: '可回收' },
{ value: 735, name: '厨余' },
{ value: 580, name: '有害' },
{ value: 300, name: '其他' }
],
itemStyle: {
borderRadius: 5,
borderColor: '#fff',
borderWidth: 2
}
}]
}
6. 项目扩展方向
在实际部署中我们发现几个有价值的改进点:
- 重量传感器扩展:在桶底加装HX711模块,实现垃圾重量统计
- 满溢检测:使用TOF激光测距模块监测桶内垃圾高度
- 语音提示:通过SYN6288芯片播放分类指引(特别适合老年人)
调试过程中有个有趣的发现:当摄像头安装高度在1.2-1.5米时,对不同身高的用户都有较好的识别角度。这个细节在论文中很少被提及,却是实际部署时影响用户体验的关键因素。
