圣诞纯情手势告白(Mediapipe基本使用手势识别详解)
文章目錄
- 前言
- 環境安裝
- 快速上手(手勢捕捉)
- 獲取手的坐標
- 返回參數詳解
- 不同算子
- 手勢識別案例
- 手指狀態判斷
- 編碼
- 升級版(圣誕表白器)
- 總結
前言
本來不想寫這個的,但是轉了一圈國內mediapipe 的比較少教程。沒有那么全面,所以這邊還是記錄一下吧。
環境安裝
如果你是 Anconada 那么你不需要安裝,但如果不是,你只需要輸入以下指令
pip install mediapipe再次之前你必須掌握 python3
pyharm 使用
opencv 基本使用
快速上手(手勢捕捉)
這邊我們舉一個快爛大街的東西。
import mediapipe as mp import cv2cap = cv2.VideoCapture(0)mpHand = mp.solutions.hands #mp的手部捕捉 Hand = mpHand.Hands() #找到圖片當中的手 mphanddraw = mp.solutions.drawing_utils #繪制工具while True:flag,img = cap.read()RGBImage = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #把圖片進行轉換result = Hand.process(RGBImage)if(result.multi_hand_landmarks): #如果有手,那么就會得到手的列表記錄了手的坐標for handlist in result.multi_hand_landmarks:mphanddraw.draw_landmarks(img,handlist,mpHand.HAND_CONNECTIONS)#繪制手的關節 HAND_CONNECTIONS 把點連接起來cv2.imshow("Hands",img)if(cv2.waitKey(1)==ord("q")):breakcap.release() cv2.destroyAllWindows()
注釋應該說得很清楚了,這里就還不闡述了。
獲取手的坐標
從剛才的效果你可以發現,handlist 包含了我們的一只手的完整坐標,并且可以繪制21個點
那么事實上 handlist 就是21個點的編號和坐標(這個坐標是按照百分比來算的),每個點對應下面的圖
所以我們可以非常清楚的去捕捉到我們手的狀態。
接下來我們來對我們的手進行重新繪制。
之后的話我們可以對代碼進行優化,我們知道我們可以直接獲取一個手掌的每一個關節的坐標,在我們的圖片上,這樣一來我們就可以對我們手的姿態進行預測,判斷。這樣一來就好玩了。
例如這樣:
所以就好玩了。
返回參數詳解
這個返回參數很重要,看前面的例子是吧。
首先 hands_data 是多只手的總體坐標,幾只手在屏幕上,那么 len()就是幾
handlist 是包含了一只手的21個點
handlist 包含了 [{點1},{點2}…]
所以么獲取 拇指頭就是 handlist.landmark[4].x * w
所以就ok了。
不同算子
這個其實我也不太好說那玩意叫啥,這里的話我先叫他算子。
那么這個有啥用呢,其實就是使用不同的算法模型,來幫助我們提取不同的特征,以便處理。
這里可以看到這里有很多不同的算子。
調用方式都是類似的,但是處理的方式可能有些許不同。
當然我們這里還是先探討關于 hands這個東西改怎么玩。后面我們再來說說其他的玩意,到本系列最后說不定可以做一個手勢系統,用我們身體的姿態來控制電腦,例如我們可以使用我們的手來充當我們的鼠標(右手)等等,那玩意應該會比較酷!或者我們結合VR游戲驅動,我們將不需要游戲手柄,只需要一個像素良好的攝像頭,并且由于 mediapipe 是直接在CPU當中運行的,這就意味著我們可以在沒有顯卡 GPU 的設備運行,Google官方也說過這玩意可以用到移動端,linux等。
ok 繼續,關于前面的代碼,我們其實已經可以來做一個簡單的音量控制器了,我們只需要對手指間距進行換算即可。不夠這個任然不是我們的主題,我們今天的主題其實是如何識別出我們的手勢,例如識別
1 ~ 5。
手勢識別案例
OK ,那么接下來開始我們的案例,這個案例其實就是
Opencv 快速使用(基礎使用&手勢識別)
的
部分,當時這個部分是直接copy的,結果發現這哥們的其實是抄我發的那個視頻的代碼(吐槽一波寫的真爛,有很嚴重的 OOM 問題。所以我打算自己寫一個算了,反正這個挺好玩的)
手指狀態判斷
首先我們不難發現其實,其實對比官方給出的手指圖片以及我前面的那個手指的圖片。我們只需要對比關節的坐標就可以判斷手有沒有立起來。
相當直觀是吧。
但是這里其實還有個問題,那就是大拇指的問題。
由于大拇指太 短了 所以沒辦法這樣直接判斷,所以我們需要去使用x 的坐標來判斷我們的手。但是這樣一來又出現問題了,那就是我們左右手的構造有點不一樣。
所以我們有時候得去判斷一下我們那個手是左手還是右手
判斷左右手的方式相當簡單,看 1 5 號 X 的相對位置就好了。但是還有個問題那就是手心手背的問題但是其實手心手背的投影和那個左右手的投影是一樣的。
編碼
import mediapipe as mp import cv2 import mathcap = cv2.VideoCapture(0)mpHand = mp.solutions.hands #mp的手部捕捉 Hand = mpHand.Hands() #找到圖片當中的手 mphanddraw = mp.solutions.drawing_utils #繪制工具TipsId = [4,8,12,16,20] #定點的坐標 while True:flag,img = cap.read()RGBImage = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #把圖片進行轉換result = Hand.process(RGBImage)if(result.multi_hand_landmarks): #如果有手,那么就會得到手的列表記錄了手的坐標hands_data = result.multi_hand_landmarksfor handlist in hands_data:h, w, c = img.shapefingers = []#判斷大拇指的開關if(handlist.landmark[TipsId[0]-3].x < handlist.landmark[TipsId[0]+1].x):if handlist.landmark[TipsId[0]].x > handlist.landmark[TipsId[0]-1].x:fingers.append(0)else:fingers.append(1)else:if handlist.landmark[TipsId[0]].x < handlist.landmark[TipsId[0] - 1].x:fingers.append(0)else:fingers.append(1)# 判斷其他手指for id in range(1,5):if(handlist.landmark[TipsId[id]].y > handlist.landmark[TipsId[id]-2].y):fingers.append(0)else:fingers.append(1)# 獲得手指個數totoalfingle = fingers.count(1)cv2.putText(img,str(totoalfingle),(50,50),cv2.FONT_HERSHEY_PLAIN,5,(255,255,255),5)# 這個只是繪制手指關節的,可以忽略這段代碼for id,lm in enumerate(handlist.landmark):cx,cy = int(lm.x * w),int(lm.y * h)cv2.circle(img,(cx,cy),15,(255,0,255),cv2.FILLED)cv2.putText(img,str(id),(cx,cy),cv2.FONT_HERSHEY_PLAIN,1,(0,255,255),1)mphanddraw.draw_landmarks(img,handlist,mpHand.HAND_CONNECTIONS,)cv2.imshow("Hands",img)if(cv2.waitKey(1)==ord("q")):breakcap.release() cv2.destroyAllWindows()效果
升級版(圣誕表白器)
接下來到此我們應該就已經結束了,但是突然想起來那啥,我們其實不僅可以顯示文字在我們的文字,還可以疊加圖片,
SO MAYBE IT CAN WORK SOME INTERESTING THINGS SUCH AS
CONFESS TO SOMEBODY WHICH I CAN NOT USE IT RIGHT NOW!
FUCK,叫我狗糧制造機,謝謝!
效果
代碼
圖片自己準備去(如果有人表白成功了記得踹我)
總結
最基本的使用其實就是這樣的,后面你想怎么架構,就怎么架構,這個無所謂,按照這個模板來套就可以了。
總結
以上是生活随笔為你收集整理的圣诞纯情手势告白(Mediapipe基本使用手势识别详解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 引领高并发直播场景进入毫秒时代,阿里云发
- 下一篇: 人工智能训练平台