
安裝所需模塊:
pip install cv2
pip install midiapipe
MediaPipe
MediaPipe 為直播和流媒體提供跨平臺、可定制的機器學習解決方案,
- 端到端加速引擎:內置的快速 ML 推理和處理即使在常見硬體上也能加速
- 一次構建,任意部署:統一解決方案適用于 Android、iOS、桌面/云、Web 和物聯網
- 即用型解決方案:先進的機器學習解決方案展示了框架的全部功能
- 免費開源:Apache 2.0下的框架和解決方案,完全可擴展和可定制

MediaPipe主要應用:
- 人臉檢測
- 臉部幾何
- 物體檢測
- 即時物體追蹤
我們首先構建一個Hand物件,然后創建hands和mpDraw兩個物件,分別用于檢測手和繪制手指關鍵點,
手地標模型:

mpHands = mp.solutions.hands
hands = mpHands.Hands(args.mode, args.maxHands, args.model_complexity, args.detectionCon, args.trackCon) # 用于檢測手
mpDraw = mp.solutions.drawing_utils # 繪制關鍵點
results = 0

該物件會識別出人手的21個關鍵點部位,如上圖所示,21個關鍵點分別對應人手的不同關節位置,用于定位手的位置,
def findHands(img, draw=True):
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
global results
results = hands.process(imgRGB)
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
if draw:
mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
return img
該段代碼用于檢測影像中的手,首先將圖片轉成RGB影像,然后利用hands物件進行識別,然后再使用mpDrwa在人手上繪制關鍵點,
# 獲取關節點位置
def findPosition(img, draw=True):
lmLists = []
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
for id, lm in enumerate(handLms.landmark):
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
lmLists.append([id, cx, cy])
if draw:
cv2.circle(img, (cx, cy), 12, (255, 0, 255), cv2.FILLED)
return lmLists
如果已經檢測到手部,之后會進行檢測關鍵點位置,將其進行回傳,回傳的是一個包含21個元素的串列,每個元素由為一個串列,內置有不同關鍵點的相對坐標,
if len(lmList) != 0:
max_list = [lmList[4][2], lmList[8][2], lmList[12][2], lmList[16][2], lmList[20][2]] # 每個手指的尖端部位
count = 0 # 手勢數字結果
# 手勢為4
if max_list[1] < lmList[9][2] and max_list[2] < lmList[9][2] and max_list[3] < lmList[9][2] and max_list[
4] < \
lmList[9][2] and max_list[0] > lmList[9][2] and max_list[0] > lmList[17][2]:
count = 4
# 手勢為3
elif max_list[1] < lmList[9][2] and max_list[2] < lmList[9][2] and max_list[3] < lmList[9][2] and \
lmList[20][
2] > lmList[9][2]:
count = 3
# 手勢為2
elif max_list[1] < lmList[9][2] < lmList[16][2] and max_list[2] < lmList[9][2] < lmList[20][2]:
count = 2
# 手勢為1
elif max_list[1] < lmList[9][2] < lmList[16][2] and lmList[20][2] > lmList[9][2] and lmList[12][2] > \
lmList[9][
2]:
count = 1
# 手勢為5
else:
count = 5
該段代碼用于進行手勢識別,按照21個關鍵點的相對位置,判斷此時影像的手勢情況,

完整代碼
本專案可以使用檔案輸入和攝像頭進行輸入,下面代碼采用的是檔案輸入,如果需要使用攝像頭作為輸入源,只需要將 cap = cv2.VideoCapture("video/finger3.MP4") 內部引數置為0即可,不過還需要調整一下其它位置,這里不做過多敘述,
import argparse
import time
import cv2
import mediapipe as mp
ap = argparse.ArgumentParser()
ap.add_argument("--mode", default=False,
help="Whether to treat the input images as a batch of static and possibly unrelated images, or a video stream.")
ap.add_argument("--maxHands", default=2, help="Maximum number of hands to detect")
ap.add_argument("--model_complexity", default=1, help="Complexity of the hand landmark model: 0 or 1. ")
ap.add_argument("--detectionCon", default=0.8, help="Minimum confidence value for hand detection")
ap.add_argument("--trackCon", default=0.8, help="Minimum confidence value for the hand landmarks")
ap.add_argument("--wCam", default=360, help="width of window")
ap.add_argument("--hCam", default=640, help="height of window")
args = ap.parse_args()
# cap = cv2.VideoCapture(0) # 若使用筆記本自帶攝像頭則編號為0 若使用外接攝像頭 則更改為1或其他編號
# cap.set(3, args.wCam) # 設定視窗的寬高
# cap.set(4, args.hCam)
mpHands = mp.solutions.hands
hands = mpHands.Hands(args.mode, args.maxHands, args.model_complexity, args.detectionCon, args.trackCon) # 用于檢測手
mpDraw = mp.solutions.drawing_utils # 繪制關鍵點
results = 0
# 檢測影像幀中的手
def findHands(img, draw=True):
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
global results
results = hands.process(imgRGB)
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
if draw:
mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
return img
# 獲取關節點位置
def findPosition(img, draw=True):
lmLists = []
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
for id, lm in enumerate(handLms.landmark):
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
lmLists.append([id, cx, cy])
if draw:
cv2.circle(img, (cx, cy), 12, (255, 0, 255), cv2.FILLED)
return lmLists
def main():
pTime = 0
cap = cv2.VideoCapture("video/finger3.MP4")
cap.set(3, args.wCam) # 設定視窗的寬高
cap.set(4, args.hCam)
# 檢查是否正確打開視頻
if cap.isOpened():
open, frame = cap.read()
else:
open = False
while open:
success, img = cap.read() # 讀取資料幀
img = cv2.transpose(img)
img = findHands(img) # 檢測手
lmList = findPosition(img, draw=False) # 獲取手部20個關鍵點坐標
if len(lmList) != 0:
max_list = [lmList[4][2], lmList[8][2], lmList[12][2], lmList[16][2], lmList[20][2]] # 每個手指的尖端部位
count = 0 # 手勢數字結果
# 手勢為4
if max_list[1] < lmList[9][2] and max_list[2] < lmList[9][2] and max_list[3] < lmList[9][2] and max_list[
4] < \
lmList[9][2] and max_list[0] > lmList[9][2] and max_list[0] > lmList[17][2]:
count = 4
# 手勢為3
elif max_list[1] < lmList[9][2] and max_list[2] < lmList[9][2] and max_list[3] < lmList[9][2] and \
lmList[20][
2] > lmList[9][2]:
count = 3
# 手勢為2
elif max_list[1] < lmList[9][2] < lmList[16][2] and max_list[2] < lmList[9][2] < lmList[20][2]:
count = 2
# 手勢為1
elif max_list[1] < lmList[9][2] < lmList[16][2] and lmList[20][2] > lmList[9][2] and lmList[12][2] > \
lmList[9][
2]:
count = 1
# 手勢為5
else:
count = 5
HandImage = cv2.imread(f'FingerImg/{count}.jpg"/>轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/375013.html
標籤:其他
