以前作姿態識別,夢想着之後能夠本身作出一款體感遊戲,然然後來才發現too young。可是夢想仍是要有的,萬一實現了呢。趁着paper發出去的這幾天,作一個toy demo。研究了一下如何將姿態估計的結果應用於unity,參考了不少資料,最終決定使用UDP協議,讓unity腳本接收python腳本的數據(關節點座標),來達到控制object的目的,因爲剛接觸unity時間不長(c#也是剛接觸的),因此確定有不少不足,歡迎交流。demo的代碼和模型地址https://github.com/bBobxx/MyPoseWithUnity3dpython
Recognition.py,須要安裝tensorflow和opencv-pythonlinux
python腳本這邊就是普通的姿態估計的tensorflow程序,只不過要調用socket包,用來發送數據。這邊我設定的是git
UDP_IP = "127.0.0.1" UDP_PORT = 5065 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
端口能夠更改,只要肯定沒佔用就行。github
後面的dataProcess函數是將圖片處理成個人網絡的輸入,這邊的姿態估計算法是我論文中的網絡,識別率不是很高,可是湊活,相比於那些識別率很高的,速度也快點,在筆記本的cpu上能達到3FPS左右,勉強能用,我這邊的模型使用的是cpu,gpu能不能用沒測試過,固然這裏徹底能夠換成別的姿態識別模型,最重要的地方是算法
string_send = 'st,' for w in range(nr_joint): string_send += str(x_c[w])+','+str(y_c[w])+',' string_send += 'end' sock.sendto( string_send.encode(), (UDP_IP, UDP_PORT) )
必定要將數字轉換成字符串,而且encode(),固然這裏加不加開頭和結尾沒那麼重要,可是加上能夠在unity那邊判斷一下。c#
playerControllerScript.cs, move.cs前者放在Sphere上,後者放在Cube上。網絡
在unity那邊首先要創建關節點表明的sphere,我這邊是這樣設置的,注意sphere的層次關係和名字必定要跟我同樣:socket
cube是爲了玩加上去的,能夠不用這些。看一下c#這邊的接受函數函數
private void ReceiveData() { client = new UdpClient (port); while (true) { try { IPEndPoint anyIP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), port); byte[] data = client.Receive(ref anyIP); string text = Encoding.UTF8.GetString(data); //這邊記得在解碼,port是以前python腳本的端口 string[] strArray = text.Split(','); int[] coord1 = new int[32]; for (int i = 1; i<strArray.Length-1;++i) { int x = Int32.Parse(strArray[i]); coord1[i-1] = x; } if (updateCoord) { coord = coord1; updateCoord = false; } } catch(Exception e) { print (e.ToString()); } } }
這部分的代碼主要參考的這篇博客https://www.raywenderlich.com/5475-introduction-to-using-opencv-with-unity測試
而後將姿態估計的結果應用到每一個小球上就能夠了,這裏個人demo中將小球和方塊添加了剛體和碰撞屬性,這部分若是不清楚就去查資料吧,我也是剛入門,就不誤導了。這是update函數中乾的事情:
void Update () { if (!updateCoord){ for (int i=0; i<16;i++) { string obj = "Sphere (" + Convert.ToString(i+1)+")"; GameObject spherei = sphere.transform.Find(obj).gameObject; if (coord[2*i] >0 && coord[2*i+1]>0) { int x = coord[2*i]-320; int y = coord[2*i+1]-240; spherei.transform.position = new Vector3(x, y, 0.0f); } else spherei.transform.position = new Vector3(-1000.0f, -1000.0f, 0.0f); updateCoord = true; } } }
個人筆記本的相機拍出的圖片大小是640*480的,因此上面將x,y座標減了一半,這裏可能須要改,或者直接不減也能夠。這裏的z座標是0,是由於這是2d姿態估計,3d的之後若是有結果再實現。
小球太大的結果QAQ,因此有重疊,真人的話就好點了。編譯了一個64位linux的執行文件,連接:[https://pan.baidu.com/s/19P5ebRN7dUXNcN2n7EQLXQ] (https://pan.baidu.com/s/19P5ebRN7dUXNcN2n7EQLXQ) 提取碼: ju73。