Home People Research Blog Courses Links Search Download
NCHC

Blog

Blog 最新文章

  1. Visual Studio 的遠端偵錯:Windows
    2021/03/24 14:45
  2. Visual Studio 2019 16.9 支援使用 OpenMP LLVM
    2021/03/03 13:52
  3. Valve 推出完全支援 OpenXR 的 SteamVR 1.16.8
    2021/02/25 09:43

Blog 最新回應

  1. 加入斜體文字...
    2021/02/07 21:06
  2. 加入斜體文字...
    2021/02/07 21:06
  3. 加入斜體文字...
    2021/02/07 21:06

Keyword 關鍵字

VR Python OpenNI 開放資料 資料視覺化 git 開放資料 OpenCV Pandas C++11 WebGL OpenNI2 Oculus xml C++20 OpenCL HTC Vive Focus svn C++14 NiTE2 Valve Index OpenMP Pandas javascript Docker ASUS Xtion C++ C++17 C++14 Vulkan HoloLens 2 Python Boost Windows MR Qt HTC Vive 3d print Kinect Oculus Rift S PHP Oculus Quest 2 CubeX HTC Vive Pro Java OpenGL 3D立體 CUDA MR VR GitLab 資訊地圖 iFlyover OpenVR Docker OpenXR

類別:技術相關 » 技術研究
文章發表|我要回應|RSS訂閱

Kinect + OpenNI 的深度值

這篇,稍微來提一下 Kinect 在 OpenNI 的環境下的深度資料性質吧∼

上面這張圖,是 Heresy 透過 Kinect、連續錄下 50 的畫面的深度分布統計資料(Histogram),橫軸是深度(單位 mm)、縱軸則是該深度所抓到的點的數量。雖然隨著場景的不同,得到的結果應該會有落差,但是上面的統計圖,應該還是有一定程度的參考價值。(原始資料)


深度值的意義

不過,這邊首先,Heresy 先釐清一個 Heresy 之前弄錯的地方。那就是,在投影(projective)坐標系、也就是透過 Depth Generator 直接得到的深度圖上,像素的值其實就是直接代表深度值,單位就是 mm;它所代表的意義,就是該點到 Kinect 所在的平面的垂直距離。

而在透過 depth generator 的 ConvertProjectiveToRealWorld() 這個函式轉換到真實世界(real world)坐標系的時候,其實 Z 的值是不會變的;他會根據投影座標系統上的 ( X, Y, Z ),去計算出在真實世界坐標系的位置,理論上會是 ( X', Y', Z ),雖然 X / Y 的執會改變,但是實際上 Z 的值應該都是維持不變的。也就是說,在 OpenNI 裡(或者更嚴格的來說,在 OpenNI 的 Kinect 這個裝置上)投影座標系統和真實世界座標系統的深度值所代表的意義是相同的。

所以,如果只是想知道某個點的深度,或是兩個點的深度差的話,其實不用轉換到真實世界座標系統,直接在投影座標系統針對 Z 值做計算就可以了∼但是,如果是想知道兩點的距離的話,那就還是要透過轉換的函式,把真實世界座標系統的 X / Y 算出來了。


深度的範圍以及精確度

Kinect 的深度有效範圍,根據《Kinect for Windows SDK 官方中文開發教學影片》的投影片的說法,是建議在 1.2 公尺到 3.6 公尺左右;不過實際上,在 OpenNI 中,depth generator 有提供一個 GetDeviceMaxDepth() 函式,可以用來取得這個深度感應器可以偵測到的最遠距離。而 Kinect 所回報的值是 10,000mm、也就是 10 公尺,算是比微軟官方建議的大了不少。

不過雖然他號稱能到這樣的範圍,但是從上方的統計圖裡資料分布的不同應該可以看的出來,實際上深度點的分布密度,在前方是比較高的,而到了後面,密度就很低了!這也代表著,Kinect 這款深度感應器,在比較近的位置,能提供比較高的精確度,而比較遠的地方,精確度就降低了。

