?本項目是使用了谷歌開源的框架mediapipe,里面有非常多的模型提供給我們使用,例如面部檢測,身體檢測,手部檢測等。
手勢識別系列文章
1.opencv實現手部追蹤(定位手部關鍵點)
2.opencv實戰項目 實現手勢跟蹤并返回位置信息(封裝調用)
3.手勢識別-手勢音量控制(opencv)
4.opencv實戰項目 手勢識別-手勢控制鼠標
未完待續...
?代碼需要用到opencv? ?HandTraqckModule模塊? ?mediapipe模塊和一個音量控制模塊
AndreMiras/pycaw: Python Core Audio Windows Library (github.com)?音量控制模塊的作者,有興趣可以了解
手部追蹤模塊來自前期的我們實戰內容opencv 實現手勢跟蹤并返回位置信息(封裝調用)_陳子邇的博客-CSDN博客
下面給大家詳細說一下代碼
import cv2
import time
import numpy as np
from HandTraqckModule import *
import math
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
這些行導入了所需的庫和模塊:
cv2
: OpenCV 庫,用于圖像處理和顯示。time
: Python 標準庫,用于處理時間操作。numpy
: 數值計算庫,用于插值計算。HandTraqckModule
: 自定義的手部追蹤模塊(你的代碼中似乎有個拼寫錯誤,正確的應該是HandTrackModule
)。math
: Python 標準庫,用于數學計算。comtypes
: 用于處理 COM 接口的庫。pycaw
: 用于訪問 Windows 音頻控制接口的庫。-
devices = AudioUtilities.GetSpeakers() interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None) volume = interface.QueryInterface(IAudioEndpointVolume) volRange = volume.GetVolumeRange() minVol = volRange[0] maxVol = volRange[1]
-
這部分代碼獲取了默認音頻輸出設備的信息,并通過
pycaw
庫設置了音量范圍、最小音量和最大音量。 -
wCam, hCam = 1280, 720 cap = cv2.VideoCapture(0) cap.set(3, wCam) cap.set(4, hCam)
這里設置了攝像頭的分辨率,并通過 OpenCV 打開攝像頭。
pTime = 0
detector = handDetector(detectionCon=0.7)
初始化了上一幀的時間 pTime
,并創建了 handDetector
類的實例 detector
,設置了手勢檢測的置信度閾值為 0.7。
while True:success, img = cap.read()img = detector.findHands(img)lmList = detector.findPosition(img, draw=False)if len(lmList) != 0:# 從手部標記點列表中獲取兩個指尖的坐標x1, y1 = lmList[4][1], lmList[4][2]x2, y2 = lmList[8][1], lmList[8][2]cx, cy = (x1 + x2) // 2, (y1 + y2) // 2# 繪制手勢標記和連接線cv2.circle(img, (x1, y1), 15, (255, 255, 0), cv2.FILLED)cv2.circle(img, (x2, y2), 15, (255, 0, 0), cv2.FILLED)cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 3)cv2.circle(img, (cx, cy), 10, (255, 255, 0), cv2.FILLED)# 計算手勢長度length = math.hypot(x2 - x1, y2 - y1)# 映射手勢長度到音量范圍vol = np.interp(length, [10, 230], [minVol, maxVol])print(int(length), int(vol))# 設置系統音量volume.SetMasterVolumeLevel(vol, None)# 如果手勢長度小于一定閾值,繪制一個圓圈表示手勢過小if length < 50:cv2.circle(img, (cx, cy), 15, (255, 100, 100), cv2.FILLED)cTime = time.time()fps = 1 / (cTime - pTime)pTime = cTime# 繪制幀率信息cv2.putText(img, f'FPS:{int(fps)}', (40, 40), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 0), 3)# 顯示圖像cv2.imshow('img', img)cv2.waitKey(1)
這部分代碼是主要的處理循環,它會不斷地從攝像頭捕獲圖像,然后使用 detector
對象進行手部檢測和標記繪制。隨后,通過手指標記點的坐標計算手勢的長度,并將這個長度映射到音量范圍,然后設置系統音量。如果手勢長度小于閾值,會在圖像上繪制一個圓圈來表示手勢過小。最后,還會繪制幀率信息并顯示圖像。
下面附上全部代碼
總體代碼
import cv2
import time
import numpy as np
from HandTraqckModule import *
import math
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume# 獲取默認音頻輸出設備
devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = interface.QueryInterface(IAudioEndpointVolume)
# 獲取音量范圍
volRange = volume.GetVolumeRange()
minVol = volRange[0]
maxVol = volRange[1]# 設置攝像頭分辨率
wCam, hCam = 1280, 720# 打開攝像頭
cap = cv2.VideoCapture(0)
cap.set(3, wCam)
cap.set(4, hCam)pTime = 0
detector = handDetector(detectionCon=0.7)while True:success, img = cap.read()img = detector.findHands(img)lmList = detector.findPosition(img, draw=False)if len(lmList) != 0:x1, y1 = lmList[4][1], lmList[4][2]x2, y2 = lmList[8][1], lmList[8][2]cx, cy = (x1 + x2) // 2, (y1 + y2) // 2# 繪制手勢標記和連接線cv2.circle(img, (x1, y1), 15, (255, 255, 0), cv2.FILLED)cv2.circle(img, (x2, y2), 15, (255, 0, 0), cv2.FILLED)cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 3)cv2.circle(img, (cx, cy), 10, (255, 255, 0), cv2.FILLED)# 計算手勢長度length = math.hypot(x2 - x1, y2 - y1)# 映射手勢長度到音量范圍vol = np.interp(length, [10, 230], [minVol, maxVol])print(int(length), int(vol))# 設置系統音量volume.SetMasterVolumeLevel(vol, None)# 如果手勢長度小于一定閾值,繪制一個圓圈表示手勢過小if length < 50:cv2.circle(img, (cx, cy), 15, (255, 100, 100), cv2.FILLED)cTime = time.time()fps = 1 / (cTime - pTime)pTime = cTime# 繪制幀率信息cv2.putText(img, f'FPS:{int(fps)}', (40, 40), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 0), 3)# 顯示圖像cv2.imshow('img', img)cv2.waitKey(1)