Python實戰(zhàn)之手勢識別控制電腦音量
今天給大家?guī)硪粋€OpenCV的實戰(zhàn)小項目——手勢識別控制電腦音量
先上個效果圖:
通過大拇指和食指間的開合距離來調(diào)節(jié)電腦音量,即通過識別大拇指與食指這兩個關鍵點之間的距離來控制電腦音量大小
一、環(huán)境配置
這個項目需要的環(huán)境比較簡單,主要就是opencv和mediapipe庫
import cv2 import mediapipe as mp from ctypes import cast, POINTER from comtypes import CLSCTX_ALL from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume import pyautogui
缺庫的話直接:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 庫名稱
二、代碼介紹
1)初始化mediapipe庫
self.mp_drawing = mp.solutions.drawing_utils self.mp_drawing_styles = mp.solutions.drawing_styles self.mp_hands = mp.solutions.hands
2)獲取電腦音量范圍
devices = AudioUtilities.GetSpeakers() interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None) self.volume = cast(interface, POINTER(IAudioEndpointVolume)) self.volume.SetMute(0, None) self.volume_range = self.volume.GetVolumeRange()
3)利用OpenCV讀取攝像頭視頻流進行顯示
cap = cv2.VideoCapture(0) resize_w = 640 resize_h = 480 while cap.isOpened(): success, image = cap.read() image = cv2.resize(image, (resize_w, resize_h))
4)識別手掌,獲取手掌關鍵點坐標
# 判斷是否有手掌 if results.multi_hand_landmarks: # 遍歷每個手掌 for hand_landmarks in results.multi_hand_landmarks: # 在畫面標注手指 # 解析手指,存入各個手指坐標 landmark_list = [] for landmark_id, finger_axis in enumerate( hand_landmarks.landmark): landmark_list.append([ landmark_id, finger_axis.x, finger_axis.y, finger_axis.z ]) if landmark_list: # 獲取大拇指指尖坐標 thumb_finger_tip = landmark_list[4] thumb_finger_tip_x = math.ceil(thumb_finger_tip[1] * resize_w) thumb_finger_tip_y = math.ceil(thumb_finger_tip[2] * resize_h) # 獲取食指指尖坐標 index_finger_tip = landmark_list[8] index_finger_tip_x = math.ceil(index_finger_tip[1] * resize_w) index_finger_tip_y = math.ceil(index_finger_tip[2] * resize_h) # 獲取中指尖坐標 middle_finger_tip = landmark_list[12] middle_finger_tip_x = math.ceil(middle_finger_tip[1] * resize_w) middle_finger_tip_y = math.ceil(middle_finger_tip[2] * resize_h) # 中指與食指中間點 middle_index_finger_middle_point = (middle_finger_tip_x + index_finger_tip_x) // 2, ( middle_finger_tip_y + index_finger_tip_y) // 2 # print(thumb_finger_tip_x) middle_finger_point = (middle_finger_tip_x, middle_finger_tip_y) index_finger_point = (index_finger_tip_x, index_finger_tip_y) # 畫指尖2點 image = cv2.circle(image, middle_finger_point, 10, (255, 0, 255), -1) image = cv2.circle(image, index_finger_point, 10, (255, 0, 255), -1) image = cv2.circle(image, middle_index_finger_middle_point, 10, (255, 0, 255), -1) # 畫2點連線 image1 = cv2.line(image, middle_finger_point, index_finger_point, (255, 0, 255), 5) # 勾股定理計算長度 middle_index_line_len = math.hypot((middle_finger_tip_x - index_finger_tip_x), (middle_finger_tip_y - index_finger_tip_y))
5)將拇指與食指距離與電腦音量進行關聯(lián)
# 當食指中指距離大于65像素允許調(diào)音量 if middle_index_line_len < 65.0: # 拇指與食指中間點 finger_middle_point = (thumb_finger_tip_x + index_finger_tip_x) // 2, ( thumb_finger_tip_y + index_finger_tip_y) // 2 # print(thumb_finger_tip_x) thumb_finger_point = (thumb_finger_tip_x, thumb_finger_tip_y) index_finger_point = (index_finger_tip_x, index_finger_tip_y) # 畫2點連線 image = cv2.line(image, thumb_finger_point, index_finger_point, (255, 0, 255), 5) # 勾股定理計算長度 line_len = math.hypot((index_finger_tip_x - thumb_finger_tip_x), (index_finger_tip_y - thumb_finger_tip_y)) # 獲取電腦最大最小音量 min_volume = self.volume_range[0] max_volume = self.volume_range[1] # 將指尖長度映射到音量上 vol = np.interp(line_len, [50, 300], [min_volume, max_volume]) # 將指尖長度映射到矩形顯示上 rect_height = np.interp(line_len, [50, 300], [0, 200]) rect_percent_text = np.interp(line_len, [50, 300], [0, 100]) # 設置電腦音量 self.volume.SetMasterVolumeLevel(vol, None) #鎖定調(diào)音量,進行鼠標控制 else: for id, lm in enumerate(hand_landmarks.landmark): # print(id,lm) h, w, c = image.shape cx, cy = int(lm.x * w), int(lm.y * h) # id=手部關鍵點 if id == 0: if cx > dot[0] and cx < dot[2] and cy > dot[1] and cy < dot[3]: x0 = ((cx-dot[0])/(dot[2]-dot[0]))*1920 y0 = ((cy-dot[1])/(dot[3]-dot[1]))*1080 pyautogui.moveTo(x0, y0, duration=0.02) # print(thumb_finger_tip_x) thumb_finger_point = (thumb_finger_tip_x, thumb_finger_tip_y) index_finger_point = (index_finger_tip_x, index_finger_tip_y) # 畫指尖2點 image = cv2.circle(image, thumb_finger_point, 10, (255, 0, 255), -1) image = cv2.circle(image, index_finger_point, 10, (255, 0, 255), -1) image = cv2.circle(image, finger_middle_point, 10, (255, 0, 255), -1) # 畫2點連線 image = cv2.line(image, thumb_finger_point, index_finger_point, (255, 0, 255), 5) # 勾股定理計算長度 line_len = math.hypot((index_finger_tip_x - thumb_finger_tip_x), (index_finger_tip_y - thumb_finger_tip_y)) # 操作 # 左鍵雙擊 if line_len < 20: pyautogui.doubleClick() ms_d = 0
三、使用方式
1)直接運行程序
2)把手掌靠近攝像頭,置于矩形框內(nèi)
3)通過拇指與食指的開合即可調(diào)節(jié)音量
到此這篇關于Python實戰(zhàn)之手勢識別控制電腦音量的文章就介紹到這了,更多相關Python手勢識別控制電腦音量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
淺談Python數(shù)學建模之整數(shù)規(guī)劃
整數(shù)規(guī)劃并不一定是線性規(guī)劃問題的變量取整限制,對于二次規(guī)劃、非線性規(guī)劃問題也有變量取整限制而引出的整數(shù)規(guī)劃。但在數(shù)學建模問題中所說的整數(shù)規(guī)劃,通常是指整數(shù)線性規(guī)劃。整數(shù)規(guī)劃與線性規(guī)劃的差別只是變量的整數(shù)約束。選擇簡單通用的編程方案,讓求解器去處理吧2021-06-06Python常用標準庫詳解(pickle序列化和JSON序列化)
這篇文章主要介紹了Python常用標準庫,主要包括pickle序列化和JSON序列化模塊,通過使用場景分析給大家介紹的非常詳細,需要的朋友可以參考下2022-05-05python數(shù)據(jù)處理之如何選取csv文件中某幾行的數(shù)據(jù)
這篇文章主要給大家介紹了關于python數(shù)據(jù)處理之如何選取csv文件中某幾行的數(shù)據(jù)的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用python具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-09-09Python大數(shù)據(jù)量文本文件高效解析方案代碼實現(xiàn)全過程
在數(shù)據(jù)分析中,有時數(shù)據(jù)源會是超大的文本文件(幾G,或在幾十G),需要從中提取需要的信息,下面這篇文章主要給大家介紹了關于Python大數(shù)據(jù)量文本文件高效解析方案代碼實現(xiàn)的相關資料,需要的朋友可以參考下2022-12-12思考分析Python運算中?a+=b?和?a=a+b是否相等
這篇文章主要為大家介紹了Python運算中a+=b和a=a+b是否相等及原理思考分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04