基于opencv實現(xiàn)手勢控制音量(案例詳解)
基于opencv的手勢控制音量和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類的對象只能使用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:
# 如果存在多個手
for handLms in self.results.multi_hand_landmarks:
if draw:
# 設置連接線等屬性
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 = []
# 每個點的索引和它的像素比例,若知道窗口的寬度和高度可以計算位置
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定義了一個名為 handDetector 的類,用于檢測和跟蹤手部。下面是代碼的詳細分析:
導入庫
cv2: OpenCV 庫,用于圖像處理。mediapipe as mp: 用于多媒體解決方案的庫,在此用于手部檢測。time: 用于時間管理,但在給定的代碼段中未使用。
handDetector 類
初始化方法 __init__
該方法用于初始化 handDetector 類的對象,并設置一些參數(shù)。
mode: 布爾值,控制 MediaPipe 手部解決方案的靜態(tài)圖像模式。默認值為False。maxHands: 最大手部數(shù)量,控制同時檢測的手的數(shù)量。默認值為2。model_complexity: 模型復雜度,有 0、1、2 三個級別。默認值為1。detectionCon: 檢測置信度閾值。默認值為0.5。trackCon: 跟蹤置信度閾值。默認值為0.5。
此外,還創(chuàng)建了 MediaPipe 手部解決方案的實例,并初始化了繪圖工具。
方法 findHands
該方法用于在給定圖像中找到手,并根據(jù)需要繪制手部標記。
img: 輸入圖像。draw: 布爾值,控制是否繪制手部標記。默認值為True。
該方法首先將圖像從 BGR 轉(zhuǎn)換為 RGB,然后處理圖像以找到手部標記。如果找到了手部標記,并且 draw 參數(shù)為 True ,則會在圖像上繪制手部標記和連接線。
方法 findPosition
該方法用于在給定圖像中找到手部標記的位置,并返回一個包含每個標記位置的列表。
img: 輸入圖像。handNum: 手的索引,用于選擇多個檢測到的手中的特定一只。默認值為0。draw: 布爾值,控制是否在圖像上繪制每個標記的圓圈。默認值為True。
該方法遍歷給定手的每個標記,并計算其在圖像中的位置。如果 draw 參數(shù)為 True ,則在每個標記的位置上繪制一個圓圈。
總結
handDetector 類是一個用于檢測和跟蹤手部的工具。它使用了 MediaPipe 的手部解決方案,并提供了在圖像上繪制手部標記和連接線的功能。通過調(diào)用這些方法,你可以在視頻流或靜態(tài)圖像中跟蹤手部,甚至找到特定手部標記的位置。
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)
# 設置攝像頭的寬度
cap.set(3, wCam)
# 設置攝像頭的高度
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:
# 遍歷三個通道
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. 導入必要的庫
- OpenCV (
cv2): 用于圖像處理,例如讀取圖像、轉(zhuǎn)換顏色空間、繪制形狀等。 - NumPy (
np): 用于數(shù)值計算,特別是線性插值。 HandTrackingModule as htm: 導入自定義的手部檢測模塊。math: 提供數(shù)學功能,例如計算兩點間的距離。ctypes,comtypes,pycaw.pycaw: 用于與操作系統(tǒng)的音量控制交互。
2. 初始化參數(shù)和對象
- 攝像頭大小 (
wCam,hCam): 定義攝像頭的寬度和高度。 - 攝像頭 (
cap): 通過 OpenCV 初始化攝像頭,并設置寬度和高度。 - 時間 (
pTime): 用于計算幀率。 - 圖像疊加 (
tiga_img): 讀取一個圖像文件,稍后用于疊加。 - 手部檢測器 (
detector): 使用自定義的手部檢測模塊創(chuàng)建檢測器對象,設置檢測置信度為 0.7。 - 人臉檢測 (
face_Cascade): 加載 OpenCV 的 Haar 級聯(lián)分類器來檢測人臉。 - 音量控制 (
volume): 通過 pycaw 訪問系統(tǒng)的音量控制,獲取音量范圍。
3. 定義圖像疊加函數(shù) overlay_img
該函數(shù)負責將一個圖像疊加到另一個圖像上的特定位置。它遍歷覆蓋圖像的每個像素,并將非透明像素復制到背景圖像的相應位置。
4. 主循環(huán)
在無限循環(huán)中,代碼執(zhí)行以下任務:
a. 人臉檢測和圖像疊加
- 讀取圖像: 從攝像頭捕獲圖像。
- 灰度轉(zhuǎn)換: 將圖像轉(zhuǎn)換為灰度,以便進行人臉檢測。
- 人臉檢測: 使用級聯(lián)分類器檢測人臉。
- 調(diào)整疊加圖像: 根據(jù)人臉大小調(diào)整疊加圖像的大小。
- 疊加圖像: 調(diào)用
overlay_img函數(shù)將圖像疊加到人臉上。
b. 手部檢測和音量控制
- 檢測手部: 調(diào)用
detector.findHands在圖像上檢測并繪制手部。 - 找到位置: 調(diào)用
detector.findPosition獲取手部標記的位置。 - 計算距離: 計算手部標記 4 和 8 之間的距離。
- 繪制形狀: 在這兩個點上繪制圓圈,并在它們之間繪制線條。
- 音量映射: 使用 NumPy 的
np.interp函數(shù)將手的距離映射到音量范圍。 - 設置音量: 調(diào)用
volume.SetMasterVolumeLevel設置系統(tǒng)音量。
c. 可視化
- 繪制音量條: 在圖像上繪制一個表示音量級別的矩形條。
- 計算幀率: 使用當前時間和上一幀的時間計算幀率。
- 繪制幀率: 在圖像上繪制幀率文本。
d. 顯示結果
- 顯示圖像: 使用 OpenCV 的
imshow方法顯示處理后的圖像。 - 等待: 通過 OpenCV 的
waitKey方法等待 1 毫秒,這樣可以實時更新圖像。
總結
這個代碼集成了多個功能:通過攝像頭捕獲圖像,檢測人臉并在人臉上疊加圖像,檢測手部并通過手指之間的距離控制系統(tǒng)音量,然后通過 OpenCV 實時顯示結果。它結合了圖像處理、人臉和手部檢測、系統(tǒng)交互和實時可視化,展示了計算機視覺和人機交互的強大功能。
效果

(B站演示視頻)[https://www.bilibili.com/video/BV1Xu41177Gz/?spm_id_from=333.999.0.0]
到此這篇關于基于opencv的手勢控制音量的文章就介紹到這了,更多相關opencv手勢控制音量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python?OpenCV實現(xiàn)姿態(tài)識別的詳細代碼
這篇文章主要介紹了Python?OpenCV實現(xiàn)姿態(tài)識別的方法,本文通過截圖實例代碼相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02
Python調(diào)整數(shù)組形狀如何實現(xiàn)
這篇文章主要介紹了Python調(diào)整數(shù)組形狀如何實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-12-12
python實現(xiàn)錄制全屏和選擇區(qū)域錄屏功能
這篇文章主要介紹了python實現(xiàn)錄制全屏和選擇區(qū)域錄屏功能,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02

