博客園排版系統真的比較挫,可以訪問我的github.io閱讀
關於Unit的概念
在pmvs的源代碼中,有一個函數是getUnit ,其函數如下(在PMVS2的windows版本代碼,optim.cc文件,1184行):
float Coptim::getUnit(const int index, const Vec4f& coord) const {
const float fz = norm(coord - m_fm.m_pss.m_photos[index].m_center);
const float ftmp = m_ipscales[index];
if (ftmp == 0.0)
return 1.0;
return 2.0 * fz * (0x0001 << m_fm.m_level) / ftmp;
}
其中index是圖像編號,coord是三維射影空間下的坐標。
這個函數在pmvs代碼中幾乎所有的和空間幾何計算相關的函數中均被調用,最開始看代碼時我並沒有特別注意,但是隨着代碼閱讀的深入,發現如果不將該函數讀懂,就完全無法理解pmvs中所有的幾何計算函數究竟是在做什么,於是今天花時間特意鑽研了下,把該函數的含義表達清楚。
先說結論:該函數是計算將圖片上的一個像素反投影到空間的一個指定的面片(patch)上得到的正方形的大小(以世界坐標系中的距離為量度),這個面片滿足如下條件——面片的中心位於coord, 面片的法線與相片的法線平行但方向相反(也就是論文中初始化patch時的法線計算方法)。
這個結論看起來非常復雜,簡單說就是如果我在空間的某個坐標處想要畫一個正方形,使得該正方形投影到對應的與該正方形平行的相片上的大小恰好是1×1像素大小,那么這個正方形的邊長在世界坐標系中的表達究竟是多少。這個函數就是來求解這個邊長的。
這樣的話這個函數作用其實就相當大了,他直接溝通了像素坐標和空間坐標的比例關系,可以粗略的比較相片對於場景的縮放,簡化很多投影和反投影計算。而這個函數用到的計算方法其實也非常簡單。就是簡單的相似三角形關系,具體解釋如下
小孔成像相機的幾何關系如下圖所示(摘自《 Multiple View Geometry in Computer Vision 》)

從該成像原理上我們可以看出,空間中一個長度為\(D\) 的物體投影到圖像上長度\(l\)滿足如下關系:
其中\(f\) 為焦距,\(Z_0\) 為物體到攝影中心的距離。
由上式可以得到:
這樣我們已知\(l\) 為1個像素長度,\(Z_0\) 可以直接由coord到相片的攝影中心直接計算得到。那么只要我們知道以像素為單位的\(f\)的數值,就可以直接得到\(D\)。幸運的是,根據一般CCD相機內參數矩陣中各變量的定義:
其中\(a_x\)和 \(a_y\)分別是相機在x和y方向上的焦距,且以像素為量綱。另外一般情況下,CCD相機在x和y方向上的比例因此近似相等,即\(a_x \approx a_y\),這樣我們可以用下式來近似計算\(f\)
綜上可得:
這就是pmvs中getUnit的計算方法, 特別解釋下,代碼中m_ipscales[index]就是提前計算好的\(a_x+a_y\)的數值,而(0x0001 << m_fm.m_level)則是一個比例因子,可以讓程序將圖像縮放到一半或者四分之一大小進行計算。
