赞
踩
今天给大家带来一个OpenCV的实战小项目——手势识别控制电脑音量
先上个效果图:
通过大拇指和食指间的开合距离来调节电脑音量,即通过识别大拇指与食指这两个关键点之间的距离来控制电脑音量大小
这个项目需要的环境比较简单,主要就是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 库名称
还不会配置环境的朋友,请看我环境配置系列的三篇文章:
Python环境配置系列—第二篇:Pycharm与Anaconda的完美配合
Python环境配置系列—第三篇:pip国内源快速安装opencv,pyqt5,tensorflow等
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: # 在画面标注手指 self.mp_drawing.draw_landmarks( image, hand_landmarks, self.mp_hands.HAND_CONNECTIONS, self.mp_drawing_styles.get_default_hand_landmarks_style(), self.mp_drawing_styles.get_default_hand_connections_style()) # 解析手指,存入各个手指坐标 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)将拇指与食指距离与电脑音量进行关联
# 当食指中指距离大于65像素允许调音量 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.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)) # 获取电脑最大最小音量 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) #锁定调音量,进行鼠标控制 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)把手掌靠近摄像头,置于矩形框内
3)通过拇指与食指的开合即可调节音量
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。