使用 OpenCV 进行抽烟识别是一个典型的计算机视觉应用,通常需要结合目标检测、特征分析和行为判断等步骤。以下是实现这一任务的基本方法和思路:
一、核心技术思路
抽烟识别的关键在于检测两个核心目标:手部 / 手臂动作和烟雾特征,并结合两者的时空关系判断是否为抽烟行为。主要步骤如下:
视频帧捕获与预处理
从摄像头或视频文件中读取帧序列
预处理:灰度化、去噪(高斯模糊)、增强对比度等,提高后续检测准确性
人体 / 手部检测
定位画面中的人体(尤其是上半身)和手部区域,可使用:
传统方法:Haar 级联分类器(适合简单场景);
深度学习方法:YOLO、SSD 等目标检测模型(推荐,精度更高)。
烟雾特征分析
烟雾的视觉特征:颜色(多为灰白色)、动态扩散性、半透明性、边缘模糊等。
分析方法:
颜色空间分析:在 HSV 空间中提取特定颜色范围(烟雾通常在低饱和度区域);
动态变化检测:通过帧差法或光流法检测手部区域附近的动态模糊区域;
形态学操作:通过膨胀 / 腐蚀去除噪声,提取烟雾轮廓。
行为判断
当检测到手部靠近口部且附近存在符合烟雾特征的区域,且该状态持续一定时间(排除误判),则判定为抽烟行为。
二、关键代码实现示例
以下是一个基于 OpenCV 的简单抽烟识别框架(需结合实际模型优化):
import cv2
import numpy as np
# 1. 视频捕获
cap = cv2.VideoCapture(0) # 0表示默认摄像头
# 2. 预处理函数
def preprocess_frame(frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 灰度化
blur = cv2.GaussianBlur(gray, (5, 5), 0) # 高斯去噪
return blur
# 3. 手部检测(示例使用Haar分类器,实际建议用YOLO)
hand_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_hand.xml') # 需要手部数据集训练
# 4. 烟雾检测函数(基于颜色和动态特征)
def detect_smoke(frame, hand_roi):
# 提取手部区域附近的ROI(感兴趣区域)
x, y, w, h = hand_roi
roi = frame[y:y+h+50, x:x+w] # 扩大区域检测烟雾
# 转换到HSV空间,提取低饱和度区域(烟雾特征)
hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
lower_smoke = np.array([0, 0, 50]) # 调整阈值适应场景
upper_smoke = np.array([180, 50, 200])
smoke_mask = cv2.inRange(hsv, lower_smoke, upper_smoke)
# 计算烟雾区域面积
smoke_area = np.sum(smoke_mask) / 255 # 白色像素占比
return smoke_area > 50 # 设定阈值判断是否存在烟雾
# 5. 主循环
smoke_counter = 0 # 连续检测计数器
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 预处理
processed = preprocess_frame(frame)
# 检测手部
hands = hand_cascade.detectMultiScale(processed, 1.1, 5)
# 遍历手部区域,检测烟雾
smoking_detected = False
for (x, y, w, h) in hands:
# 绘制手部框
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
# 检测烟雾
if detect_smoke(frame, (x, y, w, h)):
cv2.putText(frame, "Smoke detected", (x, y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
smoke_counter += 1
smoking_detected = True
else:
smoke_counter = max(0, smoke_counter - 1) # 计数器衰减
# 持续检测到烟雾超过阈值,判定为抽烟
if smoke_counter > 10: # 连续10帧检测到
cv2.putText(frame, "Smoking Behavior!", (50, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3)
# 显示结果
cv2.imshow('Smoking Detection', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
三、优化方向
使用深度学习提升检测精度
用 YOLOv5/YOLOv8 训练专门的烟雾和手部检测模型(需标注抽烟场景数据集);结合姿态估计(如 MediaPipe)判断手部是否靠近口部。
特征融合
结合烟雾的动态特征(如光流向量)和静态特征(颜色、纹理);使用背景减除(如 MOG2 算法)提取运动区域,排除静态干扰。
抗干扰处理
针对光照变化:使用自适应阈值或白平衡校正;
针对相似物体(如白色杯子):增加形状和纹理分析。
四、注意事项
实际应用中需大量标注数据训练模型,否则传统方法易受环境干扰;可结合边缘计算设备(如 Jetson Nano)实现实时检测;抽烟行为的判定需要时间序列分析(非单帧判断),避免误检。
通过上述方法,可以构建一个基础的抽烟识别系统,实际部署时需根据场景进行参数调优和模型训练。