使用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.pswp.cn/web/72274.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/72274.shtml
英文地址,請注明出處:http://en.pswp.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…