使用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) 无人值守管理

  • 应用场景:智能楼宇、写字楼、电影院等无人巡逻区域。
  • 作用:通过 AI 检测+语音提醒,劝阻违规吸烟者。

3. 健康管理与医疗

(1) 吸烟习惯分析

  • 应用场景:医院、戒烟中心、健康管理 APP。
  • 作用:记录个人抽烟次数、时间、环境等数据,帮助戒烟计划制定。

(2) 远程监护

  • 应用场景:养老院、精神病院等特殊场所。
  • 作用:监测老年人或患者是否有吸烟行为,防止健康风险。

4. AI 监控与商业分析

(1) 保险行业

  • 应用场景:人寿保险、健康保险公司。
  • 作用:检测投保人是否吸烟,调整保费或健康建议。

(2) 商场营销

  • 应用场景:便利店、烟草店。
  • 作用:分析吸烟人群的特征,优化营销策略。

5. 技术实现

(1) 计算机视觉

  • 算法:基于 YOLO、Faster R-CNN 等目标检测模型。
  • 数据:训练数据包含吸烟者的手部、嘴部、烟雾等特征。

(2) 传感器检测

  • 红外摄像头:检测烟头的温度特征。
  • 空气质量传感器:监测 PM2.5、尼古丁气味等。

(3) 结合物联网(IoT)

  • 智能监控摄像头:内置 AI 识别系统,边缘计算本地处理数据。
  • 云平台:接收数据并发出警报。

6. 挑战与优化

(1) 误报问题

  • 误将吸烟动作与喝水、拿笔等动作混淆。
  • 解决方案:使用时间序列分析、骨骼检测等方法提高准确率。

(2) 夜间检测难度

  • 夜间光照条件差,普通摄像头难以检测烟雾。
  • 解决方案:采用 红外摄像头 结合 AI 算法提高夜间识别率。

(3) 隐私问题

  • 监控摄像头涉及个人隐私,可能引发争议。
  • 解决方案:使用 边缘计算,仅上传检测结果,不存储人脸信息。



代码实现思路

实现思路

1. 初始化检测模型

  • MediaPipe Hands:用于检测 手部位置,得到手的边界框(bounding box)。
  • dlib 人脸关键点检测:用于检测 嘴部关键点,确定嘴巴的位置。
  • YOLOv3:用于检测 香烟,需要加载权重(yolov3.weights)、配置文件(yolov3.cfg)和类别标签(coco.names)。

2. 读取视频流

  • 通过 cv2.VideoCapture(0) 打开摄像头,逐帧读取视频。

3. 手部检测

  • MediaPipe Hands 处理帧图像,返回检测到的手部 关键点
  • 计算手部的 边界框x_min, y_min, x_max, y_max)。
  • 使用 cv2.rectangle() 画出手部边界框。

4. 香烟检测

  • 通过 YOLOv3 目标检测 识别图像中的物体(包括香烟)。
  • 过滤出 类别为 "cigarette" 的目标,并记录香烟的边界框信息(cigarette_bboxes)。
  • 使用 cv2.rectangle() 画出香烟的位置。

5. 嘴部检测

  • 通过 dlib 人脸检测器 定位人脸,并使用 68个面部关键点 识别嘴部(第48-67号点)。
  • 计算 嘴部中心位置
  • cv2.polylines() 画出嘴部区域。

6. 抽烟行为判断

  • 遍历每只 手的边界框
    1. 判断是否持有香烟(手与香烟的 IOU 交并比 是否超过阈值 0.3)。
    2. 计算手部到嘴部的距离
      • 获取手部中心 (hand_center_x, hand_center_y)
      • 计算与 最近的嘴部中心 的欧几里得距离 distance
    3. 综合判断抽烟行为
      • 手持香烟 且 距离嘴部<100像素,则判定 正在抽烟
      • 手部靠近嘴部<50像素,但未持有香烟,则 可能在抽烟(警告)。

7. 可视化输出

  • 如果检测到 正在抽烟
    • 在屏幕上显示 "WARNING: Active Smoking Detected!"(红色警告)。
  • 如果 疑似抽烟(手靠近嘴但未持烟):
    • 显示 "Potential Smoking!"(黄色提示)。
  • 画出所有检测到的 手部、香烟、嘴部