實際上,以這組資料來說,深度的部分是從 328mm 開始有偵測到深度的,之前基本上都沒有;這應該也就是 Kinect 能取得的最短深度了(有沒有可能更小?不確定)。但是實際上,這時候能抓到的資料量並不多、也不穩定,所以並不建議使用這種距離的資料。而這個時候,每間隔 1mm 的深度,都可以找到資料點,也就是在取得的資料上,精確度應該是可以到達 1mm 的。

而當深度到達 611mm 後,資料就不再是連續,而會有缺值;也就是某些深度會完全沒有資料,代表著精確度開始降低了。向在這邊有缺值的深度點,依序是 611、622、631、638、644、650…可以發現,缺資料的深度間隔,是越來越高的!而這樣隨著距離越來越遠,有缺值的深度也就越多、分布的密度也就越來越疏,代表精深度的確度越來越低。

大概到 100 公分左右時,大概就已經掉到資料間隔是 3mm 了,這也代表了在這個距離下,3mm 內的深度差異,Kinect 是無法區隔的∼到了 200 公分時,基本上 1 公分左右的差異,Kinect 就已經無法區隔了;而到 300 公分時,則是大約 3 公分內的差異都無法分辨。

而最後有抓到資料的深度,是 9,758(976 公分),不過資料量同樣也很小,不會建議使用這個區段的資料。而前幾的有資料的深度,則是 8,996、9,236、9490;基本上,已經是要格超過 20 公分的間隔了∼也就是說,當到了一定的深度後(約 8 公尺),20 公分以內的深度差異,Kinect 是分辨不出來的。

所以,雖然透過 OpenNI 得到的 Kinect 的深度資料是以 mm 為單位,但是實際上由於感應器的精確度在正常使用的距離下、並沒有這麼高,所以在使用的時候,最好確認一下自己深度上判斷的條件,不要設得太細,以免因為精確度造成問題。

張貼者:heresy於2011/12/27 12:55 下午有29則回應,瀏覽次數:10,415次
jingjing123 於 2011/12/30 16:12 下午 回應:
大牛您好:最近出了个PCL(point cloud library)的数据库,是专门处理点云数据的开源库,目前已经关于kinect的各类数据处理,希望博主有时间可以看看哈,
目前除了官方网站没有什么比较好的交流论坛了悲傷
作者作者heresy 於 2012/01/02 09:39 上午 回應:
to jingjing123 感謝你的分享。PCL Heresy 也有去看過,只是他所需要建置的環境太繁瑣了,雖然他有簡易安裝包,但是有幾個額外的 library 和 Heresy 這邊的環境有重疊…再加上連 OpenNI 都要是 patch 過的…Heresy 是覺得麻煩啦∼所以一直沒有真得下去用…至於會不會認真研究?可能要看之後有沒有時間吧。
James 於 2012/02/16 11:38 上午 回應:
想請問一下 我從kinect 獲得的(x y z) 是指投影座標嗎? 例如 320x240 中的某一點 (100 20 1000)
作者作者heresy 於 2012/02/16 12:23 下午 回應:
to James

如果你是透過 OpenNI Depth Generator 拿到的話,基本上應該就是只有深度值;再加上影像的 x, y,構成投影座標系統上的一個點。
James 於 2012/02/16 17:54 下午 回應:
所以如果要轉成世界座標(X Y Z) Z=深度值
那X Y 呢?
x=f *X /Z , y=f*Y/Z 嗎?
x y 為320x240 中間某一點
f 為焦距

麻煩請解答,謝謝
作者作者heresy 於 2012/02/16 18:22 下午 回應:
您好,座標轉換的部分,請參考:
http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&
SUB_ID=1&PAPER_ID=217


