Kinect for Unity自身好像并沒(méi)有附帶檢測(cè)身高的API可以直接使用。
但Kinect可以獲得24個(gè)骨骼點(diǎn),這足夠讓我們自行根據(jù)距離寫(xiě)計(jì)算出身高代碼。
當(dāng)然也有別的方法,因?yàn)榭梢垣@得人體輪廓,然后計(jì)算地面距離和頭頂距離..
Unity的AssetStore里有個(gè)的Kinect的unitypackage,
直接搜Kinect就可以 叫"Kinect with MS-SDK"
下載導(dǎo)入這個(gè)包后,
其中有一個(gè)檢測(cè)骨骼點(diǎn)并在三維世界里生產(chǎn)的代碼 --- "SkeletonOverlayer.cs"
這個(gè)代碼:
會(huì)根據(jù)Kinect的高度和角度 自動(dòng)調(diào)整你的MainCamera的位置和角度,
以至于和Kinect在現(xiàn)實(shí)中的角度高度一致。
獲得Kinect的Camera看到的彩色圖像。
根據(jù)Kinect檢測(cè)到的骨骼數(shù)據(jù)得到各個(gè)骨點(diǎn)的距離,
在unity的三維世界相應(yīng)地產(chǎn)生一個(gè)綠球作為骨骼點(diǎn)的示意。
會(huì)自動(dòng)生成25個(gè)球和N條線連接這些球。
再用unity Line Renderer一一根據(jù)人的肢體連接起來(lái)。
結(jié)果就得到了一個(gè)附在圖像看到的現(xiàn)實(shí)世界的人體上的綠球與線做成的人偶。
腳本示圖(我把骨骼點(diǎn)也顯示在面板,方便大家看到)
然后根據(jù)我們的需要,選取骨骼點(diǎn),可以計(jì)算雙腿的平均值,這里我只計(jì)算了左腿:)
所以,所要計(jì)算的骨骼就是Head到Neck到SpineShoulder到SpineMid到SpineBase到KneeLeft到AnkleLeft。
也就分別是數(shù)組中的[3],[2 ] [2],[20] [20],[1] [1],[0] [0],[13] [13],[14] 。
具體實(shí)現(xiàn)代碼:
我們?cè)趕keletonoverlayer.cs里新增一個(gè)自定義方法HeightCalculation()來(lái)計(jì)算身高
1.直接計(jì)算法:
void HeightCalculation(){
//************距離計(jì)算*************//
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);
//**********直接計(jì)算**********//
UIHeight.text = kinectHeight.ToString();
}
這個(gè)方法雖然能實(shí)現(xiàn),在不斷測(cè)試中發(fā)現(xiàn)了有許多問(wèn)題:
1、Kinect的距離、高度、角度,也許會(huì)對(duì)檢測(cè)也有小許影響。
2、彎腰和伸展動(dòng)作會(huì)對(duì)檢測(cè)到的距離有一定影響
3、由于檢測(cè)到的頭和腳的骨點(diǎn)是中央,得出的身高和小于實(shí)際身高。
4、穩(wěn)定性不算高,偶爾還會(huì)有丟失骨點(diǎn)情況。
問(wèn)題1和2:
都是Kinect骨點(diǎn)檢測(cè)不十分精確的后果,相差可能最大有10CM.
問(wèn)題3:
我會(huì)采用對(duì)最后身高進(jìn)行一個(gè)常量的乘法。具體我用Kinect多次測(cè)量得到的頭骨點(diǎn)(其實(shí)就是頭的中心),到腳骨點(diǎn)的距離穩(wěn)定為1.66左右,而我的準(zhǔn)確身高是1.76。
所以我在得到Kinect檢測(cè)到的頭骨點(diǎn)和腳骨點(diǎn)的距離上乘以一個(gè)常量1.066(=1.76/1.66),
最后得到的當(dāng)然就是我的準(zhǔn)確身高啦。
之后在CSDN某大神的點(diǎn)贊后,我發(fā)現(xiàn)某大神的處理是加上了估算頭的距離,
也就是7~10cm左右,我認(rèn)為他寫(xiě)的更好更科學(xué)。
2.常量相乘得實(shí)際身高:
voidHeightCalculation(){
if(GameObject.Find("KinectObject"))
{
//**********直接計(jì)算**********//
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();
}
}
問(wèn)題4:
各種情況讓骨骼點(diǎn)不是一直在每一幀都會(huì)存在或在一個(gè)正常的位置上,這一點(diǎn)作為開(kāi)發(fā)著的我是非常的頭痛頭痛頭痛(太頭痛 所以說(shuō)3次。。)
然后我決定測(cè)量自己的每個(gè)骨骼點(diǎn)的距離,防止它檢測(cè)不到然后距離為0的情況,遇到距離為0,我便以我的骨骼距離為標(biāo)準(zhǔn)給玩家補(bǔ)上。
我得到我的由頭到腳的骨骼點(diǎn)距離穩(wěn)定值分別為:
頭到脖子:0.12 | 脖子到肩膀中心:0.07 | 肩膀中心到脊髓中心:0.22 | 脊髓中心到脊髓根部:0.3 | 脊髓根部到左膝蓋:0.35 | 左膝蓋到左腳踝:0.5
事實(shí)證明,我的腿很長(zhǎng)
。。當(dāng)然,上面的那些骨點(diǎn)名稱(chēng)我瞎翻譯的,大家意會(huì)就好。

這里順便給大家一個(gè)彩蛋,Kinect的檢測(cè)原理是根據(jù)紅外線反射到的深度,
然后識(shí)別到像人一樣的肢體的東西就覺(jué)得是人,圖中人偶便被識(shí)別了。由于本人太帥 就不上鏡了:)
然后,
為了防止玩家亂動(dòng),擺奇怪的姿勢(shì)(我也是服了,第一次玩Kinect的人總喜歡亂動(dòng)。。上頭就說(shuō)我做的東西怎么這么不穩(wěn)定,Kinect是有范圍的好嗎,真想打斷他們腿)
我做了一個(gè)多次測(cè)量取得平均值的循環(huán)~ 讓最后身高數(shù)據(jù)取平均值。
3.平均值計(jì)算身高:
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("次數(shù):"+ i);
Invoke("HeightCalculation",0.8F);
}
else
{
playerHeight = playerHeight/10;
UIHeight.text ="高度:"+ playerHeight.ToString();
Debug.Log("高度:"+ playerHeight);
}
}
}
這里我沒(méi)加上骨點(diǎn)距離不正常的判斷了。。。其實(shí)不正常分很多種情況balbala的起碼有3種情況,不是幾句話就能寫(xiě)完,我就懶得寫(xiě)了,人生哪有那么多時(shí)間造輪子,喜歡寫(xiě)代碼你們自己寫(xiě)去啊。。。

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