這一篇主要是針對《透過 OpenNI / NITE 分析人體骨架(上)》和《透過 OpenNI / NITE 分析人體骨架(下)》這兩篇文章,做一些簡單的資料補充。由於這算是比較簡單的筆記,所以就簡單寫一下,不附上完整的程式碼了。
關節位置的平滑化
實際上,OpenNI 所讀出來的深度資料有一定的誤差、甚至每個點的值在李英固定的情況下,也會有相當程度的變動。而同樣的情況,也發生在透過 xn::SkeletonCapability 讀取到的關節位置上;也就是說,讀取到的關節位置,會有一定程度的抖動的現象。
而要怎樣減輕這樣的問題呢?OpenNI 在 xn::SkeletonCapability 這個 capability 裡有提供一個名為 SetSmoothing() 的函式,可以傳入一個浮點樹當作調整參數、來針對讀取到的結果作平滑化;他的值的範圍應該是 0 到 1 之間,越大的話得到的結果連續下來會越平滑,不過相對的也會喪失細節、並且增加一些時間上的延遲。
所以,基本上這部分可能是要視需求去做參數的調整。而理論上,只要在初始化階段透過 SetSmoothing() 這個函式設定好平滑化的參數後,就可以減輕關節資料抖動的現象了。
使用現有的校正資料(不用再擺出校正姿勢)
在使用 OpenNI 做人體姿勢分析的時候,標準的作法是需要擺出 NITE 的標準校正姿勢、也就是所謂的 PSI 姿勢的。不過說實話,要使用者都得擺出這個姿勢一小段時間後、才能開始使用,其實算是滿麻煩的。而實際上 OpenNI 是有提供骨架校正資料的儲存取存取,某種程度上是可以用來做到「不用先擺校正姿勢的人體骨架分析」的!
以目前的 OpenNI 來說,它提供了兩組(四個)相關的函式,可供利用。這兩組函式分別為:
- 儲存、讀取記憶體裡的校正資料
- XnStatus SaveCalibrationData( XnUserID user, XnUInt32 nSlot )
- XnStatus LoadCalibrationData( XnUserID user, XnUInt32 nSlot )
- 儲存、讀取檔案形式的校正資料
- XnStatus SaveCalibrationDataToFile( XnUserID user, const XnChar *strFileName )
- XnStatus LoadCalibrationDataFromFile( XnUserID user, const XnChar *strFileName )
第一組的函式,是可以將已經特定使用者(根據 user ID)校正好的骨架資料,透過 SaveCalibrationData() 儲存到記憶體裡指定的 slot 中(用整數來代表 slot 編號),之後再透過 LoadCalibrationData() 讀出來、套用指定的使用者上使用。
而第二組的函式基本上也是類似的,不過他是將骨架的校正資料以檔案的形式來做儲存與讀取;如此一來,就算程式已經結束過、要重新執行,也還是可以重複利用這些校正過的資料。
要使用這兩組函式其實也不複雜。儲存的部分,主要就是要等到使用者已經完成骨架的校正後(就是《透過 OpenNI / NITE 分析人體骨架(上)》中的 CalibrationEnd() 裡),透過 SaveCalibrationData() 或 SaveCalibrationDataToFile() 來將校正好的資料儲存下來。
而之後要套用儲存下來的骨架校正資料的話,則是要 user generator 有抓到新的使用者、建立新的 user 後(就是《透過 OpenNI / NITE 分析人體骨架(上)》中的 NewUser() 裡),透過 LoadCalibrationData() 或 LoadCalibrationDataFromFile(),直接將儲存好的骨架校正資料讀取出來、並直接套用在新的 user 上(透過指定 user ID)。如此一來,OpenNI 就會認為這個 user 已經經過骨架校正的步驟了~也就是說,可以不用再擺出指定的校正姿勢(PSI),就可以直接開始追蹤骨架了~
而這樣的功能比較直接的應用,應該就是先儲存好一組校正的結果資料,然後之後對於所有新偵測到的使用者,都直接套用這一組骨架校正資料了!這樣基本上,就算是做到「不用擺出校正姿勢的人體骨架分析與追蹤」了~而實際測試的話,這個方法在某種程度上應該算是可行的~
不過,在 Heresy 來看,透過指定姿勢(PSI)來進行骨架的校正實際上應該還是有其必要性的;而這樣的作法,算是把一組校正好的骨架資料當作標準範例、硬套用到所有其他 user generator 偵測到的「使用者上」,所以還是會有可能有問題的。像 Heresy 在實際測試的時候,不但有可能會導致某些非人的物體,也被硬套上骨架的情形,而即使是人,在某些狀況下,也會有骨架資料沒辦法正確追蹤的狀況。整體來說,Heresy 是覺得這種強制套用校正資料的方法,穩定性是相對比較差的。
目前沒有繼續再玩下去,不過 Heresy 現在的想法,是覺得應該可以透過骨架各關節的可靠度,來判斷這種強制套用的結果是否合適,如此或許可以略過某些不合適的例子;但是實際上這也還只是個想法,並沒有經過實測就是了。
您好目前我是使用《透過 OpenNI / NITE 分析人體骨架(上)》來抓取全身坐標之中右手的座標
可是如大大所說會有嚴重的抖動情況
假如想要平滑可以直接改其中的code還是需要做甚麼修正?
大概加甚麼東西在哪個部分
讚讚
不好意思比較沒基礎再麻煩您清楚一點點出將SetSmoothing() 或者甚麼方法放在哪一段
讚讚
SetSmoothing() 是控制用的參數,基本上只要把相關的物件建立出來後,就可以呼叫了,沒有限制要放在哪。
讚讚
相關物件是?
讚讚
以這邊來說,SetSmoothing() 是 xn::SkeletonCapability 的函式,所以你至少得要可以取得 xn::SkeletonCapability 才能呼叫。
也因此,你必須要先把 UserGenerator 建立好才可以用。
讚讚
// 3. create depth generator
xn::DepthGenerator mDepthGenerator;
xn::SkeletonCapability SetSmoothing();
mDepthGenerator.Create( mContext );
mDepthGenerator.SetMapOutputMode( mapMode );
我放在這邊對嗎? 請問有需要再()加上參數?
讚讚
XN_C_API XnStatus XN_C_DECL xnSetSkeletonSmoothing ( XnNodeHandle hInstance,
XnFloat fFactor
)
這?…不太懂
讚讚
你這邊的程式碼基本上應該是不合法的語法,應 該不可能編譯過的。
建議請參考這篇的範例來做修改
https://kheresy.wordpress.com/2011/12/06/nite1-5_skeleton_without_calibration_pose/
https://kheresy.wordpress.com/2011/01/28/detecte_skeleton_via_openni_part1/
裡面就有使用到 SkeletonCapability 的東西。
而且,文章和之前的回應也都已經有說明了,SkeletonCapability 是由 UserGenerator 提供的,你的程式應該要加在 UserGenerator 建立好之後。
但是你這邊是加上 DepthGenerator 的建立?
讚讚
// 8. start generate data
mContext.StartGeneratingAll();
mSC.SetSmoothing(0.1);
我是直接套用您在https://kheresy.wordpress.com/2011/01/28/detecte_skeleton_via_openni_part1/
的文章code 所以UserGenerator 建立已經完成?
編譯出來可執行可是我不確定他真的有smoothing 這樣有完成?
讚讚
理論上這一的設定應該是正確的。
建議可以把數值拉高試試看效果。
讚讚
想請問他參數0.1~1所代表的意思是甚麼呢?
讚讚
文章內已經有說明了,
他的值的範圍應該是 0 到 1 之間,越大的話得到的結果連續下來會越平滑,不過相對的也會喪失細節、並且增加一些時間上的延遲
讚讚
不好意思我可能描述得不好
我的意思是0.1~1的1是指過濾掉1mm的雜訊? 還是甚麼嗎?
讚讚
不是。
他基本上只是 0 – 1 的一個平化化的參數,沒有特定單位。
讚讚
[…] OpenNI 人體骨架分析部分補充、OpenNI XnSkeletonJointOrientation 簡單分析 […]
讚讚
[…] + NITE 在某種程度上也可以做到不用校正姿勢的骨架追蹤中(參考),但是相較之下,Kinect SDK […]
讚讚
又有OpenNI的新文了
感謝heresy大大
XDD
讚讚