8. 运行主循环

  • 不断读取摄像头画面,并调用 detect_smoking(frame) 进行检测。
  • 按下 ESC 退出程序。



完整代码

import cv2
import numpy as np
import dlib
import mediapipe as mp# 初始化MediaPipe手部检测
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(max_num_hands=2,min_detection_confidence=0.7,min_tracking_confidence=0.5
)# 初始化dlib人脸检测
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")# 加载YOLOv3模型(需包含自定义训练的香烟类别)
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers().flatten()]with open("coco.names", "r") as f:classes = [line.strip() for line in f.readlines()]def is_holding_cigarette(hand_bbox, cigarette_bboxes, iou_threshold=0.3):"""判断手部是否持有香烟(基于IOU)"""for cig_bbox in cigarette_bboxes:# 计算IOUx1 = max(hand_bbox[0], cig_bbox[0])y1 = max(hand_bbox[1], cig_bbox[1])x2 = min(hand_bbox[2], cig_bbox[2])y2 = min(hand_bbox[3], cig_bbox[3])intersection = max(0, x2 - x1) * max(0, y2 - y1)area_hand = (hand_bbox[2] - hand_bbox[0]) * (hand_bbox[3] - hand_bbox[1])area_cig = (cig_bbox[2] - cig_bbox[0]) * (cig_bbox[3] - cig_bbox[1])iou = intersection / (area_hand + area_cig - intersection)if iou > iou_threshold:return Truereturn Falsedef detect_smoking(frame):# 转换为RGB格式(MediaPipe需要)rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 手部检测hand_bboxes = []results = hands.process(rgb_frame)if results.multi_hand_landmarks:for landmarks in results.multi_hand_landmarks:# 获取手部边界框x_coords = [lm.x * frame.shape[1] for lm in landmarks.landmark]y_coords = [lm.y * frame.shape[0] for lm in landmarks.landmark]x_min, x_max = min(x_coords), max(x_coords)y_min, y_max = min(y_coords), max(y_coords)hand_bboxes.append((x_min, y_min, x_max, y_max))cv2.rectangle(frame, (int(x_min), int(y_min)),(int(x_max), int(y_max)), (255, 0, 0), 2)# YOLOv3香烟检测cigarette_bboxes = []blob = cv2.dnn.blobFromImage(frame, 0.00392, (320, 320), swapRB=True)net.setInput(blob)outs = net.forward(output_layers)for out in outs:for detection in out:scores = detection[5:]class_id = np.argmax(scores)confidence = scores[class_id]if confidence > 0.5 and classes[class_id] == "cigarette":center_x = int(detection[0] * frame.shape[1])center_y = int(detection[1] * frame.shape[0])w = int(detection[2] * frame.shape[1])h = int(detection[3] * frame.shape[0])x = center_x - w // 2y = center_y - h // 2cigarette_bboxes.append((x, y, x + w, y + h))cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)# 人脸关键点检测mouth_positions = []faces = detector(frame)for face in faces:landmarks = predictor(frame, face)mouth_points = [(landmarks.part(i).x, landmarks.part(i).y)for i in range(48, 68)]mouth_center = np.mean(mouth_points, axis=0)mouth_positions.append(mouth_center)# 绘制嘴巴区域cv2.polylines(frame, [np.array(mouth_points, dtype=np.int32)],True, (0, 0, 255), 2)# 综合判断逻辑warning = Falsefor hand in hand_bboxes:# 判断是否持烟holding = is_holding_cigarette(hand, cigarette_bboxes)# 计算手部中心点hand_center = ((hand[0] + hand[2]) / 2, (hand[1] + hand[3]) / 2)# 找最近的人脸min_distance = float('inf')for mouth in mouth_positions:distance = np.sqrt((hand_center[0] - mouth[0]) ** 2 +(hand_center[1] - mouth[1]) ** 2)min_distance = min(min_distance, distance)# 判断条件if holding and min_distance < 100:  # 持烟且距离<100像素warning = Trueelif min_distance < 50:  # 未持烟但手部靠近嘴部cv2.putText(frame, "Potential Smoking!",(int(hand[0]), int(hand[1]) - 10),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2)if warning:cv2.putText(frame, "WARNING: Active Smoking Detected!",(20, 50), cv2.FONT_HERSHEY_SIMPLEX,1, (0, 0, 255), 3, cv2.LINE_AA)return frame# 视频处理主循环
cap = cv2.VideoCapture(0)
while cap.isOpened():ret, frame = cap.read()if not ret:breakframe = cv2.flip(frame, 1)  # 镜像翻转result = detect_smoking(frame)cv2.imshow('Smoking Detection', result)if cv2.waitKey(1) == 27:breakcap.release()
cv2.destroyAllWindows()

