背景与问题
在工厂、建筑工地、电力管线等生产场景中,安全隐患往往具有突发性和隐蔽性。传统人工巡检依赖经验,存在覆盖范围有限、响应滞后、夜晚或恶劣天气下效率低等问题。近年来,随着深度学习与边缘计算的发展,AI视觉识别技术被大量用于安全帽佩戴检测、烟火识别、人员越界告警等场景,但构建一套完整、可落地的智能识别系统仍然面临几个核心挑战:
- 数据采集与标注难:真实场景中的隐患样本少、类别不均衡,需要结合公开数据集与自采数据进行扩增。
- 模型部署链路长:从训练到推理涉及框架转换、服务封装、前后端协作,工程复杂度高。
- 实时性与成本平衡:视频流推送到云端推理会产生带宽和计算成本,需要在边缘端做初筛。
本文给出一种基于“云-边协同”的视觉隐患识别设计,并以安全帽佩戴检测为例,展示从模型选择、训练到部署的完整代码实现。
方案设计
系统整体采用如下分层结构:
摄像头/视频流 -> 边缘端推理服务 -> 告警消息队列 -> 云端管理平台/数据库
- 边缘端:使用NVIDIA Jetson或普通x86工控机运行轻量化YOLOv5s模型,对实时视频流进行抽帧推理。
- 云端:使用阿里云ECS部署Flask/FastAPI服务,接收边缘端上报的告警图片与元数据,并存入OSS或数据库。
- 告警链路:通过Redis Stream或阿里云消息队列进行异步解耦,支持短信、钉钉机器人等通知方式。
在模型层面,我们优先选择YOLOv5,因为它训练简单、部署生态成熟,且模型体积可控。为了提升对“隐患”的召回率,可在训练时使用Mosaic数据增强、自适应锚框计算,并加入背景负样本。
实现步骤
1. 数据准备
以安全帽佩戴检测为例,可以使用开源的SHWD或VOC格式数据。将数据整理为如下目录结构:
dataset/
images/
train/0001.jpg
val/0001.jpg
labels/
train/0001.txt
val/0001.txt
每个标签文件中的每一行格式为:class_id x_center y_center width height(归一化坐标)。类别0表示未佩戴安全帽,类别1表示佩戴安全帽。
2. 模型训练
克隆YOLOv5仓库,修改数据配置文件后即可开始训练。关键代码如下:
git clone https://github.com/ultralytics/yolov5
cd yolov5
pip install -r requirements.txt
数据配置helmet.yaml内容如下:
train: dataset/images/train
val: dataset/images/val
nc: 2
names: ["no_helmet", "helmet"]
启动训练:
python train.py --data helmet.yaml --weights yolov5s.pt --img 640 --batch 32 --epochs 100 --device 0
训练完成后,会生成runs/train/exp/weights/best.pt。为了在边缘环境获得更好性能,可将其导出为TensorRT或ONNX格式。
3. 边缘推理服务
下面是一个基于FastAPI的推理服务示例,它接收图片字节流,返回检测到的目标框和置信度:
import cv2
import torch
import numpy as np
from fastapi import FastAPI, UploadFile, File, HTTPException
from pydantic import BaseModel
# 加载YOLOv5模型
model = torch.hub.load("./", "custom", path="best.pt", source="local")
model.conf = 0.35 # 置信度阈值
model.iou = 0.45 # NMS IoU阈值
app = FastAPI(title="AI Vision Hazard Detector")
class DetectResult(BaseModel):
class_id: int
class_name: str
confidence: float
bbox: list
@app.post("/predict", response_model=list[DetectResult])
async def predict(file: UploadFile = File(...)):
try:
# 读取上传的图片
contents = await file.read()
nparr = np.frombuffer(contents, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
except Exception as e:
raise HTTPException(status_code=400, detail=f"Invalid image: {str(e)}")
# 执行推理
results = model(img, size=640)
detections = []
for *xyxy, conf, cls in results.xyxy[0]:
detections.append(
DetectResult(
class_id=int(cls),
class_name=model.names[int(cls)],
confidence=round(float(conf), 4),
bbox=[round(x, 2) for x in xyxy],
)
)
return detections
在上述代码中,torch.hub.load通过本地路径加载训练好的权重。FastAPI提供异步接口,能够自动处理并发请求。将服务运行在边缘设备上后,可以通过uvicorn predict_server:app --host 0.0.0.0 --port 8080启动。
4. 云上存储与告警
检测到“未佩戴安全帽”的目标时,边缘端调用云上API上报事件。云上服务会将图片和元数据写入OSS和数据库,并触发通知。示例代码如下:
# 边缘端上报(简化版)
import requests
url = "https://your-ecs-api.example.com/report_event"
payload = {
"device_id": "CAM-001",
"timestamp": 1699999999,
"class_name": "no_helmet",
"confidence": 0.92,
"bbox": [100, 80, 240, 360],
"image": "base64_or_oss_url",
}
requests.post(url, json=payload)
云端Flask接收后可通过钉钉机器人发送告警,这里不再展开。
关键点说明
- 模型选择:YOLOv5s在CPU上单帧推理约200-300ms,在Jetson Xavier NX上可达到约30-40ms。如果对速度要求更高,可改用YOLOv8n或NanoDet。
- 类不均衡处理:如果“未戴安全帽”样本过少,可使用Focal Loss或对真实负样本进行过采样。
- 视频抽帧策略:摄像头场景下建议每秒抽取2帧,避免重复告警;可结合跟踪算法(如ByteTrack)对同一目标去重。
- 模型部署:不要在生产环境中直接使用
torch.hub.load,应使用ONNX Runtime或TensorRT进行推理,减少依赖并提升性能。 - 数据隐私:涉及人脸或人员信息的图片,上报前需要做脱敏处理,并设置OSS私有读权限。
在阿里云上的落地建议
- 弹性计算:使用阿里云ECS(如g7系列)部署模型训练环境,按需选择GPU规格(如V100或A10)。训练完成后释放资源,节约成本。
- 对象存储:将训练数据和告警图片保存到OSS,配合生命周期规则自动归档冷数据。
- 消息服务:大量边缘节点产生的事件流可接入阿里云消息队列RocketMQ或Kafka,实现削峰填谷。
- 容器化部署:将推理服务打包成Docker镜像,部署到ACK或边缘节点,便于版本升级。
注意事项
- 版本兼容:YOLOv5仓库更新频繁,训练与推理环境需要固定版本,建议用requirements.txt锁定依赖。
- 内存泄漏:连续长时间推理时,需及时释放显存或内存中的中间结果,可定期重启服务。
- 告警风暴:设置告警冷却时间(如同一摄像头5分钟内只发送一条通知),避免轰炸管理员。
- 光照变化:模型在强逆光、夜间场景下容易误检,需要在训练数据中加入不同光照的样本,或使用图像增强预处理。
总结
本文从实际生产安全问题出发,设计并实现了基于AI视觉的隐患识别系统。通过公开数据集训练YOLOv5模型,使用FastAPI封装推理接口,再结合云上资源实现事件存储与告警,形成了从数据到服务的闭环。这套方案可以快速扩展到化工、电力、交通等多类场景。在落地时,需要重点考虑模型体积、推理延迟和告警治理等工程化问题,同时善用云计算平台提供的弹性与存储能力,才能实现真正高效、稳定的视觉隐患识别系统。