在本教程中,我們將使用MediaPipePython 庫來檢測我們的手勢并使用它來控制 Raspberry Pi 媒體播放器。在這里,我們將使用總共六個手勢,即開合拳和手的上、下、左、右移動。打開和關閉拳頭手勢用于播放和暫停視頻。上下手勢用于增大和減小音量,左右手勢用于快進和倒退視頻。
構建手勢控制媒體播放器所需的組件
樹莓派 4
Pi 相機模塊
在這里,我們只需要安裝了 OpenCV 和 MediaPipe 的 Raspberry Pi 4 和 Pi 攝像頭模塊。 OpenCV 用于 數字圖像處理,而 MediaPipe 用于手部跟蹤。數字圖像處理最常見的應用是 物體檢測、 人臉識別和 人數統計。
什么是媒體管道?
MediaPipe是一個框架,用于構建跨平臺(即 Android、iOS、Web、邊緣設備)多模式(例如視頻、音頻、任何時間序列數據)應用機器學習管道,包括快速 ML 推理、經典計算機視覺和媒體處理(例如視頻解碼)。MediaPipe 發布了各種預構建的 python 和其他語言包,例如:
物體檢測
人臉檢測
手部追蹤
姿勢估計
多手追蹤
頭發分割
MediaPipe Python 包在適用于 Linux、macOS 和 Windows 的 PyPI 上可用。使用以下命令在 Raspberry Pi 4 上安裝 MediaPipe:
?
須藤 pip3 安裝 mediapipe-rpi4
?
如果您沒有 Pi 4,則可以使用以下命令將其安裝在 Raspberry Pi 3 上:
?
須藤 pip3 安裝 mediapipe-rpi3
?
在樹莓派上安裝 OpenCV
在安裝 OpenCV 和其他依賴項之前,Raspberry Pi 需要完全更新。使用以下命令將 Raspberry Pi 更新到其最新版本:
?
sudo apt-get 更新
?
然后使用以下命令安裝在 Raspberry Pi 上安裝 OpenCV 所需的依賴項。
?
sudo apt-get install libhdf5-dev -y sudo apt-get install libhdf5-serial-dev –y sudo apt-get install libatlas-base-dev –y sudo apt-get install libjasper-dev -y sudo apt-get install libqtgui4 –y sudo apt-get install libqt4-test –y
?
之后,使用以下命令在您的 Raspberry Pi 上安裝 OpenCV。
?
pip3 安裝 opencv-contrib-python==4.1.0.25
?
在樹莓派上安裝PyAutoGUI
PyAutoGUI 是一個跨平臺的 GUI 自動化 Python 模塊,可讓您的 Python 腳本控制鼠標和鍵盤以自動與其他應用程序交互。PyAutoGUI 適用于 Windows、macOS 和 Linux,并在 Python 2 和 3 上運行。要在 Raspberry Pi 上安裝 PyAutoGUI,請運行:
?
pip3 安裝 pyautogui
?
文檔末尾給出了使用手勢控制媒體播放器的完整代碼。在這里,我們將解釋代碼的重要部分,以便更好地解釋。
通過導入 OpenCV、MediaPipe 和 PyAutoGUI 包來啟動代碼。如前所述,MediaPipe 是手部跟蹤的核心包,而 OpenCV 用于圖像處理。PyAutoGUI 用于根據手勢控制鍵盤。
?
導入簡歷2 將媒體管道導入為 mp 導入pyautogui
?
在接下來的幾行中,我們創建了兩個新變量。第一個是mp_drawing,它將用于從 MediaPipe python 包中獲取所有繪圖實用程序,第二個是mp_hands,用于導入手部跟蹤模型。
?
mp_drawing = mp.solutions.drawing_utils mp_hands = mp.solutions.hands
?
之后定義一個名為findPosition() 的函數。顧名思義,它用于查找食指、中指、無名指和小指的 X、Y 坐標。所有指尖的坐標都將存儲在一個名為lmList[]的變量中。
?
def 手指位置(圖像,handNo=0): lmList = [] 如果結果.multi_hand_landmarks: myHand = results.multi_hand_landmarks[handNo] 對于 id, lm in enumerate(myHand.landmark): # 打印(id,lm) h, w, c = image.shape cx, cy = int(lm.x * w), int(lm.y * h) lmList.append([id, cx, cy]) 返回 lmList
?
然后從 Raspberry Pi 相機開始視頻流,幀高和寬分別為 720、640。
?
上限 = cv2.VideoCapture(0) cap.set(3, wCam) cap.set(4, hCam)
?
然后在下一行中為 mediapipe 提要設置一個新實例,以訪問我們之前導入的手部追蹤模型。我們還傳遞了兩個關鍵字參數,即最小檢測置信度和最小跟蹤置信度。接下來,我們將讀取視頻幀并將它們存儲在圖像變量中。
用 mp_hands.Hands(min_detection_confidence=0.8, min_tracking_confidence=0.5) 作為手:
?
而 cap.isOpened(): 成功,圖像 = cap.read()
?
我們從視頻源獲得的圖像最初是 BGR 格式。因此,在這一行中,我們將首先水平翻轉圖像以供稍后的自拍視圖顯示,然后將 BGR 圖像轉換為 RGB。圖像可寫標志設置為假。?
?
圖像 = cv2.cvtColor(cv2.flip(圖像, 1), cv2.COLOR_BGR2RGB) image.flags.writeable = False
?
?之后,我們將通過手部跟蹤模型傳遞圖像以進行檢測并將結果存儲在一個名為“結果”的變量中。
?
結果=hands.process(圖像)
?
檢測完成后,我們將圖像可寫標志設置為 true,并將 RGB 圖像轉換為 BGR。
?
image.flags.writeable = True 圖像 = cv2.cvtColor(圖像,cv2.COLOR_RGB2BGR)
?
現在,當我們得到檢測結果時,我們將調用mp_drawing?變量在圖像上繪制這些檢測,并使用我們之前導入的繪圖實用程序連接所有檢測。
?
如果結果.multi_hand_landmarks: 對于 results.multi_hand_landmarks 中的 hand_landmarks: mp_drawing.draw_landmarks( 圖片、hand_landmarks、mp_hands.HAND_CONNECTIONS)
?
之后,我們將調用findPosition()函數來獲取所有檢測的 id 和坐標。這些值將存儲在名為 lmList 的變量中。
?
lmList = findPosition(圖像,繪制=真)
?
現在我們有了所有手部標志的坐標,我們將使用它們來檢測不同的手勢,其中第一個是檢測拳頭是張開還是閉合。為此,我們將比較指尖 [8, 12, 16, 20] 和中點 [6, 10, 14, 19] 的坐標,如果指尖低于中點,則拳頭閉合,反之亦然反之亦然。
對于范圍內的 id(1, 5):
?
如果 lmList[tipIds[id]][2] < lmList[tipIds[id] - 2][2]: 手指.append(1) 如果(lmList[tipIds[id]][2] > lmList[tipIds[id] - 2][2]): 手指.append(0)
?
然后在接下來的幾行中,獲取計數的手指總數并將其保存在一個名為totalFingers的變量中。
?
totalFingers = Fingers.count(1) 打印(總手指)
?
現在我們得到了手指的數量,我們將使用它們來播放和暫停視頻。
?
如果 totalFingers == 4: 狀態 = “播放” 如果 totalFingers == 0 并且 state == "Play": 狀態 = “暫停” pyautogui.press('空格') 打印(“空間”)
?
然后我們要檢測的下一個手勢是向左、向右、向上和向下移動。為了檢測左右移動,首先我們將獲取食指尖的 X 坐標,如果值小于 300 則為左滑,如果值大于 400 則為右滑。
?
如果 totalFingers == 1: 如果 lmList[8][1]<300: 打印(“左”) pyautogui.press('左') 如果 lmList[8][1]>400: 打印(“正確”) pyautogui.press('對')
?
同理,檢測上下手勢,我們會得到中指的 Y 坐標,如果值小于 210 則為上滑,如果值大于 230 則為下滑.
?
如果 totalFingers == 2: 如果 lmList[9][2] < 210: 打印(“向上”) pyautogui.press('向上') 如果 lmList[9][2] > 230: 打印(“向下”) pyautogui.press('向下')
?
測試我們的手勢控制媒體控制器腳本
現在媒體計數器腳本已經準備好了,讓我們繼續測試它。因此,將 Raspberry Pi 攝像頭模塊與 Pi 連接,如下所示:
現在,檢查 Pi 相機是否正常工作。查看相機后,啟動 Python 腳本,您會發現彈出一個窗口,其中包含視頻源。現在,您可以通過手勢控制視頻播放器。您可以在下面找到該項目的工作視頻。您可以將視頻源更改為您選擇的任何視頻,并享受通過手勢控制它的樂趣。
導入簡歷2
將媒體管道導入為 mp
導入pyautogui
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
##################################
tipIds = [4, 8, 12, 16, 20]
狀態 = 無
手勢 = 無
wCam, hCam = 720, 640
############################
def 手指位置(圖像,handNo=0):
lmList = []
如果結果.multi_hand_landmarks:
myHand = results.multi_hand_landmarks[handNo]
對于 id, lm in enumerate(myHand.landmark):
# 打印(id,lm)
h, w, c = image.shape
cx, cy = int(lm.x * w), int(lm.y * h)
lmList.append([id, cx, cy])
返回 lmList
# 對于網絡攝像頭輸入:
上限 = cv2.VideoCapture(0)
cap.set(3, wCam)
cap.set(4, hCam)
與 mp_hands.Hands(
min_detection_confidence=0.8,
min_tracking_confidence=0.5) 作為手牌:
而 cap.isOpened():
成功,圖像 = cap.read()
如果不成功:
print("忽略空相機幀。")
# 如果加載視頻,請使用“break”而不是“continue”。
繼續
# 水平翻轉圖像以供稍后自拍視圖顯示,并轉換
# 將 BGR 圖像轉為 RGB。
圖像 = cv2.cvtColor(cv2.flip(圖像, 1), cv2.COLOR_BGR2RGB)
image.flags.writeable = False
結果=hands.process(圖像)
# 在圖像上繪制手部注釋。
image.flags.writeable = True
圖像 = cv2.cvtColor(圖像,cv2.COLOR_RGB2BGR)
如果結果.multi_hand_landmarks:
對于 results.multi_hand_landmarks 中的 hand_landmarks:
mp_drawing.draw_landmarks(
圖片、hand_landmarks、mp_hands.HAND_CONNECTIONS)
lmList = 手指位置(圖像)
#打印(lmList)
如果 len(lmList) != 0:
手指 = []
對于范圍內的 id(1, 5):
如果 lmList[tipIds[id]][2] < lmList[tipIds[id] - 2][2]:
#state = "播放"
手指.append(1)
如果 (lmList[tipIds[id]][2] > lmList[tipIds[id] - 2][2] ):
# state = "暫停"
# pyautogui.press('空格')
# print("空格")
手指.append(0)
totalFingers = Fingers.count(1)
打印(總手指)
#print(lmList[9][2])
如果 totalFingers == 4:
狀態 = “播放”
# finger.append(1)
如果 totalFingers == 0 并且 state == "Play":
狀態 = “暫停”
pyautogui.press('空格')
打印(“空間”)
如果 totalFingers == 1:
如果 lmList[8][1]<300:
打印(“左”)
pyautogui.press('左')
如果 lmList[8][1]>400:
打印(“正確”)
pyautogui.press('對')
如果 totalFingers == 2:
如果 lmList[9][2] < 210:
打印(“向上”)
pyautogui.press('向上')
如果 lmList[9][2] > 230:
打印(“向下”)
pyautogui.press('向下')
#cv2.putText(image, str("Gesture"), (10,40), cv2.FONT_HERSHEY_SIMPLEX,
# 1, (255, 0, 0), 2)
cv2.imshow("媒體控制器", image)
鍵 = cv2.waitKey(1) & 0xFF
# 如果 `q` 鍵被按下,則退出循環
如果鍵 == ord("q"):
休息
cv2.destroyAllWindows()
評論
查看更多