如何使用Python和Pycharm创建一个手势音量控制器

368 阅读7分钟

使用Python和Pycharm创建一个手势音量控制器

本教程将讨论如何使用Python来跟踪手势,以及如何创建一个手势音量控制器。

在本教程结束时,你将能够使用你的手指并将计算机的音量调整到你满意的程度。

前提条件

要跟上本教程,你需要。

  • 熟悉Python编程语言。
  • 在你的电脑上安装Pycharm

推荐人的手图像

hand

上面的图片显示了MediaPipe用来指代手的不同点的数字。本教程将使用点4 和点8 ,它们分别是拇指和食指。

创建一个手势音量控制器

设置

首先,我们要准备我们的工作空间。启动Pycharm应用程序。点击创建一个新的项目。

Pycharm

在接下来出现的窗口中点击创建按钮。

我们需要安装我们将在项目中使用的库。

numpy 将帮助我们处理数组。要安装它,打开终端并运行以下命令。

pip install numpy

对其他库重复同样的过程。

pip install opencv-python

我们将把这个库作为cv2 。我们将用它来捕捉使用网络摄像头的图像,并将其转换为RGB

pip install mediapipe

它是一个由谷歌开发的开源库。我们用它来进行人脸和手势识别。在本教程中,我们将把它用于手势识别。

pip install pycaw

我们将需要这个库来访问设备的扬声器和它的主音量。

pip install python-math

我们将使用这个库,用斜线找到点号4 (拇指)和点号8 (食指)之间的距离。

pip install gpib-ctypes, comtypes

pycaw Ctypes 提供 语言兼容的数据类型。 基于C Comtypes ctypes FFI(外国函数接口)库。

现在,让我们开始编码。在pycharm自动为你创建的main.py 文件中,键入以下代码。

第1步:导入我们需要的库

import cv2
import mediapipe as mp
from math import hypot
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
import numpy as np

在上面的代码段中,我们导入我们在项目中安装的每个库。

cap = cv2.VideoCapture(0) 

然后我们从电脑的主摄像头获取视频输入。如果你使用的是其他摄像头,请将数字0 ,替换为你所使用的摄像头的数字。

第2步:检测、初始化和配置双手

mpHands = mp.solutions.hands
hands = mpHands.Hands()
mpDraw = mp.solutions.drawing_utils

在上面的代码中,我们正在调用mediapipe 手部模块,从我们的主摄像头得到的视频输入中检测手部。然后MpHands.Hands() ,完成对检测到的手部的初始化和配置。最后我们使用mp.solutions.drawing_utils ,在检测到的手上画出连接地标

第3步:使用pycaw访问说话者

devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))

这些是我们需要的初始化,以使pycaw 顺利地运行。开发者将这个库与初始化一起提供。我们不打算改变任何东西。

第4步:找到最小和最大体积之间的体积范围

volMin, volMax = volume.GetVolumeRange()[:2]

上面的代码找到了最小和最大音量之间的音量范围。我们把它放在while循环之外,因为我们只需要找到一次体积范围。

第5步:从我们的相机捕捉图像并将其转换为RGB图像

while True:
    success, img = cap.read()
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    results = hands.process(imgRGB)

上面的代码检查我们所指定的相机是否工作。如果它能工作,我们将捕获一个图像。然后我们将图像转换为RGB ,并完成图像的处理。

我们现在需要检查我们捕获的图像中是否有多只手。

第6步:检查我们的输入中是否有多只手

lmList = []
if results.multi_hand_landmarks: 

这段代码创建了一个空列表,它将存储由mediapipe 手模块检测到的手的元素列表,即手的点数。它还会检查输入是否有多只手。

我们现在将创建一个for循环来处理输入中的每一只手。

第7步:创建一个for循环来操作每一只手