效果展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/72274.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF窗口读取、显示、修改、另存excel文件——CAD c#二次开发

效果如下&#xff1a; using System.Data; using System.IO; using System.Windows; using Microsoft.Win32; using ExcelDataReader; using System.Text; using ClosedXML.Excel;namespace IfoxDemo {public partial class SimpleWindow : Window{public SimpleWindow(){Initi…

HarmonyOS NEXT - 电商App实例三( 网络请求axios)

使用axios开发网络请求是一个非常常见的任务&#xff0c;尤其是Web前端开发者&#xff0c;对它非常熟悉。axios是一个基于Promise的HTTP客户端&#xff0c;支持浏览器和Node.js环境&#xff0c;使用简单且功能强大。 在harmonyOS中&#xff0c;如果想使用axios&#xff0c;可以…

生成省市区JSON

省市区 学习记录 https://xiangyuecn.github.io/AreaCity-JsSpider-StatsGov/ package cn.serverx.sx.your;import cn.hutool.core.io.FileUtil; import cn.serverx.sx.your.vo.DistrictNode; import com.alibaba.fastjson2.JSON; import com.google.common.collect.Lists; i…

医疗APP开发如何实现跨机构数据互通

医疗APP开发如何实现跨机构数据互通 在数字化医疗时代,医疗APP开发已成为连接医疗机构、患者和医疗资源的重要桥梁。然而,如何实现跨机构的数据互通,成为医疗APP开发中的一大挑战。本文将探讨如何通过医疗APP开发实现跨机构数据互通,提升医疗服务效率和患者体验。我们将涵…

自定义Linux网络协议的开发与测试

在当今快速发展的技术领域中,定制化网络协议可以为特定的应用场景提供灵活而强大的解决方案。本文将详细介绍如何在Linux系统上开发一个自定义网络协议,并编写相应的用户空间程序进行测试。所有步骤基于2025年3月11日的时间点完成。 开发自定义协议内核模块 定义协议和实现…

PySide(PyQT)的mouseMoveEvent()和hoverMoveEvent()的区别

在 PySide中&#xff0c;mouseMoveEvent 和 hoverMoveEvent 都是用于处理鼠标移动相关操作的事件&#xff0c;但它们之间存在明显的区别&#xff1a; 事件触发条件 • mouseMoveEvent&#xff1a; 当鼠标在对应的图形项&#xff08;如 QGraphicsPixmapItem&#xff09…

级联树SELECTTREE格式调整

步骤&#xff1a; 1、将全部列表设置成Map<Long, List<Obejct>> map的格式&#xff0c;方便查看每个父级对应的子列表&#xff0c;减少循环次数 2、对这个map进行递归&#xff0c;重新进行级联树的集合调整&#xff0c;将子集放置在对应的childs里面。 public Dyna…

详解数据库范式

范式 1. 第一范式&#xff08;1NF&#xff09;2. 第二范式&#xff08;2NF&#xff09;3. 第三范式&#xff08;3NF&#xff09;4. BC范式&#xff08;BCNF&#xff0c;Boyce-Codd Normal Form&#xff09;5. 第四范式&#xff08;4NF&#xff09;6. 第五范式&#xff08;5NF&a…

一窥DeepSeek开源EPLB项目:揭开技术背后的面纱

摘要 在DeepSeek开源DualPipe项目的同一天&#xff0c;EPLB项目也正式对外公开。EPLB&#xff08;Enhanced Pipeline Balancing&#xff09;并非一蹴而就的奇迹&#xff0c;而是经过长时间的研发与优化。该项目旨在通过改进管道平衡机制&#xff0c;提升系统的稳定性和效率。本…

Unity进阶课程【二】Mask 组件的使用 UI遮罩效果以及透明抠图效果