基本上,提供投影座標系統的 x, y, z 就可以轉換成世界座標系統的點了,不需要 f。
zzscorpio 於 2012/03/21 10:31 上午 回應:
heresy你好,关于用opencv获得kinect的深度视频一直有一个疑惑,就是在oni格式下看到的是越靠近Kinec
t(当然是在有效范围内)的物体越亮(黄色),越远也就越暗。但是在得到的avi深度视频(黑白)中,却是越靠近Kinect的
物体越暗(颜色越深),越远的地方颜色越浅(白色)。感觉像是把颜色颠倒了一样,这个是什么原因呢?
作者作者heresy 於 2012/03/21 11:02 上午 回應:
to zzscorpio

深度值基本上只是一個浮點數,不代表任何顏色。
如果要用顏色來呈現深度值的話,需要自己把深度值對應到自己想要的色彩。
不同的程式會有不同的色彩對應,只是單純對應的方法不一樣而已。
fox 於 2012/04/12 21:30 下午 回應:
请教一下,那个转换坐标系为什么要除以Z呢?用X除以Z不就是说除以了深度值么?怎么变成了x了。
作者作者heresy 於 2012/04/13 10:29 上午 回應:
to fox
建議請直接用內建的功能進行轉換。
hanxv 於 2012/05/21 10:02 上午 回應:
您好,我获取的深度信息通过DepthGenerator的GetMetaData来获取的深度信息数据,此时应该获取的是投影
坐标系中的像素信息,单纯对Z信息进行变换,进行显示,得到的图像在距离较近时会有大片不重合的部分,请问这是不是由于kine
ct在检测深度时有缺值导致的呢
作者作者heresy 於 2012/05/21 10:59 上午 回應:
你是指彩色影像和深度影像的位置不一致嗎?
你有使用 Alternative View Point Cap 來做修正嗎?

而實際上,由於Kinect 或 ASUS Xtion Pro Live 在硬體上,彩色影像攝影機以及深度攝影機本來就是在不同的地方,所以本來就一定會有視角上的不同。而雖然可以透過軟體進行修正,
但是在近距離的時候,還是會有明顯的誤差,這個應該算是硬體上的限制了。
hanxv 於 2012/05/22 10:26 上午 回應:
我是用的是OpenCV来创建显示图像,利用GetMetaData获得深度数据,使用了Alternative View Point Cap 进行修正,确实是在显示的时候是靠近kinect的地方会出现较大的不一致,在查资料的时候发现说是kinect获得深度数据是
有ID信息的,我并没有去除数据中的ID信息,是不是数据的ID导致的呢?
作者作者heresy 於 2012/05/22 10:47 上午 回應:
to hanxv
不確定你的不一致是到什麼程度。
個人是建議你試試看用 OpenNI 官方範例 NiViewer,切到 overlay 模式,看看在同樣的距離下,是否會有同樣的狀況。

另,不知道你所說的 ID 是指什麼。
cts 於 2012/05/22 10:50 上午 回應:
heresy老师您好,我想请问一下骨骼关节的获取,手势识别以及setSmooth函数降噪的基本原理。是不是由于这部分是属
于NITE,没有开源?因此资料很少?
作者作者heresy 於 2012/05/22 12:37 下午 回應:
to cts
是的,這部分都是屬於 middle 的實作,也就 NITE 的部分。
hanxv 於 2012/05/22 15:42 下午 回應:
很感谢老师的指导,我同时打开我自己的程序和NiViewer进行了测试,发现二者在相同距离下的图像显示基本是一样的,我是用
灰度图像进行显示,灰度值和距离成比例关系,越靠近kinect,灰度值越小,图像也就呈黑色,在远距离时灰度值越大,在显示时
,发现在一些距离较远的地方也出现了很多灰度值较小的区域,经过老师指点,打开NiViewer程序发现也是出现这种情况,自己
得到的深度信息显示的图像应该还需要进一步处理,才能得到较好的显示效果,很感谢老师的指导
Rex 於 2012/07/11 15:40 下午 回應:
老師你好,不好意思我想請問一下有關於 KINECT 中 骨架數據的儲存語法?以及他可以儲存格式。
作者作者heresy 於 2012/07/11 18:11 下午 回應:
to Rex

