IT评测·应用市场-qidao123.com

标题: 利用OpenCV和MediaPipe库——吸烟检测(姿态监控) [打印本页]

作者: 九天猎人    时间: 2025-3-14 13:28
标题: 利用OpenCV和MediaPipe库——吸烟检测(姿态监控)

目录
吸烟检测的运用
1. 安全监控
(1) 公共场所禁烟羁系
(2) 工业安全
2. 智能城市与执法
(1) 城市违章吸烟检测
(2) 无人值守管理
3. 健康管理与医疗
(1) 吸烟习惯分析
(2) 远程监护
4. AI 监控与商业分析
(1) 保险行业
(2) 商场营销
5. 技能实现
(1) 盘算机视觉
(2) 传感器检测
(3) 结合物联网(IoT)
6. 挑衅与优化
(1) 误报问题
(2) 夜间检测难度
(3) 隐私问题
代码实现思绪
实现思绪
1. 初始化检测模型
2. 读取视频流
3. 手部检测
4. 香烟检测
5. 嘴部检测
6. 吸烟举动判断
7. 可视化输出
8. 运行主循环
完整代码
效果展示



吸烟检测的运用

1. 安全监控

(1) 公共场所禁烟羁系


(2) 工业安全



2. 智能城市与执法

(1) 城市违章吸烟检测


(2) 无人值守管理



3. 健康管理与医疗

(1) 吸烟习惯分析


(2) 远程监护



4. AI 监控与商业分析

(1) 保险行业


(2) 商场营销



5. 技能实现

(1) 盘算机视觉


(2) 传感器检测


(3) 结合物联网(IoT)



6. 挑衅与优化

(1) 误报问题


(2) 夜间检测难度


(3) 隐私问题





代码实现思绪

实现思绪

1. 初始化检测模型



2. 读取视频流



3. 手部检测



4. 香烟检测



5. 嘴部检测



6. 吸烟举动判断



7. 可视化输出



8. 运行主循环





