前言
最近翻閱關(guān)于從2D視頻或者圖片中重構(gòu)3D姿態(tài)的文章及其源碼憔披,發(fā)現(xiàn)都有關(guān)于攝像機參數(shù)的求解,查找了相關(guān)資料屋彪,做一下筆記。
國際慣例绒尊,來一波參考網(wǎng)址
透視變換畜挥、透鏡畸變及校正模型、相機校正(Camera Calibration)婴谱、Matlab相機校正工具箱蟹但、【立體視覺(一)】由基本矩陣、本質(zhì)矩陣恢復(fù)攝像機矩陣——Structure from motion谭羔、Multiple View Geometry in Computer Vision(計算機視覺中的多視角幾何),附matlab代碼?华糖、相機矩陣的分解系列教程、攝像機矩陣詳解(中文版)
【注】本文主要提取倒數(shù)第二個大牛博客的主要內(nèi)容瘟裸,最后一個博客是某位國內(nèi)大神對這位大牛博客的精解客叉,其它部分為圖像知識的補充,主要來源于《OpenGL編程指南》第五章節(jié)话告。博客不在于深究各種細節(jié)實現(xiàn)十办,主要在于對此知識點有所了解,也就是看大牛們的代碼的時候至少要知道我們需要求解的東西是什么超棺,都包含什么參數(shù)向族。對理論沒興趣的可以直接看總結(jié),也可看demo展示.
基本知識復(fù)習(xí)
先看看使用相機的主要步驟:
移動相機到拍攝位置棠绘,鏡頭對準某個方向(視圖變換,view transform)
將拍攝對象一到場景中的某個位置(模型變換,model transform)
設(shè)置相機焦距或調(diào)整縮放比例(投影變換,projection transform)
對結(jié)果圖像拉伸或者壓縮件相,變換為需要的圖片大小(視口變換,viewpoint transform)
其中前兩步可以合并為一個步驟,稱為模型-視圖變換(model-view transform)氧苍,包含多級平移夜矗、旋轉(zhuǎn)、縮放让虐。下圖摘自O(shè)penGL一書紊撕,用于理解對象從一個坐標系統(tǒng)到另一個坐標系統(tǒng)的變換過程
齊次坐標
先看看矩陣乘法在三維坐標變換的缺點:將三維坐標視為一個列向量,那么矩陣*列向量得到的新向量的每一個分量赡突,都是舊的列向量的線性函數(shù)对扶,因而三維笛卡爾坐標與矩陣的乘法只能實現(xiàn)三維坐標的縮放和旋轉(zhuǎn)区赵,而無法實現(xiàn)坐標平移。?
可以發(fā)現(xiàn)將三維的笛卡爾坐標添加一個額外坐標浪南,就可以實現(xiàn)坐標平移了笼才,而且保持了三維向量與矩陣乘法具有的縮放和旋轉(zhuǎn)操作。這個就稱為齊次坐標络凿。而這種變換也稱為仿射變換(affine transformation)骡送,不屬于線性變換(線性變換的一個重要規(guī)則就是(0,0,0)(0,0,0)映射以后仍是(0,0,0)(0,0,0))。
齊次坐標的好處也就顯而易見了:
進一步完成透視變換,也可戳這里絮记,其實第四個分量就是用于實現(xiàn)透視投影變換的摔踱,所有的分量同時處理相同值不會改變它所表達的位置。
使用線性變換完成模型的平移
【注意】我們經(jīng)常將第四個分量記為w怨愤,OpenGL會在顯示幾何體的時候用前三個分量除以第四個分量昌渤,從而將齊次坐標變換為笛卡爾坐標。當w=0.0的時候憔四,表示物體位于無限近的位置膀息,透視效果就是無限大的,所以會產(chǎn)生一些無法預(yù)知的結(jié)果了赵。而且當w是負數(shù)的時候潜支,雖然理論可以,但是負數(shù)w值可能會給圖形管線的某些環(huán)節(jié)帶來麻煩柿汛,當與其它的正數(shù)w進行計插值計算的時候冗酿,導(dǎo)致結(jié)果接近或等于0。避免這個問題的方法就是保證第四個分量w為正络断。
相機矩陣內(nèi)參和外參的分解
何為幾何相機校正(Geometric camera calibration) ?
也稱為相機反切(camera resectioning)裁替,主要用于估計圖像或者視頻攝像機的透鏡和圖像傳感器的相關(guān)參數(shù)。使用這些參數(shù)可以糾正透鏡畸變貌笨,度量真實世界中物體的大小弱判,或者相機在一個場景中的定位。因而可以被用于機器視覺锥惋,去檢測或者度量事物昌腰,也可用于機器人中,幫助導(dǎo)航系統(tǒng)和3D重建膀跌。
相機參數(shù)都有哪些遭商?估計它們需要的條件?評估所估算的相機參數(shù)好壞的標準捅伤?
①主要包含內(nèi)參(intrinsics)劫流、外參(extrinsics)、畸變系數(shù)(distortion coefficients)
②估計參數(shù)需要3D世界坐標及其對應(yīng)的2D圖像點。比如在重構(gòu)3D姿態(tài)的時候祠汇,需要同時輸入圖片及圖片中對應(yīng)的人的骨骼2D坐標點仍秤。
③評估所估計相機參數(shù)的方法就是:首先畫出相機和校準模式的相對位置;隨后計算投影誤差座哩;最后計算參數(shù)的估算誤差徒扶。在matlab中有Camera Calibrator來進行相機校準和評估參數(shù)精確度粮彤。
相機矩陣的表示根穷?缺點?
假設(shè)有一個3?43?4的相機矩陣导坟,可以將齊次3D坐標轉(zhuǎn)換為2D圖像坐標屿良。矩陣表示如下?
P=[M|?MC]
這里的’||’代表的是增廣矩陣。其中MM代表可逆的3?3矩陣惫周,C是列向量尘惧,代表世界坐標系中相機位置。
相機矩陣可以將3D點投影到2D空間递递,但是有些缺點:
沒有提供相機的擺放姿態(tài)
沒有聽相機的內(nèi)部幾何特征
不能使用鏡面光照喷橙,因為無法在相機坐標系中得到表面法線向量。
相機矩陣的分解登舞?
相機矩陣分解
為了解決上述問題贰逾,可以將相機矩陣分解為兩個矩陣的乘積:內(nèi)參矩陣K和外參矩陣[R|?RC]
P=K[R|?RC]
其中,3?3的上三角陣KK描述了相機的內(nèi)參比如焦距菠秒;3?3的旋轉(zhuǎn)矩陣R的列表示相機參考幀的世界坐標軸方向疙剑;向量C是世界坐標系中的相機中心。那么向量t=?RC就給出了相機坐標系中的世界原點位置践叠。我們需要做的就是求解這些參數(shù)言缤,當然前提是我們已經(jīng)知道P了。
相機中心的求解比較簡單禁灼,利用分解前的相機矩陣管挟,由于P的最后一列是由?MC得到的,而MM在原始的相機矩陣的前3?3部分已經(jīng)給出了弄捕,所以只需要用?M?1左乘它即可哮独。
首先注意旋轉(zhuǎn)矩陣R是正交的,因為每一列代表的是一個軸(想想三維坐標系的xyz軸是不是垂直的)察藐;而內(nèi)參矩陣K是一個上三角陣皮璧。然后考慮到QR分解的用途就是將一個滿秩矩陣分解為上三角陣和正交陣的乘積。算法好像不難分飞,matlab的寫法如
function[R Q]=rq(M)
[Q,R]= qr(flipud(M)')
R = flipud(R');??
?R =fliplr(R);? ??
Q =Q';? ? ?
?Q =flipud(Q);
但是發(fā)現(xiàn)QR分解的結(jié)果不唯一悴务,對K的任何一列以及R的對應(yīng)行取反(negative)都不會導(dǎo)致相機矩陣結(jié)果的改變。
如果滿足如下兩個條件,可以讓K的對角元為正
圖像的X/Y軸所指方向與相機的X/Y軸方向相同
相機處于z軸正方向
所以可以取QR分解中讯檐,使得KK的對角元為正的解羡疗,讓KK對角元為正的代碼如下
# make diagonal of K positive
T =diag(sign(diag(K)));
K = K * T;
R = T * R;? # (T is its own inverse)
然而在實際中,照相機和圖片的軸經(jīng)常不統(tǒng)一别洪,所以K的對角元也不應(yīng)該是正的叨恨,如果強制它們?yōu)檎瑢?dǎo)致一些不好的副作用挖垛,包含:
對象位于相機錯誤的一邊
旋轉(zhuǎn)矩陣行列式為?1而不是1
不正確的鏡面光照(?specular lighting)
出現(xiàn)視覺幾何無法被渲染問題痒钝,原因在于具有負的w坐標
如果從全正的對角元開始,你需要做的就是:
如果圖像x軸和攝像機x軸指向相反方向痢毒,將K的第一列以及R的第一行取反
如果圖像y軸和攝像機y軸指向相反方向送矩,將K的第二列以及R的第二行取反
如果相機俯視是z軸負方向,將K的第三列以及R的第三行取反哪替。
如果R的行列式置為?1栋荸,將它取反
以上每一步都能保證相機矩陣不變,最后一步等價于將整個相機矩陣P乘以?1凭舶。因為P的操作是基于齊次坐標系的晌块,所以將它乘以任何的常量都無影響。
當然可以使用向量t=?RC去檢查結(jié)果帅霜,此式代表的是在相機坐標系中的世界坐標系原點匆背。如果都沒錯,那么tx,ty,tz應(yīng)該能夠反映出在世界原點在相機中的位置(分別指出在中心左邊/右邊义屏,上邊/下邊靠汁,相機的前面/后面)
相機矩陣求解
前面看了如何將相機矩陣分解為內(nèi)參和外參矩陣的乘積。
相機的外參矩陣描述的是世界坐標中相機的位置闽铐,及其指向方向蝶怔。有兩個成分:旋轉(zhuǎn)矩陣R和平移向量t。它們并非恰好對應(yīng)相機的旋轉(zhuǎn)和平移兄墅。
外參矩陣以剛體變換矩陣的形式可以記為:左邊一個3?3旋轉(zhuǎn)矩陣踢星,右邊一個3?1的平移列向量?
常見的做法是在底部增加一行(0,0,0,1),這使得矩陣為方形的隙咸,允許我們進一步將矩陣分解為旋轉(zhuǎn)和平移矩陣?
這個矩陣描述的就是如何將世界坐標系中的點變換都相機坐標系中沐悦,向量tt描述的是世界坐標系原點在相機坐標系中的位置,RR的列代表的是相機坐標系中世界坐標系軸的方向五督。
從上可以發(fā)現(xiàn)藏否,外參主要作用就是描述世界坐標系到相機坐標系的轉(zhuǎn)換。與我們經(jīng)常想的相機坐標系到世界坐標系的轉(zhuǎn)換剛好相反充包。
如何從相機姿態(tài)中求解外參矩陣副签?
實際中遥椿,直接指定相機的姿態(tài)比指定世界坐標系中的點如何轉(zhuǎn)換到相機坐標系中更加自然,通過建立一個剛體變換矩陣描述相機姿態(tài)淆储,然后對其取逆即可建立相機的外參矩陣冠场。
因而可以這樣做:定義一個描述相機中心在世界坐標系中的位置的向量C,然后讓Rc代表相機在世界坐標系旋轉(zhuǎn)到當前姿態(tài)需要的旋轉(zhuǎn)矩陣本砰。那么描述相機姿態(tài)的變換矩陣就是(Rc|C)碴裙。同樣在底部添加一個行向量(0,0,0,1),那么外參矩陣就是相機姿態(tài)矩陣的逆
倒數(shù)第三個等式變換到倒數(shù)第二個等式点额,使用的轉(zhuǎn)置是因為Rc是正交陣舔株,證明戳此處?,此外,平移矩陣的逆就是他的負數(shù)平移向量咖楣,進而可以得到外參矩陣參數(shù)和相機姿態(tài)是直接相關(guān)的:
不要混淆了世界坐標系的變換RR和相機坐標系的變換CC
此網(wǎng)址有demo展示督笆。
內(nèi)參矩陣
內(nèi)參矩陣是將3D相機坐標變換到2D齊次圖像坐標芦昔。透視投影的一個理想模型就是針孔相機诱贿。
內(nèi)參矩陣如下?
其中每一個參數(shù)都有實際意義。
表示焦距的參數(shù):fx,fy
焦距就是真空與圖像平面(投影屏幕)的距離咕缎,類似于人眼和視網(wǎng)膜珠十,焦距的度量是針對像素的。針孔相機的fx,fy有相同的值凭豪。上圖中紅線部分就是焦距焙蹭。但是在實際中,fx和fy一般不同嫂伞,因為
數(shù)碼相機傳感器的缺陷
后處理中圖像被非均勻縮放
相機透鏡導(dǎo)致的無意的失真
相機使用了失真的格式孔厉,透鏡將寬屏場景壓縮到標準大小的傳感器中
相機校準的誤差
主點偏移x0,y0
相機的主軸是與圖像平面垂直且穿過真空的線,它與圖像平面的焦點稱為主點帖努。
主點偏移就是主點位置相對于圖像平面(投影面)的位置撰豺。上圖中,增加x0的值相當于把針孔向右移動拼余,等價將投影面向左移動同時保持針孔位置不變污桦。
軸傾斜
軸傾斜會導(dǎo)致投影圖像的形變。
焦距-從像素到世界單元
內(nèi)參矩陣只關(guān)心相機坐標和圖像坐標之間的關(guān)系匙监,與相機的絕對尺寸無關(guān)凡橱。針對焦距和主點偏移使用響度單元可以表示相機的相對尺寸,換句話說就是投影面的位置與其尺寸(以像素為單位)相關(guān)亭姥。
另一種說法是內(nèi)參相機變換與相機的幾何均勻縮放無關(guān)稼钩,利用像素單元表示尺寸,可以捕捉到這種不變性达罗。
可以使用相似三角形將像素單元轉(zhuǎn)換到世界單元中坝撑,前提是你知道世界單元中至少一個相機尺寸。比如你知道相機的投影面(數(shù)字傳感器)寬度為W毫米,圖片寬度(像素為單位)為w绍载,那就可以將焦距fx轉(zhuǎn)換為世界單元?
其它的參數(shù)fy,x0,y0也可以被轉(zhuǎn)換為對應(yīng)的世界單元Fx,X0,Y0
2D變換中的相機內(nèi)參的計算
將內(nèi)參矩陣分解為切變(shear,類似于將長方形壓成平行四邊形的變形方式)诡宗、縮放,平移變換击儡,分別對應(yīng)軸傾斜塔沃、焦距、主點偏移?
第二個等式右邊三個矩陣依次是:2D平移阳谍、2D縮放蛀柴、2D切變
另一種等價的分解是將切變放在縮放前面?
有一點需要注意:內(nèi)參不影響可見性——阻隔對象(occluded objects)在圖像空間中無法通過簡單的2D變換顯示出來。這里的occluded objects就是那些你希望看到矫夯,但是由于某些原因看不到的對象鸽疾,比如目標跟蹤的時候,一個目標被另一個目標遮擋了训貌。
總結(jié)
綜上可以發(fā)現(xiàn)相機矩陣可以通過如下方法被分解:
全相機矩陣被分解為內(nèi)參和外參矩陣
外參矩陣指示3D旋轉(zhuǎn)和平移
內(nèi)參矩陣指示2D變換
整個分解方法如下?
戳此處有交互式demo
demo中提供了三種外參接口(世界坐標系制肮,相機坐標系,look-at)递沪,三種交互效果不同豺鼻,前兩種的方向相反,世界坐標系中向左移動表示相機坐標系中向右移動款慨,但是它們都有六個參數(shù)控制:
tx 表示沿著水平方向移動相機
ty表示沿著垂直方向移動相機
tz表示沿著前后方向移動相機
px表示鏡頭不平移儒飒,但是繞x軸做俯仰旋轉(zhuǎn)
py表示鏡頭不平移,但是繞垂直軸y軸做左右搖頭旋轉(zhuǎn)
pz表示鏡頭不平移檩奠,但是繞z軸做順時針(或者逆時針)旋轉(zhuǎn)
demo也提供了內(nèi)參的接口桩了,包括四個參數(shù)控制:
焦距(Focal length):鏡頭的前后縮進(不是縮放)
軸傾斜(Axis Skew):可以導(dǎo)致球變形,平面上顯示橢球形
x0表示主點偏移埠戳,相機不動井誉,左右移動成像平面
y0表示主點偏移,相機不動乞而,上下移動成像平面