以前作姿态识别,梦想着之后能够本身作出一款体感游戏,然然后来才发现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。