完整代码

  1. import cv2
  2. import numpy as np
  3. import dlib
  4. import mediapipe as mp
  5. # 初始化MediaPipe手部检测
  6. mp_hands = mp.solutions.hands
  7. hands = mp_hands.Hands(
  8.     max_num_hands=2,
  9.     min_detection_confidence=0.7,
  10.     min_tracking_confidence=0.5
  11. )
  12. # 初始化dlib人脸检测
  13. detector = dlib.get_frontal_face_detector()
  14. predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
  15. # 加载YOLOv3模型(需包含自定义训练的香烟类别)
  16. net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
  17. layer_names = net.getLayerNames()
  18. output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers().flatten()]
  19. with open("coco.names", "r") as f:
  20.     classes = [line.strip() for line in f.readlines()]
  21. def is_holding_cigarette(hand_bbox, cigarette_bboxes, iou_threshold=0.3):
  22.     """判断手部是否持有香烟(基于IOU)"""
  23.     for cig_bbox in cigarette_bboxes:
  24.         # 计算IOU
  25.         x1 = max(hand_bbox[0], cig_bbox[0])
  26.         y1 = max(hand_bbox[1], cig_bbox[1])
  27.         x2 = min(hand_bbox[2], cig_bbox[2])
  28.         y2 = min(hand_bbox[3], cig_bbox[3])
  29.         intersection = max(0, x2 - x1) * max(0, y2 - y1)
  30.         area_hand = (hand_bbox[2] - hand_bbox[0]) * (hand_bbox[3] - hand_bbox[1])
  31.         area_cig = (cig_bbox[2] - cig_bbox[0]) * (cig_bbox[3] - cig_bbox[1])
  32.         iou = intersection / (area_hand + area_cig - intersection)
  33.         if iou > iou_threshold:
  34.             return True
  35.     return False
  36. def detect_smoking(frame):
  37.     # 转换为RGB格式(MediaPipe需要)
  38.     rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
  39.     # 手部检测
  40.     hand_bboxes = []
  41.     results = hands.process(rgb_frame)
  42.     if results.multi_hand_landmarks:
  43.         for landmarks in results.multi_hand_landmarks:
  44.             # 获取手部边界框
  45.             x_coords = [lm.x * frame.shape[1] for lm in landmarks.landmark]
  46.             y_coords = [lm.y * frame.shape[0] for lm in landmarks.landmark]
  47.             x_min, x_max = min(x_coords), max(x_coords)
  48.             y_min, y_max = min(y_coords), max(y_coords)
  49.             hand_bboxes.append((x_min, y_min, x_max, y_max))
  50.             cv2.rectangle(frame, (int(x_min), int(y_min)),
  51.                           (int(x_max), int(y_max)), (255, 0, 0), 2)
  52.     # YOLOv3香烟检测
  53.     cigarette_bboxes = []
  54.     blob = cv2.dnn.blobFromImage(frame, 0.00392, (320, 320), swapRB=True)
  55.     net.setInput(blob)
  56.     outs = net.forward(output_layers)
  57.     for out in outs:
  58.         for detection in out:
  59.             scores = detection[5:]
  60.             class_id = np.argmax(scores)
  61.             confidence = scores[class_id]
  62.             if confidence > 0.5 and classes[class_id] == "cigarette":
  63.                 center_x = int(detection[0] * frame.shape[1])
  64.                 center_y = int(detection[1] * frame.shape[0])
  65.                 w = int(detection[2] * frame.shape[1])
  66.                 h = int(detection[3] * frame.shape[0])
  67.                 x = center_x - w // 2
  68.                 y = center_y - h // 2
  69.                 cigarette_bboxes.append((x, y, x + w, y + h))
  70.                 cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
  71.     # 人脸关键点检测
  72.     mouth_positions = []
  73.     faces = detector(frame)
  74.     for face in faces:
  75.         landmarks = predictor(frame, face)
  76.         mouth_points = [(landmarks.part(i).x, landmarks.part(i).y)
  77.                         for i in range(48, 68)]
  78.         mouth_center = np.mean(mouth_points, axis=0)
  79.         mouth_positions.append(mouth_center)
  80.         # 绘制嘴巴区域
  81.         cv2.polylines(frame, [np.array(mouth_points, dtype=np.int32)],
  82.                       True, (0, 0, 255), 2)
  83.     # 综合判断逻辑
  84.     warning = False
  85.     for hand in hand_bboxes:
  86.         # 判断是否持烟
  87.         holding = is_holding_cigarette(hand, cigarette_bboxes)
  88.         # 计算手部中心点
  89.         hand_center = ((hand[0] + hand[2]) / 2, (hand[1] + hand[3]) / 2)
  90.         # 找最近的人脸
  91.         min_distance = float('inf')
  92.         for mouth in mouth_positions:
  93.             distance = np.sqrt((hand_center[0] - mouth[0]) ** 2 +
  94.                                (hand_center[1] - mouth[1]) ** 2)
  95.             min_distance = min(min_distance, distance)
  96.         # 判断条件
  97.         if holding and min_distance < 100:  # 持烟且距离<100像素
  98.             warning = True
  99.         elif min_distance < 50:  # 未持烟但手部靠近嘴部
  100.             cv2.putText(frame, "Potential Smoking!",
  101.                         (int(hand[0]), int(hand[1]) - 10),
  102.                         cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)
  103.     if warning:
  104.         cv2.putText(frame, "WARNING: Active Smoking Detected!",
  105.                     (20, 50), cv2.FONT_HERSHEY_SIMPLEX,
  106.                     1, (0, 0, 255), 3, cv2.LINE_AA)
  107.     return frame
  108. # 视频处理主循环
  109. cap = cv2.VideoCapture(0)
  110. while cap.isOpened():
  111.     ret, frame = cap.read()
  112.     if not ret:
  113.         break
  114.     frame = cv2.flip(frame, 1)  # 镜像翻转
  115.     result = detect_smoking(frame)
  116.     cv2.imshow('Smoking Detection', result)
  117.     if cv2.waitKey(1) == 27:
  118.         break
  119. cap.release()
  120. cv2.destroyAllWindows()
复制代码

效果展示





免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4