for handlandmark in results.multi_hand_landmarks:
    for id, lm in enumerate(handlandmark.landmark):
        h, w, c = img.shape
        cx, cy = int(lm.x * w), int(lm.y * h)
        lmList.append([id, cx, cy]) 
    mpDraw.draw_landmarks(img, handlandmark, mpHands.HAND_CONNECTIONS)
  • 在上面的代码中,我们使用第一个for循环来与结果中的每只手进行交互。我们使用第二个for循环来获取每只手的地标id (ID号码)和lm (地标信息)。地标信息将给我们提供xy 的坐标。id号是分配给各个手部点的数字。

  • h, w, c = img.shape检验:这行代码检验我们图像的高度、宽度和通道。这将给我们提供图像的宽度和高度。

  • cx, cy = int(lm.x * w), int(lm.y * h)这一行代码将找到我们图像的中心位置。我们将通过将lm.x乘以宽度并将得到的值赋给cx 。然后将lm.y 乘以高度并将得到的值赋给cylm 代表地标。

  • lmList.append([id, cx, cy]): 然后我们将使用这一行将id,cxcy 的值加到lmList

  • 最后我们将调用mpDraw.draw_landmarks,用最后一行代码画出手的所有地标。

第8步:指定我们要使用的拇指和中指的点

if lmList != []:
    x1, y1 = lmList[4][1], lmList[4][2]
    x2, y2 = lmList[8][1], lmList[8][2]

在上面的代码中,我们指定了lmlist 中的元素数量。它不应该是空的。我们给变量x1y1 分别指定点xy 的坐标4 。这就是拇指尖。然后我们在最后一行对食指重复同样的操作。

第9步:在拇指尖和食指尖之间画一个圆形

cv2.circle(img, (x1, y1), 15, (255, 0, 0), cv2.FILLED)  
cv2.circle(img, (x2, y2), 15, (255, 0, 0), cv2.FILLED)  

上面的代码在拇指尖和食指尖上画了一个圆。

  • (x1, y1) 15 是圆的半径。 是圆的(255, 0, 0) 颜色。 是指 像素的厚度,它将用我们指定的颜色填充圆。cv2.FILLED -1

  • 我们将对食指重复同样的步骤。

第10步:在4点和8点之间画一条线

cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 3)

在上面的代码中,我们使用cv2.line 函数在手的四点和点8 之间画一条线。这条线将连接点4 (x1, y1) ,也就是大拇指的尖端,和点8 (x2, y2) ,也就是食指的尖端。(255, 0, 0) 是线的颜色,3 是它的厚度。

第11步:寻找4号和8号点之间的距离

length = hypot(x2 - x1, y2 - y1)

在上面的代码中,我们用斜线找到拇指尖和食指尖之间的距离。我们通过调用数学函数hypot ,然后传递x2x1 之间的差值以及y2y1 之间的差值来实现。

第12步:将手的范围转换为体积范围

vol = np.interp(length, [15, 220], [volMin, volMax])
print(vol, length)

我们调用NumPy函数np.interp ,将手部范围转换为体积范围。使用的参数是。

  • length:这是我们要转换的数值。
  • [15 - 220]:这是手的范围。
  • [volMin, volMax]:给出我们要转换的范围。

第13步:设置主音量

volume.SetMasterVolumeLevel(vol, None)  

我们要根据手的范围来设置主音量水平。我们通过传递vol ,这是我们转换为音量范围的手部范围的值来实现。

第14步:显示用于与用户互动的视频输出

cv2.imshow('Image', img) 

上面的代码显示了用户与程序互动的实时视频,即用户用拇指和食指来控制音量。

第15步:终止程序

if cv2.waitKey(1) & 0xff == ord('q'): 
   break

上面的代码将在用户按下q 键时终止程序。

结果

当我们在没有任何错误的情况下运行该代码时,结果将是。

Results

结论

你现在已经掌握了创建一个手势音量控制器所需的所有技能。如果你在工作时听你最喜欢的音乐,只需用手势控制音乐的音量,你就能控制音乐的音量。