RGB+D 影片處理
- 2.5D 資料
- 3D 感知(立體聲、結構光、TOF、雷射掃描器,...)
向量、矩陣和標量
* vector (lowercase Gothic alphabets): v, p, m = [m1, m2, ..., mk]', ... * matrix (uppercase Gothic alphabets): R, A, ... * scalar (Italic alphabets: s, t, X, Y, Z, ...
索引
v(1) // the 1st element of the vector v R(1,2) // the 1st row and 2nd col of the matrix R A(:,1) // the 1st vector _ from A = [v1, v2, ..., vN]
一些保留符號
hp: a homogeneous representation of a 2D point, hp = [u, v, 1]' hx: a homogeneous representation of a 3D point, hx = [X, Y, Z, 1]' p: a 2D point, p = [u, v]' x: a 3D point, x = [X, Y, Z]' H: (3x3) planar homography matrix P: (3x4) projective projection matrix
座標變換
o<W>: the origin of the world frame o<C>: the origin of the camera frame o<O>: the origin of the object frame (e.g., x<C> represents a 3D point in the camera frame) R: (3x3) rotation matrix t: (3x1) translation vector T<n, m>: transformation from m to n coordinate system (e.g., o<C> = T<C, W> o<W>)
- 除非我們指定,否則我們使用(第一個)相機座標系作為世界參考系。
- 除了以上符號外,我們將遵循 MATLAB 的符號。
當您取一個 3D 點,,該點的每個值 x(j) 都是相對於特定座標系表示的(例如,感測器座標系)。點 X 也可以在不同的座標系中表示(例如,房間的一個角),。為了區分兩組值,我們可以寫出符號以及相應的座標系: 和 ,其中 是相對於感測器座標系的點,而 是相對於角落座標系的相同點。兩個座標系之間存在一個剛性運動,該運動由一個 (3×3) 旋轉矩陣 和一個 (3×1) 平移向量 表達:。在齊次座標系中,剛性運動可以寫成。請注意,我們放置了源座標系(角落)和目標系統(感測器)的符號。一系列變換表示為,其中.
校準
[edit | edit source]為什麼要校準?
總體流程
a) RGB camera ---- RGB image --(1)-- Rectified RGB image --(3)-- Registered RGB image (w.r.t. IR image)
b) IR camera ---- IR image --(2)-- Rectified IR image
c) projector --(internal calibration + IR image)-- Depth image --(4)-- Rectified Depth image --(5)-- 3D points
- 問題 1: (1), (2), (4) - 徑向畸變
- 方法
http://www.ros.org/wiki/kinect_calibration/technical
http://nicolas.burrus.name/index.php/Research/KinectCalibration
- 問題 2: (3) - RGB 影像到 IR 影像的配準
- 方法:平面單應性
- 問題 3: (5) - 3D 重建
- 方法:三角測量
- 全部合一
http://www.ee.oulu.fi/~dherrera/kinect/
幾何基元和不確定性
[edit | edit source]- 當 x 和 s*x 代表相同的幾何實體時,實體 x 是齊次的。
- 點:歐幾里得空間中的二維點 xx = [x1, x2]' 在二維投影空間中表示為 x = [x1, x2, 1]'。
- 線:二維直線表示為 l = [a b c]'。
- 直線和直線上一點的點積為 0:x' * l == 0。
- 二維歐幾里得空間中的直線方程為 a*x + b*y + c == 0。我們可以將其改寫為 [a b c] * [x y 1]' == 0,這就是點積。因此,在投影空間中,dot(x,l) == x' * l == 0。
- 兩條直線的叉積給出交點:x = cross(l,m)。
- 兩條直線(l 和 m)的交點是一個點。交點 x 位於直線 l 上:dot(x,l) = 0。此外,點 x 位於直線 m 上:dot(x,m) = 0。因此,l 和 m 的叉積給出交點 x。
- 兩點的叉積給出直線:l = cross(x, y)。
- 兩點:|| x - y ||
- 兩條直線:|| l x m ||
- 兩條線段
- 三維直線:兩點 X、Y 構成一條直線。
- 普呂克矩陣定義為 U(4x4) = X Y' - Y X'。從 U 中,直線定義為 L := [ U(4,1) U(4,2) U(4,3) U(2,3) U(3,1) U(1,2) ]'。
- 直線 L 由 [方向向量 U1 | 法向量 U2] 部分組成。U1 代表向量 Y - X。U2 代表 X 和 Y 的叉積。顯然,dot(U1,U2) = 0。
- 兩條直線的交點是一個點。如果兩條直線 L、M 相交,dot(L,M) = 0。
- 兩平面的交點形成一條直線。
- 經過平面 K 的直線 L 形成一個點。
- ...
- 三維座標變換
- 對齊(參見:ICP)
- TP:三維空間的投影變換(15dof),TP = [TA t; v' s]
- TA:三維空間的仿射變換(12dof),TP = [TA t; 0' 1]
- TS:三維空間的相似變換(7dof),TP = [s*R t; 0' 1]
- TE:三維空間的歐幾里得變換(6dof),TP = [R t; 0' 1]
- 點的 uncertainty?
- 直線的 uncertainty?
- 方向的 uncertainty?
- 平面的 uncertainty?

假設你用量角器測量三角形的三個角。從第一次試驗中,你得到了值 [30.5, 60.0, 90.1] 度。這些值並不完美,因為它們的總和不等於 180 度!因此,你決定測量 10 次並將它們取平均值。但是,你仍然不確定平均值的總和是否會等於 180 度。
圖 XXX 顯示了三角形中三個角之間的關係。
- 方法
1) Define a manifold M (e.g. Figure XXX) 2) Measure a set of values p = [a(i), b(i), c(i)] for N times 3) Compute the mean m and the covariance matrix S 4) Project p and S onto the manifold M: q, H
output: angles <-- q variance <-- f(H)
當你在 N 個感測器的外部標定中觀察到多個剛體變換時,你可以使用“對偶四元數”來計算“平均”剛體變換。
- 演算法
* input: {R(i), t(i)} % a set of R, t
* output: R*, t* % optimal R, t
Procedure:
* convert all R(i), t(i) to DQ(i) % Dual Quaternions
* find the mean DQ* from {DQ(i)}
* convert DQ* to R*, t*
"類似於單位長度四元數可以表示三維空間中的旋轉,單位長度對偶四元數可以表示三維空間中的剛體運動。這個事實被用於理論運動學以及在三維計算機圖形學、機器人技術和計算機視覺中的應用。"維基百科
http://stat.fsu.edu/~anuj/CVPR_Tutorial/ShortCourse.htm 形狀分析和活動識別的微分幾何方法
點配準問題 (1) 查詢點到點的對應關係,(2) 估計它們之間的變換。以前的方法可以分為三類:ICP(迭代最近點)、軟分配方法和機率方法。
ICP 可能會陷入區域性最小值,並且對初始化和接受匹配的閾值敏感。因此,最近點策略被連續最佳化框架內的軟分配取代。但是,在存在異常值的情況下,收斂性不能得到保證。點到點的分配問題可以被轉化為估計(高斯)混合模型的引數。--> EM-ICP
- ICP、EM-ICP
- 張量
- 初始化
- ECMPR
- EM-ICP
由於我們同時擁有 RGB 和深度圖,因此可以透過簡單的 3D 特徵匹配來完成兩個檢視的配準。給定兩組對應的 3D 特徵描述符,X = [x1, x2, ..., xn] 和 Y = [y1, y2, ..., yn],X 和 Y 之間的剛體運動,Y = T X,可以直接計算。在存在異常值的情況下,魯棒估計方法(如 RANSAC)可以提供精確的結果。
- 虛擬碼:計算剛性運動
* input: X, Y
* output: R, t
Solution = [];
For i=1:N
randomly select 5 corresponding points from X, Y: s1 = {X(j), X(k), X(l)} and s2 = {Y(j), Y(k), Y(l)}
estimate T' = (R', t') using s1, s2
compute Y^ = T' X
store the number of inliers, m(i), to Solution: S(i) = (R'(i), t'(i), m(i))
Endfor
Answer = arg max(i) (S(i).m(i))
- 參見 HK 分割
- 存在噪聲深度圖時的曲率估計
- 在深度圖上使用 2D 影像特徵
我們可以在 2.5D 深度圖上使用 2D 影像特徵(例如,SIFT、ORB、SURF、LBP)。關鍵區別之一是影像的尺度。由於我們知道範圍圖中的絕對尺度,因此可以將搜尋空間限制為僅檢測物理上有意義的特徵。
- 最大值、自旋影像
- 使用 LKT 在深度影片中跟蹤特徵?
- 深度感測器應經過校準。
- 我們對 2D 特徵的位置和深度值的誤差進行建模。
- 如果我們有一個已知的相機矩陣 K,最小化影像空間中的重新投影誤差可以提供一個準確的估計。
- SIM(表面穿透度量)[Queirolo 2010]
- RGB 值和深度資訊可以融合。
- 人臉檢測
- 人臉識別(OpenNI2 中介軟體)[1]
- 人臉建模(OpenNI2 應用程式)[2]
- 面部特徵檢測:眼睛、鼻尖、嘴巴、耳朵
- 3D 人臉姿態跟蹤
- 微軟釋出的人臉跟蹤 SDK Kinect Windows[3]
- 姿態估計和跟蹤
- 來自 ICT@USC 的 FAAST(骨骼跟蹤)
- Styku 人體建模
- 虛擬試衣間
- 魔鏡
- 從 2.5D
- 從 3D
[物體識別 - M. Bennamoun 和 G.J. Mamic] 中的特徵匹配方法
1. 假設和檢驗
2. 匹配關係結構
3. 姿態聚類
4. 幾何雜湊
5. 解釋樹
6. 配準和距離變換
- 幾何雜湊
- RANSAC、StaRSaC 等。
向量和矩陣操作、偽逆、秩、特徵值分解、奇異值分解、最小二乘法、齊次系統
梯度下降法、牛頓法、列文伯格-馬夸特法 (http://www.ics.forth.gr/~lourakis/levmar/)、單純形法
協方差矩陣、貝葉斯機率
- 卡爾曼濾波、擴充套件卡爾曼濾波
- 粒子濾波
表面切線、法線、面積、三角形網格、沃羅諾伊圖、表面曲率、法線和主曲率
- OpenNI 和 Prime Sensor
http://www.openni.org/Downloads/OpenNIModules.aspx,選擇與您的作業系統匹配的版本。
嘗試此操作:http://structure.io/openni
您需要
- OpenNI 二進位制檔案
- 適用於 Prime Sensor 模組的 OpenNI 相容硬體二進位制檔案穩定版本
下載並安裝二進位制檔案後,您現在可以使用 OpenNI 庫與 OpenCV 結合編寫精彩的程式碼。
- 在您的工作環境(Visual Studio)中進行配置
在專案的“屬性”中,您需要新增
- DIRECTORY_OF_OPENNI\Include 到您的“附加包含目錄”
- DIRECTORY_OF_OPENNI\Lib 到您的“附加庫目錄”
- 在連結器部分,在輸入節點下,選擇附加依賴項並新增 OpenNI2.lib。(應該在 DIRECTORY_OF_OPENNI\Lib\OpenNI2.lib 中)
- 確保您將附加包含目錄和庫目錄新增到您的釋出和除錯配置中。根據您的 OpenNI2 版本選擇 win32 或 x64。
- 您的程式碼檔案應包含 OpenNI.h
供您參考,請檢視 http://www.openni.org/openni-programmers-guide/
簡單的 Openni
[edit | edit source]https://code.google.com/p/simple-openni/wiki/Installation#Windows
如何從深度感測器讀取單個 3D 點?(OpenNI 2)
[edit | edit source]成功安裝 OpenNI2 後,您應該能夠執行 DIRECTORY_OF_OPENNI\Samples/Bin 中的示例程式。
以下程式碼是獲取單個點的深度資訊的關鍵程式碼(對於初始化,您可以參考“SimpleViewer”示例程式碼)
openni::VideoFrameRef depthFrame;
const openni::DepthPixel* pDepth = (const openni::DepthPixel*) depthFrame.getData;
int width = depthFrame.getWidth();
int height = depthFrame.getHeight();
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j, ++pDepth)
if(i == height/2 && j == width/2 && *pDepth != 0 )//The if sentence depends on which point you want, this is the center point for example
{} //assign the value to a 3D point structure
在 OpenCV 影像中顯示來自 OpenNI 輸入的深度圖 (C++) (OpenNI 1)
[edit | edit source]/* Display depth map */
// Matthias Hernandez: 07/27/2011 - University of Southern California
// m31hernandez@gmail.com
// display the depthMap from openNI input in the openCV image ‘out’
void displayDepthMap(IplImage *out, const XnDepthPixel* pDepthMap, XnDepthPixel max_depth, XnDepthPixel min_depth) {
uchar *data = (uchar *)out->imageData;
int step = out->widthStep;
int channels = out->nChannels;
float normalize = (float)(max_depth-min_depth)/255.0f;
int index=0;
for (int i=0; i<MAX_I; i++) {
if (pDepthMap[i] < min_depth || pDepthMap[i] > max_depth) {
for (int k=0; k<channels; k++)
data[index++] = 0;
} else {
if (normalize != 0) {
for (int k=0; k<channels; k++)
data[index++] = (int)(255-(float)(pDepthMap[i]-min_depth)/normalize);
}
else
for (int k=0; k<channels; k++)
data[index++] = 255;
}
}
}
顯示來自 OpenNI 輸入的 RGB 影像 (C) (OpenNI 1)
[edit | edit source]/* Display image map */
// Matthias Hernandez: 07/27/2011 - University of Southern California
// m31hernandez@gmail.com
// display the image map from openNI input in the openCV image ‘out’
void displayImageMap(IplImage *out, const XnUInt8* pImageMap) {
uchar *data = (uchar *)out->imageData;
int step = out->widthStep;
int channels = out->nChannels;
for (int i=0; i<MAX3_HR; i+=3) {
data[i+2] = pImageMap[i];
data[i+1] = pImageMap[i+1];
data[i] = pImageMap[i+2];
}
}
從投影到真實世界的轉換 (C) (OpenNI 2)
[edit | edit source]#define XtoZ 1.114880018171494f
#define YtoZ 0.836160013628620f
#define MIN_DEPTH 450
#define MAX_DEPTH 800
void convertP2RW(float *pDepth, float *pReal, int x, int y, int w, int h) {
int max_i = w * h;
int i1 = (y * w + x),
i2 = i1 + max_i,
i3 = i2 + max_i;
float Z = pDepth[i1];
if (Z > MIN_DEPTH && Z < MAX_DEPTH){
float X_rw = ( (float)x /(float)w -0.5f)*Z*XtoZ;
float Y_rw = (0.5f-(float)y / (float)h)*Z*YtoZ;
pReal[i1] = X_rw;
pReal[i2] = Y_rw;
pReal[i3] = Z;
} else {
pReal[i1] = 0.0f;
pReal[i2] = 0.0f;
pReal[i3] = 0.0f;
}
}
// Of Course, the inverse function is
void convertRW2P(float *pReal, float *pDepth,int x, int y, int w, int h) {
int max_i = w * h;
int i1 = (y * w + x),
i2 = i1 + max_i,
i3 = i2 + max_i;
float xR = pReal[i1];
float yR = pReal[i2];
float zR = pReal[i3];
int ixi = (xR/zR/XtoZ + 0.5f)*(float)w + 0.5f; // x
int iyi = (-yR/zR/YtoZ + 0.5f)*(float)h + 0.5f; // y
pDepth[i1] = zR;
}
校準的理念(使用絕對圓錐的影像)
[edit | edit source]x = P (H inv(H)) X H: a projective transformation
無窮遠平面和絕對圓錐
PAI:在 H 下固定
AC:在 H 下固定
ADQ:在 H 下固定(單個方程)
Q = H Q H’ PAI is the null-vector of ADQ (Q a = 0)
DIAC(絕對圓錐的雙重影像)= ADQ 的影像(參見 IAC(絕對圓錐的影像))
W* = K K'(K:校準矩陣)透過 Cholesky 因式分解。
如何從深度相機讀取紅外流
[edit | edit source]http://stomatobot.com/primesense-3dsensor-ir-stream/?goback=.gde_2642596_member_242724626
參考資料
[edit | edit source]- [Queirolo 2010] C. C. Queirolo,Luciano Silva,Olga R. P. Bellon,M. P. Segund,使用表面互穿測度進行 3D 人臉識別:對 FRGC 資料庫的比較評估,使用模擬退火和表面互穿測度進行 3D 人臉識別。IEEE 模式分析與機器智慧彙刊 32(2): 206-219 (2010)。
- [CVonline] CVonline:不斷發展、分散式、非專有、線上的計算機視覺綱要
- [Foerstner04] 不確定性和射影幾何
- 計算微分幾何 dmg.tuwien.ac.at
- 計算幾何演算法庫 [4]
深度感測器
[edit | edit source]PrimeSense www.primesense.com
Kinect - Xbox.com www.xbox.com/KINECT
Xtion PRO LIVE http://www.asus.com/Multimedia/Motion_Sensor/Xtion_PRO_LIVE/
softkinetic http://www.softkinetic.com/
velodynelidar.com http://velodynelidar.com/lidar/lidar.aspx
Leap 簡介 http://www.youtube.com/watch?v=_d6KuiuteIA
Mesa Imaging http://mesa-imaging.ch/
工具
[edit | edit source]http://www.danielgm.net/cc/ CloudCompare - 3D 點雲和網格處理軟體
http://www.cs.unc.edu/~isenburg/lastools/ LAStools:用於快速轉換、過濾、檢視、網格化和壓縮 LiDAR 的屢獲殊榮的軟體
問答
[edit | edit source]- {在此處提出您的問題...}