Unity组件讲解 Mask 时隔多年&#xff0c;今天咱们继续进阶课程&#xff0c;这几年变化很大&#xff0c;但是一直还是从事Unity行业&#xff0c;行业虽难&#xff0c;依旧坚持&#xff0c;以后会养成习惯&#xff0c;定期更新&#xff0c;希望小伙伴们监督&#xff0c;有想学习…

汽车无钥匙启动系统不使用传统机械钥匙启动汽车

汽车无钥匙启动系统 定义 汽车无钥匙启动系统&#xff08;Keyless Start System&#xff09;&#xff0c;启动车辆时不用掏拧钥匙&#xff0c;只需把钥匙放在包内或口袋里&#xff0c;按下车内按键或拧动导板即可使发动机点火。它无需插入钥匙&#xff0c;通过点按按键或旋转…

Webpack 和 Vite 的主要区别

Webpack 和 Vite 的主要区别&#xff0c;从构建机制、开发体验、生产优化等多个维度进行对比&#xff1a; 1. 构建机制与速度 Webpack 全量打包&#xff1a;启动时必须分析所有模块依赖关系&#xff0c;进行全量打包&#xff0c;生成 Bundle 文件。项目越大&#xff0c;冷启动时…

【Python】Python 3.11安装教程

一、Python 3.11安装包下载 1. Python 3.11下载与安装 Download Python | Python.org 下载完成包含以下文件&#xff1a; 二、python3.11安装步骤 1.右键以管理员身份运行安装程序。 2.勾选【Add Python…】然后点击【Customize…】。 3.页面点击【Next】。 4.勾选【Install …

如何处理PHP中的编码问题

如何处理PHP中的编码问题 在PHP开发过程中&#xff0c;编码问题是一个常见且棘手的问题。无论是处理用户输入、数据库交互&#xff0c;还是与外部API通信&#xff0c;编码问题都可能导致数据乱码、解析错误甚至安全漏洞。本文将深入探讨PHP中的编码问题&#xff0c;并提供一些…

【毕业论文格式】word分页符后的标题段前间距消失

文章目录 【问题描述】 分页符之后的段落开头&#xff0c;明明设置了标题有段前段后间距&#xff0c;但是没有显示间距&#xff1a; 【解决办法】 选中标题&#xff0c;选择边框 3. 选择段前间距&#xff0c;1~31磅的一个数 结果

【实战ES】实战 Elasticsearch:快速上手与深度实践-附录-3-从ES 7.x到8.x的平滑迁移策略

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 附录-版本升级指南 3-Elasticsearch 7.x 到 8.x 平滑迁移策略指南1. 升级必要性分析1.1 版本特性对比1.2 兼容性评估矩阵 2. 预升级准备清单2.1 环境检查表2.2 数据备份策略 3. 分阶段…

Android,Java,Kotlin 确保线程顺序执行的多种实现方式

在多线程编程中&#xff0c;有时需要确保一个线程必须等待另一个线程执行完毕后再执行。本文将介绍几种常见的方法来实现这一需求&#xff0c;并提供详细的代码示例。 1. 使用 Thread.join() Thread.join() 是最简单直接的方法&#xff0c;它会让当前线程等待目标线程执行完毕…

论文调研 | 一些开源的AI代码生成模型调研及总结【更新于250313】

本文主要介绍主流代码生成模型&#xff0c;总结了基于代码生成的大语言模型&#xff0c;按照时间顺序排列。 在了解代码大语言模型之前&#xff0c;需要了解代码相关子任务 代码生成 文本生成代码(Text to code):根据自然语言描述生成代码 重构代码&#xff08;Refactoring …

【QT】-一文说清楚QT定时器怎么用

在 Qt 中&#xff0c;定时器&#xff08;QTimer&#xff09;是用来定时执行某些任务的非常有用的类。它可以帮助你在指定的时间间隔后重复执行某个函数。常见的用法是启动一个定时器&#xff0c;每过一段时间自动执行某个操作&#xff0c;比如更新 UI、检查状态或发送数据等。 …

iOS OC匹配多个文字修改颜色和字号

1、传入字符串数组&#xff0c;通过NSMutableAttributedString修改匹配文字 可以根据需要搞成匹配单个字符串 - (NSAttributedString *)applyFontSizeToText:(NSString *)text matchStrings:(NSArray<NSString *> *)matchStrings {NSMutableAttributedString *attribut…