OpenNI 的座標系統


恩…最近才發現,雖然 Heresy 有就深度值得意義和精確度做過簡單的探討(參考《Kinect + OpenNI 的深度值》,但是除了在之前「3D 體感應用研習工作坊」的課程投影片(參考)裡面,有說明過 OpenNI 的投影世界座標系統(projective coordinate system)和真實世界座標系統(real world coordinate system)外,似乎都沒有在部落格上整理過相關的資料?所以現在來補一下,大概解釋一下 OpenNI 中這兩個座標系統的定義、關係。

投影座標系統/Projective Coordinate System

首先,在之前《使用 Qt GraphicsView 顯示 OpenNI 影像資料》一文中,已經有提供範例,可以使用 Nokia Qt,在 2D 的環境下把 OpenNI 抓到的影像顯示出來了;而顯示出來的結果,大致上會像右圖的樣子。

而實際上,這個時候深度資訊所使用的,就是 OpenNI 的「投影座標系統」。這邊的「投影」所代表的意義,實際上應該就是電腦 3D 圖學裡面,「把三度空間場景裡的東西、以指定的方法投影到一個設定好的平面上、產生出一張平面的圖」的意思。

在 OpenNI 的投影座標系統裡,基本上是以左上角為 (0, 0) 的原點,往右邊為正的 X 軸、往下方為正的 Y 軸;這樣的定義,和一般電腦中影像的座標系統是相同的。

而 Z 軸的正向,可以視為往螢幕內延伸,這樣就形成了一個右手座標系統(如果把 Z 軸看成出螢幕,就會變成左手座標系統);像下圖就是透過 OpenGL 把 OpenNI 得到的資訊,以投影座標系統的形式畫成 3D 的結果;其中 Z 軸就是透過 Depth Generator 讀取到的深度,不過由於考量到 Z 軸的值的範圍和 X/Y 的差異很大,所以這邊有把 X 和 Y 軸放大十倍來做顯示。

其中,畫面左上角就是 (0,0,0)、也就是原點;紅線代表 X 軸、綠線代表 Y 軸、藍線則是代表Z 軸;而黃色的框線所構成的長方體,則是感應器理論上可以看到的範圍,一般狀況下得到的點都會在這個四方體內。

而由於投影座標系統裡的 X / Y 軸的單位是像素、Z 軸的單位則是公厘,所以其實單位是不一致的;再加上直接這樣畫出來的話,其實可以發現 3D 場景裡的物體其實是有變形的,也就是會有「越遠的東西越小」的效果,所以其實並不適合直接把投影座標系統上的資料,拿來做 3D 空間的處理。

 

真實世界座標系統/Real World Coordinate System

由於投影座標系統基本上是針對 2D 平面的影像再做處理用的,如果要在 3D 環境下做處理,在取得投影座標系統的資料後,需要透過 OpenNI 內 Depth Generator 所提供的 ConvertProjectiveToRealWorld() 這個函式,來將投影座標系統上的座標點,轉換成真實世界座標系統的座標點。這部分的使用說明,可以參考《透過 OpenNI 建立 Kinect 3D Point Cloud》一文。

而 OpenNI 的真實世界座標系統,基本上是感應器(Kinect 或 Xtion Pro)為原點的座標系統;感應器的前方為正的 Z、上方為正的 Y,而感應器的右方則為正的 X。所以實際上,這個座標系統是採用「左手座標系統」的形式;而如果畫成示意圖的話,基本上就會是像右邊的樣子。

如果把 OpenNI 得到的深度資料,在透過 depth generator 的 ConvertProjectiveToRealWorld() 轉換到這個所謂的真實世界座標系統後,透過 3D 畫出來的話,就會變成像下面的圖的樣子:

基本上,上圖中的紅綠藍三種顏色的粗線,一樣分別是對應到 X/Y/Z 三個軸的方向。而黃色的線所構成像是金字塔的四角錐,就是感應器理論上可以看到的區域;他所代表的意義,和在投影座標系統裡的長方體其實是相同的,只是投影座標系統的長方體是經過投影、變形的結果而已。

而在真實世界座標系統裡,X / Y / Z 三個軸的單位就會是一致的,都是公厘;而物體也不會因為遠近而有變形、或大小的改變,只有精確度會隨著 Z 的變大而變低。

不過,如果是要像 Heresy 一樣搭配 OpenGL 來使用的話,還要注意的就是:OpenNI 的真實世界座標系統是「左手座標系統」,而 OpenGL 則是採用「右手座標系統」!兩者的 X 方向是相反的~如果不加上鏡射(mirror)的效果的話,看到的東西是會左右相反的~也就是會變成下圖的樣子:

上面所選的視角或許看的不是很清楚,下面用比較高的視角來俯瞰、應該就比較清楚了。下面左圖就是有經過鏡射處理、符合真實世界狀況的左手座標系統的;而下方右圖,則是不經過鏡射處理、直接把 3D 的點使用 OpenGL 的右手座標系統畫出來的效果。應該可以很明顯看得出來,左右是顛倒的。

 

所以在處理真實世界座標系統的話,最好也考慮一下自己所使用的 3D 函式庫是採用哪種座標系統、是否和 OpenNI 所定義的相符。(不過就算沒有考慮,一般大概也就是只會產生靜像效果而已)

 

這篇大致上就是這樣了,這部分有很多地方基本上是自己摸索出來的,如果有不正確的地方請麻煩指證。
對於座標系統的簡單說明,可以參考維基百科


OpenNI / Kinect 相關文章目錄

對「OpenNI 的座標系統」的想法

  1. 您好,想問您幾個問題,
    1.轉成真實世界座標系後,原點座標怎麼計算得到?
    2.原點座標會是深度攝影機的鏡頭還是rgb的鏡頭?
    感謝您

    • 1. 原點的定義就是 0, 0, 0,沒有所謂的計算…
      2. 官方文件僅有血是以感應器為原點,並沒有進一步的資訊。不過,個人臆測應為深度感應器。

      • 謝謝您的回覆,最近要寫kinect程式想在了解一些事情。
        1.如果要讓pointcloud看起來跟rgb影像重疊(以opengl畫出),則是否要計算出視角的參數(如glFrustum(left, right, bottom, top, near, far))?
        2.呈上個問題2.,既然是以深度感應器為原點,在本問題1.的應用中,是否代表在我無法將pointcloud完全重疊。
        感謝您的回答

        • 抱歉,不瞭解你的問題所在。
          如果是要用 Point cloud 畫,那直接把顏色附加在每個點上不就好了?為什麼要考慮重疊?

          • 應該說在應用上,單純以pointcloud的視覺效果比較差,所以想用rbg做影像的呈現,但因pointcloud與之重疊,因此達到需要的功能性。
            我說的重疊是影片中這個意思:

            感謝您

          • 如果你是要這種顯示效果,請不要使用 point 來畫,而是用 mesh。
            色彩可以用 pre-vertex color 或是 texture 的形式。

  2. […] 首先,在 OpenNI 1.x 的座標系統,基本上分成「投影座標系統」(Projective Coordinate System)和「真實世界座標系統」(Real World Coordinate System)兩種,這在之前的《OpenNI 的座標系統》已經有介紹過了,如果還沒看過的,請稍微閱讀一下這篇文章。 […]

  3. xDepthGenerator.ConvertProjectiveToRealWorld( 5, aProjPoint, aRealPoint );
    請教老師,
    5 那個數字代表什麼意思?
    謝謝

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.