Unity3D Kinect 实时显示对象的头部图像

本文介绍了如何在Unity3D结合Kinect的项目中,通过GreenScreen技术实现锁定骨架头部的实时图像显示。作者详细讲述了从获取彩色图像数据,到利用Shader进行头部区域渲染的全过程,并分享了遇到的问题及解决方案,最终达到在Oculus上也能清晰识别头部的效果。
摘要由CSDN通过智能技术生成

最近在做一个Unity+Kinect 的项目,因为涉及一些姿势的识别,所以要锁定一个识别的骨架,但是用户怎么知道我锁定的骨架是谁呢?于是想到一个方法,那就是把当前的锁定的骨架的对象的头部图片展示出来,那么这样用户就知道当前检测的是谁啦~
话不多说,先展示一下demo,最终的一个展示效果~
这里写图片描述
有了这个想法,那么我们就来开始动手做吧,查找了一些资料,但是一输入关键词头部或者face什么的都是一些Unity的面部检测的相关内容,但是我只是想把头部的彩色图像从ColorView中抠出来而已啊,而且,我的项目最终是需要戴Oculus的,所以面部检测的话,估计最后带上那么大的Oculus也识别不出来。于是乎,突然想到Unity的开发者包里面有一个GreenScreen的项目,但是那个导入貌似有问题…于是乎去解决一下问题,然后再来研究一些那个项目是干嘛的…
对于GreenScreen的导入之后的错误,我们只要更改一下Shader的一处变量就好啦~
这里写图片描述
然后,我们运行这个程序,你会发现它其实是把检测到的人的部分显示在屏幕上,而其他的部分全部用绿色填充,这也就是为什么叫做GreenScreen吧…
我们来分析一下这个代码:CoordinateMapperManager和CoordinateMapperView。
浏览一遍代码之后,它的实现流程是这样的,利用Kinect的MultiSourceFrameReader读取Kinect的彩色图像,深度图像和BodyIdex,注意,这个BodyIndex不是Body,它不包含骨骼的信息,它是一个和kinect 深度图像等大的一个数组,如果你用texture展示出来它的话,你会得到一个身体的轮廓【如果你想查看一下这个轮廓的话,可以在CoordinateMapperManager里面更改一个texture的声明:m_pColorRGBX = new Texture2D(cDepthWidth,cDeapthHeight,TextureFormat.BC4,false) ,然后在ProcessFrame函数里面更改一下材质的填充语句为m_pColorRGBX.LoadRawTextureData(pBodyIndexBuffer),然后运行的话,你就应该可以看到一个红色的人的轮廓图像】
额,说的有点多,我就不在这里分析代码了,就是说一下实现,他这个例子的实现过程是:采集到图像的数据,然后把深度图像的数据以及BodyIndex的数据作为类似掩码的一个功能,在Shader里面片元着色器渲染的时候,判断当前的像素时候是需要渲染的状态,是的话,就渲染,不是的话就渲染成绿色,大体上讲有点类似于PS的模板的功能。
这里写图片描述
这里是例子Shader的片元着色器的部分代码:
这里写图片描述
所以呢,我也就想到了,那我也做一个“模板”啊,于是呢,在做之前,我们要想一想具体的过程是怎么样的?
我这里的流程是:
1. 选取Kinect最近骨架的Head和SpineShoulder两个节点,作为计算展示的区域。
2. 把骨骼的Camera坐标映射到彩色图片的坐标
3. 计算出末班数组的内容(这里0表示不渲染,1表示渲染)
4. Shader片元着色器渲染材质
嗯,好下面就开始编写代码创建一个与BodySourceView类似的MineBodySourceView脚本,首先根据判断当前检测到的骨架的远近,拿出来距离最近的骨架的bodytrackid。

        //get the nearest body
        float near_Z = 5;
        foreach (var body in data) {
            if (body == null)
            {
                continue;
            }
            if (body.IsTracked) {
                if (body.Joints [Kinect.JointType.SpineMid].Position.Z < near_Z) {
                    nearest_body = body.TrackingId;
                    near_Z = body.Joints [Kinect.JointType.SpineMid].Position.Z;
                }
            }
        }

然后,根据对应骨架的头部和肩膀中部的坐标,计算显示区域的大小。

    private void RefreshBodyObject(Kinect.Body body, GameObject bodyObject)
    {
        for (Kinect.JointType jt = Kinect.JointType.SpineBase; jt <= Kinect.JointType.ThumbRight; jt++)
        {
            Kinect.Joint sourceJoint = body.Joints[jt];
            Kinect.Joint? targetJoint = null;

            if(_BoneMap.ContainsKey(jt))
            {
                targetJoint = body.Joints[_BoneMap[jt]];
            }

            Transform jointObj = bodyOb
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值