如果是 OpenNI 的話,基本上就是要手動把各關節點的資訊讀取出來,然後自己看要怎麼把它存下來。
基本上儲存是要自己寫的。
Rex 於 2012/07/12 16:40 下午 回應:
老師你好,可以請問一下儲存的語法嗎?我想要自動存成TXT檔可是我只找到 this.skeletonData = new Skeleton[kinect.SkeletonStream.FrameSkeletonArrayLength]; 其用法不知如何運用新手上路老師請多包涵。謝謝老師
作者作者heresy 於 2012/07/12 17:02 下午 回應:
to Rex

確認一下,你現在是使用什麼語言、哪個方案再做開發?
感覺上你似乎不是使用 OpenNI、而是使用 Kinect for Windows SDK?
如果是的話,抱歉,Heresy 這邊是使用 OpenNI、並沒有使用 Kinect for Windows SDK。

另外,在標準 C 裡,可以透過 fstream 來對檔案進行存取,建議可以參考看看。
Rex 於 2012/07/13 13:43 下午 回應:
老師你好,老師我是使用 Kinect for Windows SDK,如果我是在C 中的話透過 fstream的話要如何寫?不好意思新手上路,有很多不懂請多多包涵。感謝老師辛苦了。
作者作者heresy 於 2012/07/13 17:48 下午 回應:
to Rex
網路上有很多相關範例,建議可以先參考看看
http://www.cplusplus.com/doc/tutorial/files/
henry 於 2012/10/24 10:37 上午 回應:
heresy老师,您好,新手上路,我想做一张类似您这样的一张条形图,可以参考哪里的代码?
作者作者heresy 於 2012/10/24 17:19 下午 回應:
to henry
Heresy 這張圖是輸出成純文字檔後,然後用 Excel 畫的耶
ty 於 2012/11/01 15:20 下午 回應:
heresy,您好,假如我知道彩色图像的一个二维点(100,100),将它投影到深度图像中,用XnStatus xn:很高興epthGenerator::ConvertProjectiveToRealWorld(XnUInt32 nCount,const XnPoint3D *aProjective,XnPoint3D *aRealWorld)const
这个函数将它转换为实际空间中的坐标时,而这个函数中的aProjective坐标点应该是三维的,那么我这个y值应该怎样获得
呢?
作者作者heresy 於 2012/11/01 17:19 下午 回應:
to ty

2D 影像上的一個點,本來就是三度空間裡面的一條線。
所以你要把投影座標系統裡的點轉換到真實世界座標系統,就必須要指定它的深度,也就是 Z 的值(應該不是 y)。
而一般來說,這個 z 的直就是去取 depth generator 裡的象素值。
ty 於 2012/11/01 18:10 下午 回應:
嗯,我上面打错了,我是想问的怎么取Z值,打成了y,谢谢您了哈
GXJ 於 2013/03/27 17:30 下午 回應:
TO zzscorpio:
请问你是怎么得到深度视频的,我最近也在做这个,但是写入的视频总是有问题,你能给我点指导么,谢谢!

-- TOP --

我要回應
* 身份  訪客 (暱稱:)
 本篇文章作者 (帳號:密碼:)
* 內容      
很高興 悲傷 震驚 疑惑 大笑 發瘋 傷心
* 留言密碼 (請輸入下方圖片中去除前、後位數的數字,共五碼。)
說明 1. * 表示必填欄位。
2. 不支援HTML Tag。
   

-- TOP --

© Visualization and Interactive Media Laboratory of NCHC, 2007 - 2021, All Rights Reserved. Contact E-mail