Kinect for Unity检测身高方法

Kinect for Unity自身好像并没有附带检测身高的API可以直接使用。
但Kinect可以获得24个骨骼点,这足够让我们自行根据距离写计算出身高代码。

当然也有别的方法,因为可以获得人体轮廓,然后计算地面距离和头顶距离..


Unity的AssetStore里有个的Kinect的unitypackage,
直接搜Kinect就可以 叫"Kinect with MS-SDK"
下载导入这个包后,
其中有一个检测骨骼点并在三维世界里生产的代码 --- "SkeletonOverlayer.cs"

这个代码:
会根据Kinect的高度和角度 自动调整你的MainCamera的位置和角度,
以至于和Kinect在现实中的角度高度一致。

获得Kinect的Camera看到的彩色图像。
根据Kinect检测到的骨骼数据得到各个骨点的距离,
在unity的三维世界相应地产生一个绿球作为骨骼点的示意。
自动生成25个球和N条线连接这些球
再用unity Line Renderer一一根据人的肢体连接起来。
结果就得到了一个附在图像看到的现实世界的人体上的绿球与线做成的人偶。


脚本示图(我把骨骼点也显示在面板,方便大家看到)



然后根据我们的需要,选取骨骼点,可以计算双腿的平均值,这里我只计算了左腿:)

所以,所要计算的骨骼就是Head到Neck到SpineShoulder到SpineMid到SpineBase到KneeLeft到AnkleLeft。
也就分别是数组中的[3],[2 ] [2],[20] [20],[1] [1],[0] [0],[13] [13],[14] 。


具体实现代码:
我们在skeletonoverlayer.cs里新增一个自定义方法HeightCalculation()来计算身高

1.直接计算法:

void HeightCalculation(){
  //************距离计算*************//
  kinectHeight = Vector3.Distance(joints[3].transform.position,joints[2].transform.position) +
      Vector3.Distance(joints[2].transform.position,joints[20].transform.position) +
      Vector3.Distance(joints[20].transform.position,joints[1].transform.position) +
      Vector3.Distance(joints[1].transform.position,joints[0].transform.position) +
      Vector3.Distance(joints[0].transform.position,joints[13].transform.position) +
      Vector3.Distance(joints[13].transform.position,joints[14].transform.position);
      //**********直接计算**********//
      UIHeight.text = kinectHeight.ToString();
}

这个方法虽然能实现,在不断测试中发现了有许多问题:
1、Kinect的距离、高度、角度,也许会对检测也有小许影响。
2、弯腰和伸展动作会对检测到的距离有一定影响
3、由于检测到的头和脚的骨点是中央,得出的身高和小于实际身高
4、稳定性不算高,偶尔还会有丢失骨点情况。


问题1和2:
都是Kinect骨点检测不十分精确的后果,相差可能最大有10CM.

问题3:
我会采用对最后身高进行一个常量的乘法。具体我用Kinect多次测量得到的头骨点(其实就是头的中心),到脚骨点的距离稳定为1.66左右,而我的准确身高是1.76。
所以我在得到Kinect检测到的头骨点和脚骨点的距离上乘以一个常量1.066(=1.76/1.66),
最后得到的当然就是我的准确身高啦。
之后在CSDN某大神的点赞后,我发现某大神的处理是加上了估算头的距离,
也就是7~10cm左右,我认为他写的更好更科学。

2.常量相乘得实际身高:

voidHeightCalculation(){
  if(GameObject.Find("KinectObject"))
  {
  //**********直接计算**********//
  kinectHeight = Vector3.Distance(joints[3].transform.position,joints[2].transform.position) + 
    Vector3.Distance(joints[2].transform.position,joints[20].transform.position) + 
      Vector3.Distance(joints[20].transform.position,joints[1].transform.position)  + 
        Vector3.Distance(joints[1].transform.position,joints[0].transform.position) +
           Vector3.Distance(joints[0].transform.position,joints[13].transform.position) + 
            Vector3.Distance(joints[13].transform.position,joints[14].transform.position);
    UIHeight.text = (kinectHeight * 1.06667F).ToString();
  }
}

问题4:
各种情况让骨骼点不是一直在每一帧都会存在或在一个正常的位置上,这一点作为开发着的我是非常的头痛头痛头痛(太头痛 所以说3次。。)
然后我决定测量自己的每个骨骼点的距离,防止它检测不到然后距离为0的情况,遇到距离为0,我便以我的骨骼距离为标准给玩家补上。
我得到我的由头到脚的骨骼点距离稳定值分别为:
头到脖子:0.12 | 脖子到肩膀中心:0.07 | 肩膀中心到脊髓中心:0.22 | 脊髓中心到脊髓根部:0.3 | 脊髓根部到左膝盖:0.35 | 左膝盖到左脚踝:0.5
事实证明,我的腿很长
。。当然,上面的那些骨点名称我瞎翻译的,大家意会就好。



这里顺便给大家一个彩蛋,Kinect的检测原理是根据红外线反射到的深度,
然后识别到像人一样的肢体的东西就觉得是人,图中人偶便被识别了。由于本人太帅 就不上镜了:)


然后,
为了防止玩家乱动,摆奇怪的姿势(我也是服了,第一次玩Kinect的人总喜欢乱动。。上头就说我做的东西怎么这么不稳定,Kinect是有范围的好吗,真想打断他们腿)

我做了一个多次测量取得平均值的循环~ 让最后身高数据取平均值。

3.平均值计算身高:

voidHeightCalculation(){
  if(GameObject.Find("KinectObject"))
  {
    //**********平均值**************//
    headToNeck.text = Vector3.Distance(joints[3].transform.position,joints[2].transform.position).ToString();
    neckToSpineShoulder.text = Vector3.Distance(joints[2].transform.position,joints[20].transform.position).ToString();
    spineShoulderToSpineMid.text = Vector3.Distance(joints[20].transform.position,joints[1].transform.position).ToString();
    spineMidToSpineBase.text = Vector3.Distance(joints[1].transform.position,joints[0].transform.position).ToString();
    spineBaseToKneeLeft.text = Vector3.Distance(joints[0].transform.position,joints[13].transform.position).ToString();
    kneeLeftToAnkleLeft.text = Vector3.Distance(joints[13].transform.position,joints[14].transform.position).ToString();
    if(i<10)
    {
      if(kinectHeight < 0.6F)
      kinectHeight = 1.7F;
      Height[i] = kinectHeight  * 1.07F;
      UIHeight.text ="第"+ i +"次:"+ Height[i].ToString();
      playerHeight = playerHeight + Height[i];
      i++;
     Debug.Log("次数:"+ i);
      Invoke("HeightCalculation",0.8F);
    }
    else
    {
      playerHeight = playerHeight/10;
      UIHeight.text ="高度:"+ playerHeight.ToString();
      Debug.Log("高度:"+ playerHeight);
    }
  }
}

这里我没加上骨点距离不正常的判断了。。。其实不正常分很多种情况balbala的起码有3种情况,不是几句话就能写完,我就懒得写了,人生哪有那么多时间造轮子,喜欢写代码你们自己写去啊。。。


---------end-----------

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容