基于opencv實(shí)現(xiàn)手勢(shì)控制音量(案例詳解)
基于opencv的手勢(shì)控制音量和ai換臉
HandTrackingModule.py
import cv2 import mediapipe as mp import time class handDetector(): def __init__(self, mode = False, maxHands = 2, model_complexity = 1, detectionCon = 0.5, trackCon = 0.5): self.mode = mode self.maxHands = maxHands self.model_complexity = model_complexity self.detectionCon = detectionCon self.trackCon = trackCon self.mpHands = mp.solutions.hands self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.model_complexity, self.detectionCon, self.trackCon) self.mpDraw = mp.solutions.drawing_utils def findHands(self, img, draw = True): # Hand類的對(duì)象只能使用RGB圖像 imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) self.results = self.hands.process(imgRGB) # print(results.multi_hand_landmarks) # 如果存在手 if self.results.multi_hand_landmarks: # 如果存在多個(gè)手 for handLms in self.results.multi_hand_landmarks: if draw: # 設(shè)置連接線等屬性 self.connection_drawing_spec = self.mpDraw.DrawingSpec(color=(0, 255, 0), thickness=2) # 繪制 self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS, connection_drawing_spec=self.connection_drawing_spec) return img def findPosition(self, img, handNum=0, draw=True): lmList = [] # 每個(gè)點(diǎn)的索引和它的像素比例,若知道窗口的寬度和高度可以計(jì)算位置 if self.results.multi_hand_landmarks: myHand = self.results.multi_hand_landmarks[handNum] for id, lm in enumerate(myHand.landmark): # print(id, lm) h, w, c = img.shape cx, cy = int(lm.x * w), int(lm.y * h) # print(id, cx, cy) lmList.append([id, cx, cy]) if draw: cv2.circle(img, (cx, cy), 7, (255, 0, 0), cv2.FILLED) # 繪制每一只手 return lmList
定義了一個(gè)名為 handDetector
的類,用于檢測(cè)和跟蹤手部。下面是代碼的詳細(xì)分析:
導(dǎo)入庫(kù)
cv2
: OpenCV 庫(kù),用于圖像處理。mediapipe as mp
: 用于多媒體解決方案的庫(kù),在此用于手部檢測(cè)。time
: 用于時(shí)間管理,但在給定的代碼段中未使用。
handDetector
類
初始化方法 __init__
該方法用于初始化 handDetector
類的對(duì)象,并設(shè)置一些參數(shù)。
mode
: 布爾值,控制 MediaPipe 手部解決方案的靜態(tài)圖像模式。默認(rèn)值為False
。maxHands
: 最大手部數(shù)量,控制同時(shí)檢測(cè)的手的數(shù)量。默認(rèn)值為2
。model_complexity
: 模型復(fù)雜度,有 0、1、2 三個(gè)級(jí)別。默認(rèn)值為1
。detectionCon
: 檢測(cè)置信度閾值。默認(rèn)值為0.5
。trackCon
: 跟蹤置信度閾值。默認(rèn)值為0.5
。
此外,還創(chuàng)建了 MediaPipe 手部解決方案的實(shí)例,并初始化了繪圖工具。
方法 findHands
該方法用于在給定圖像中找到手,并根據(jù)需要繪制手部標(biāo)記。
img
: 輸入圖像。draw
: 布爾值,控制是否繪制手部標(biāo)記。默認(rèn)值為True
。
該方法首先將圖像從 BGR 轉(zhuǎn)換為 RGB,然后處理圖像以找到手部標(biāo)記。如果找到了手部標(biāo)記,并且 draw
參數(shù)為 True
,則會(huì)在圖像上繪制手部標(biāo)記和連接線。
方法 findPosition
該方法用于在給定圖像中找到手部標(biāo)記的位置,并返回一個(gè)包含每個(gè)標(biāo)記位置的列表。
img
: 輸入圖像。handNum
: 手的索引,用于選擇多個(gè)檢測(cè)到的手中的特定一只。默認(rèn)值為0
。draw
: 布爾值,控制是否在圖像上繪制每個(gè)標(biāo)記的圓圈。默認(rèn)值為True
。
該方法遍歷給定手的每個(gè)標(biāo)記,并計(jì)算其在圖像中的位置。如果 draw
參數(shù)為 True
,則在每個(gè)標(biāo)記的位置上繪制一個(gè)圓圈。
總結(jié)
handDetector
類是一個(gè)用于檢測(cè)和跟蹤手部的工具。它使用了 MediaPipe 的手部解決方案,并提供了在圖像上繪制手部標(biāo)記和連接線的功能。通過調(diào)用這些方法,你可以在視頻流或靜態(tài)圖像中跟蹤手部,甚至找到特定手部標(biāo)記的位置。
VolumeHandControl.py
import cv2 import time import numpy as np import HandTrackingModule as htm import math from ctypes import cast, POINTER from comtypes import CLSCTX_ALL from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume wCam, hCam = 640, 480 cap = cv2.VideoCapture(0) # 設(shè)置攝像頭的寬度 cap.set(3, wCam) # 設(shè)置攝像頭的高度 cap.set(4, hCam) pTime = 0 tiga_img = cv2.imread("tiga.jpg", cv2.IMREAD_UNCHANGED) detector = htm.handDetector(detectionCon=0.7) face_Cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml") devices = AudioUtilities.GetSpeakers() interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None) volume = cast(interface, POINTER(IAudioEndpointVolume)) # volume.GetMute() # volume.GetMasterVolumeLevel() # 音量范圍 volRange = volume.GetVolumeRange() print(volRange) # 最小音量 minVol = volRange[0] # 最大音量 maxVol = volRange[1] vol = 0 volBar = 400 volPer = 0 def overlay_img(img, img_over, img_over_x, img_over_y): # 背景圖像高寬 img_w, img_h, img_c = img.shape # 覆蓋圖像高寬通道數(shù) img_over_h, img_over_w, img_over_c = img_over.shape # 轉(zhuǎn)換成4通道 if img_over_c == 3: img_over = cv2.cvtColor(img_over, cv2.COLOR_BGR2BGRA) # 遍歷列 for w in range(0, img_over_w): #遍歷行 for h in range(0, img_over_h): if img_over[h, w, 3] != 0: # 遍歷三個(gè)通道 for c in range(0, 3): x = img_over_x + w y = img_over_y + h if x >= img_w or y >= img_h: break img[y-40, x, c] = img_over[h, w, c] return img while True: success, img = cap.read() gray_frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) height, width, channel = img.shape faces = face_Cascade.detectMultiScale(gray_frame, 1.15, 5) for (x, y, w, h) in faces: gw = w gh = int(height * w / width) tiga_img = cv2.resize(tiga_img, (gw, gh+gh)) print(gw, gh) if 0 <= x < img.shape[1] and 0 <= y < img.shape[0]: overlay_img(img, tiga_img, x, y) img = detector.findHands(img) lmList = detector.findPosition(img, draw=False) if len(lmList) != 0: # print(lmList[4], lmList[8]) x1, y1 = lmList[4][1], lmList[4][2] x2, y2 = lmList[8][1], lmList[8][2] cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED) cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED) cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 3) cx, cy = (x1+x2)//2, (y1+y2)//2 cv2.circle(img, (cx, cy), 15, (255, 0, 255), cv2.FILLED) length = math.hypot(x2 - x1, y2 - y1) print(length) # Hand rang 130 25 # Vomume Range -65 0 vol = np.interp(length, [25, 175], [minVol, maxVol]) volBar = np.interp(length, [25, 175], [400, 150]) volPer = np.interp(length, [25, 175], [0, 100]) print(int(length), vol) volume.SetMasterVolumeLevel(vol, None) if length<25: cv2.circle(img, (cx, cy), 15, (0, 255, 0), cv2.FILLED) cv2.rectangle(img, (50, 150), (85, 400), (255, 0, 0), 3) cv2.rectangle(img, (50, int(volBar)), (85, 400), (255, 0, 0), cv2.FILLED) cv2.putText(img, f'{int(volPer)} %', (40, 450), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 3) cTime = time.time() fps = 1/(cTime - pTime) pTime = cTime cv2.putText(img, f'FPS:{int(fps)}', (40, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 3) cv2.imshow("img", img) cv2.waitKey(1)
1. 導(dǎo)入必要的庫(kù)
- OpenCV (
cv2
): 用于圖像處理,例如讀取圖像、轉(zhuǎn)換顏色空間、繪制形狀等。 - NumPy (
np
): 用于數(shù)值計(jì)算,特別是線性插值。 HandTrackingModule as htm
: 導(dǎo)入自定義的手部檢測(cè)模塊。math
: 提供數(shù)學(xué)功能,例如計(jì)算兩點(diǎn)間的距離。ctypes
,comtypes
,pycaw.pycaw
: 用于與操作系統(tǒng)的音量控制交互。
2. 初始化參數(shù)和對(duì)象
- 攝像頭大小 (
wCam
,hCam
): 定義攝像頭的寬度和高度。 - 攝像頭 (
cap
): 通過 OpenCV 初始化攝像頭,并設(shè)置寬度和高度。 - 時(shí)間 (
pTime
): 用于計(jì)算幀率。 - 圖像疊加 (
tiga_img
): 讀取一個(gè)圖像文件,稍后用于疊加。 - 手部檢測(cè)器 (
detector
): 使用自定義的手部檢測(cè)模塊創(chuàng)建檢測(cè)器對(duì)象,設(shè)置檢測(cè)置信度為 0.7。 - 人臉檢測(cè) (
face_Cascade
): 加載 OpenCV 的 Haar 級(jí)聯(lián)分類器來檢測(cè)人臉。 - 音量控制 (
volume
): 通過 pycaw 訪問系統(tǒng)的音量控制,獲取音量范圍。
3. 定義圖像疊加函數(shù) overlay_img
該函數(shù)負(fù)責(zé)將一個(gè)圖像疊加到另一個(gè)圖像上的特定位置。它遍歷覆蓋圖像的每個(gè)像素,并將非透明像素復(fù)制到背景圖像的相應(yīng)位置。
4. 主循環(huán)
在無限循環(huán)中,代碼執(zhí)行以下任務(wù):
a. 人臉檢測(cè)和圖像疊加
- 讀取圖像: 從攝像頭捕獲圖像。
- 灰度轉(zhuǎn)換: 將圖像轉(zhuǎn)換為灰度,以便進(jìn)行人臉檢測(cè)。
- 人臉檢測(cè): 使用級(jí)聯(lián)分類器檢測(cè)人臉。
- 調(diào)整疊加圖像: 根據(jù)人臉大小調(diào)整疊加圖像的大小。
- 疊加圖像: 調(diào)用
overlay_img
函數(shù)將圖像疊加到人臉上。
b. 手部檢測(cè)和音量控制
- 檢測(cè)手部: 調(diào)用
detector.findHands
在圖像上檢測(cè)并繪制手部。 - 找到位置: 調(diào)用
detector.findPosition
獲取手部標(biāo)記的位置。 - 計(jì)算距離: 計(jì)算手部標(biāo)記 4 和 8 之間的距離。
- 繪制形狀: 在這兩個(gè)點(diǎn)上繪制圓圈,并在它們之間繪制線條。
- 音量映射: 使用 NumPy 的
np.interp
函數(shù)將手的距離映射到音量范圍。 - 設(shè)置音量: 調(diào)用
volume.SetMasterVolumeLevel
設(shè)置系統(tǒng)音量。
c. 可視化
- 繪制音量條: 在圖像上繪制一個(gè)表示音量級(jí)別的矩形條。
- 計(jì)算幀率: 使用當(dāng)前時(shí)間和上一幀的時(shí)間計(jì)算幀率。
- 繪制幀率: 在圖像上繪制幀率文本。
d. 顯示結(jié)果
- 顯示圖像: 使用 OpenCV 的
imshow
方法顯示處理后的圖像。 - 等待: 通過 OpenCV 的
waitKey
方法等待 1 毫秒,這樣可以實(shí)時(shí)更新圖像。
總結(jié)
這個(gè)代碼集成了多個(gè)功能:通過攝像頭捕獲圖像,檢測(cè)人臉并在人臉上疊加圖像,檢測(cè)手部并通過手指之間的距離控制系統(tǒng)音量,然后通過 OpenCV 實(shí)時(shí)顯示結(jié)果。它結(jié)合了圖像處理、人臉和手部檢測(cè)、系統(tǒng)交互和實(shí)時(shí)可視化,展示了計(jì)算機(jī)視覺和人機(jī)交互的強(qiáng)大功能。
效果
(B站演示視頻)[https://www.bilibili.com/video/BV1Xu41177Gz/?spm_id_from=333.999.0.0]
到此這篇關(guān)于基于opencv的手勢(shì)控制音量的文章就介紹到這了,更多相關(guān)opencv手勢(shì)控制音量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python爬蟲之驗(yàn)證碼篇3-滑動(dòng)驗(yàn)證碼識(shí)別技術(shù)
本篇涉及到的驗(yàn)證碼為滑動(dòng)驗(yàn)證碼,不同于極驗(yàn)證,本驗(yàn)證碼難度略低,需要的將滑塊拖動(dòng)到矩形區(qū)域右側(cè)即可完成。對(duì)python爬蟲滑動(dòng)驗(yàn)證碼識(shí)別技術(shù)感興趣的朋友跟隨小編一起看看吧2019-04-04Python?OpenCV實(shí)現(xiàn)姿態(tài)識(shí)別的詳細(xì)代碼
這篇文章主要介紹了Python?OpenCV實(shí)現(xiàn)姿態(tài)識(shí)別的方法,本文通過截圖實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02Python調(diào)整數(shù)組形狀如何實(shí)現(xiàn)
這篇文章主要介紹了Python調(diào)整數(shù)組形狀如何實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12Django--權(quán)限Permissions的例子
今天小編就為大家分享一篇Django--權(quán)限Permissions的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-08-08python實(shí)現(xiàn)錄制全屏和選擇區(qū)域錄屏功能
這篇文章主要介紹了python實(shí)現(xiàn)錄制全屏和選擇區(qū)域錄屏功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02python點(diǎn)擊鼠標(biāo)獲取坐標(biāo)(Graphics)
這篇文章主要為大家詳細(xì)介紹了python點(diǎn)擊鼠標(biāo)獲取坐標(biāo),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08