OpenCV+Mediapipe手势动作捕捉与Unity引擎的结合
OpenCV+Mediapipe手勢動作捕捉與Unity引擎的結合
- 前言
- Demo演示
- 認識Mediapipe
- 項目環(huán)境
- 手勢動作捕捉部分
- 實時動作捕捉
- 核心代碼
- 完整代碼
- Hands.py
- py代碼效果
- Unity 部分
- 建模
- Unity代碼
- UDP.cs
- UDP.cs接收效果圖
- Line.cs
- Hands.cs
- 最終實現(xiàn)效果
前言
本篇文章將介紹如何使用Python利用OpenCV圖像捕捉,配合強大的Mediapipe庫來實現(xiàn)手勢動作檢測與識別;將識別結果實時同步至Unity中,實現(xiàn)手勢模型在Unity中運動身體結構識別
Demo演示
Demo展示:https://hackathon2022.juejin.cn/#/works/detail?unique=WJoYomLPg0JOYs8GazDVrw
本篇文章所用的技術會整理后開源,后續(xù)可以持續(xù)關注:
GitHub:https://github.com/BIGBOSS-dedsec
項目下載地址:https://github.com/BIGBOSS-dedsec/OpenCV-Unity-To-Build-3DHands
CSDN: https://blog.csdn.net/weixin_50679163?type=edu
同時本篇文章實現(xiàn)的技術參加了稀土掘金2022編程挑戰(zhàn)賽-游戲賽道-優(yōu)秀獎
作品展示:https://hackathon2022.juejin.cn/#/works/detail?unique=WJoYomLPg0JOYs8GazDVrw
認識Mediapipe
項目的實現(xiàn),核心是強大的Mediapipe ,它是google的一個開源項目:
| 人臉檢測 FaceMesh | 從圖像/視頻中重建出人臉的3D Mesh |
| 人像分離 | 從圖像/視頻中把人分離出來 |
| 手勢跟蹤 | 21個關鍵點的3D坐標 |
| 人體3D識別 | 33個關鍵點的3D坐標 |
| 物體顏色識別 | 可以把頭發(fā)檢測出來,并圖上顏色 |
Mediapipe Dev
以上是Mediapipe的幾個常用功能 ,這幾個功能我們會在后續(xù)一一講解實現(xiàn)
Python安裝Mediapipe
也可以用 setup.py 安裝
https://github.com/google/mediapipe
項目環(huán)境
Python 3.7
Mediapipe 0.8.9.1
Numpy 1.21.6
OpenCV-Python 4.5.5.64
OpenCV-contrib-Python 4.5.5.64
實測也支持Python3.8-3.9
手勢動作捕捉部分
手勢特征點圖
實時動作捕捉
本項目在Unity中實現(xiàn)實時動作捕捉的核心是通過本地UDP與socket 進行通信
關于數(shù)據(jù)文件部分,詳細可以查看OpenCV+Mediapipe人物動作捕捉與Unity引擎的結合中對數(shù)據(jù)文件部分的講解和使用
核心代碼
攝像頭捕捉部分:
import cv2cap = cv2.VideoCapture(0) #OpenCV攝像頭調用:0=內置攝像頭(筆記本) 1=USB攝像頭-1 2=USB攝像頭-2while True:success, img = cap.read()imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #cv2圖像初始化cv2.imshow("HandsImage", img) #CV2窗體cv2.waitKey(1) #關閉窗體視頻幀率計算
import time#幀率時間計算 pTime = 0 cTime = 0while True cTime = time.time()fps = 1 / (cTime - pTime)pTime = cTimecv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,(255, 0, 255), 3) #FPS的字號,顏色等設置Socket通信:
定義Localhost和post端口地址
手勢動作捕捉:
if hands:# Hand 1hand = hands[0]lmList = hand["lmList"] for lm in lmList:data.extend([lm[0], h - lm[1], lm[2]])完整代碼
Hands.py
from cvzone.HandTrackingModule import HandDetector import cv2 import socketcap = cv2.VideoCapture(0) cap.set(3, 1280) cap.set(4, 720) success, img = cap.read() h, w, _ = img.shape detector = HandDetector(detectionCon=0.8, maxHands=2)sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) serverAddressPort = ("127.0.0.1", 5052)while True: success, img = cap.read() hands, img = detector.findHands(img) data = []if hands:# Hand 1hand = hands[0]lmList = hand["lmList"] for lm in lmList:data.extend([lm[0], h - lm[1], lm[2]])sock.sendto(str.encode(str(data)), serverAddressPort)cv2.imshow("Image", img)cv2.waitKey(1)py代碼效果
Unity 部分
建模
在Unity中,我們需要搭建一個人物的模型,這里需要一個21個Sphere作為手勢的特征點和21個Cube作為中間的支架
具體文件目錄如下:
Line的編號對應手勢模型特征點
Unity代碼
UDP.cs
本代碼功能將Socket發(fā)送的數(shù)據(jù)進行接收
using UnityEngine; using System; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading;public class UDPReceive : MonoBehaviour {Thread receiveThread;UdpClient client; public int port = 5052;public bool startRecieving = true;public bool printToConsole = false;public string data;public void Start(){receiveThread = new Thread(new ThreadStart(ReceiveData));receiveThread.IsBackground = true;receiveThread.Start();}private void ReceiveData(){client = new UdpClient(port);while (startRecieving){try{IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);byte[] dataByte = client.Receive(ref anyIP);data = Encoding.UTF8.GetString(dataByte);if (printToConsole) { print(data); }}catch (Exception err){print(err.ToString());}}} }UDP.cs接收效果圖
無數(shù)據(jù)接收下:
數(shù)據(jù)通信接收下
Line.cs
這里是每個Line對應cs文件,實現(xiàn)功能:使特征點和Line連接在一起
using System.Collections; using System.Collections.Generic; using UnityEngine;public class LineCode : MonoBehaviour {LineRenderer lineRenderer;public Transform origin;public Transform destination;void Start(){lineRenderer = GetComponent<LineRenderer>();lineRenderer.startWidth = 0.1f;lineRenderer.endWidth = 0.1f;} // 連接兩個點void Update(){lineRenderer.SetPosition(0, origin.position);lineRenderer.SetPosition(1, destination.position);} }Hands.cs
這里是讀取上文識別并保存的手勢動作數(shù)據(jù),并將每個子數(shù)據(jù)循環(huán)遍歷到每個Sphere點,使特征點隨著攝像頭的捕捉進行運動
using System.Collections; using System.Collections.Generic; using UnityEngine;public class HandTracking : MonoBehaviour {public UDPReceive udpReceive;public GameObject[] handPoints;void Start(){}void Update(){string data = udpReceive.data;data = data.Remove(0, 1);data = data.Remove(data.Length - 1, 1);print(data);string[] points = data.Split(',');print(points[0]);for (int i = 0; i < 21; i++){float x = 7-float.Parse(points[i * 3]) / 100;float y = float.Parse(points[i * 3 + 1]) / 100;float z = float.Parse(points[i * 3 + 2]) / 100;handPoints[i].transform.localPosition = new Vector3(x, y, z);}} }最終實現(xiàn)效果
Good Luck,Have Fun and Happy Coding!!!
總結
以上是生活随笔為你收集整理的OpenCV+Mediapipe手势动作捕捉与Unity引擎的结合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring boot车辆管理系统毕业设
- 下一篇: 小号福利