當初選方向時就因為從小幾何就不好、缺乏空間想像能力才沒有選擇攝影測量方向而是選擇了GIS。昨天同學找我幫他做圖像匹配,這我哪里懂啊,無奈我是一個別人有求於我,總是不好意思開口拒絕的人。於是乎就看着他給的一章節內容開始寫程序了,今天總算給他完成了。做的比較簡單,中間也遇到了不少問題,尤其是計算量大的問題,由於老師給的數據是粗配准過的數據, RANSAC算法評估時就簡化了下。
理論內容:
第5章 圖像配准建立幾何變換模型
特征點建立匹配關系之后,下一步就是求解圖像之間的變換關系。仿射變換能夠很好的表達圖像之間的一般變換,並且最少只需要3對匹配點就可以求解。由於之前用的匹配算法不能保證沒有誤匹配(實際上是存在誤匹配的),本文將采用RANSAC方法來估計兩幅圖像之間的仿射變換關系。如果有足夠多的圖像特征匹配符合某一個特定的仿射變換,則我們認為當前匹配滿意,反之,我們進行下一次估計。
5.1 RANSAC算法
RANSAC(RandomSample Consensus),即隨機采樣一致算法,准確來說是一種從一組包含噪聲的觀測數據中通過迭代的方式估計出數據所滿足的某個數學模型的參數的算法。由Fischler和Bolles於1981年提出,是目前廣泛使用的一種剔除誤匹配點的方法。
5.2 仿射變換
仿射變換(Affine Transform)是一種仿射平面到自身的變換,它能夠保持點的共線性(Parallelism,即保持二維圖形之間相對位置關系不變,平行仍是平行,相交直線的交角不變)和直線的平行性(Straightness,即變換后圓弧還是圓弧,直線還是直線)。仿射變換是配准中最常用的一類轉換模型,在幾何學中有專門的仿射幾何分支,並將仿射變換被看成一個平行的投影鏈。
仿射變換可用以個三乘三的矩陣表示,最后一行為(0,0,1)。該變換矩陣將原坐標(x,y)變為(x`,y`)。
變換矩陣為:
我們在空間幾何信息檢驗中,認為如果兩幅圖像描述的是同一個物體或場景,由於圖片大小,位置和角度的不同,兩幅圖像中相應的興趣點的位置信息應該滿足某一個仿射變換關系。因此,我們以兩幅圖像之間的特征匹配作為數據來估計仿射變換矩陣,如果能找到一個足夠多特征匹配都服從的仿射變換,則認為當前匹配讓人滿意。
5.3 RANSAC仿射變換空間檢驗
空間檢驗就是通過RANSAC算法,根據圖像之間的特征匹配信息,估計出一個仿射變換模型。
我們用下式來表示仿射變換矩陣
其中m1,m2,m3,m4體現尺度和旋轉特性,tx是x方向上的平移,ty是y方向上的平移。
則一對匹配點的坐標可以寫成
或者寫成
其中,(x,y)是變換前,(u,v)是變換后的坐標。
為了解求仿射變換參數,對上式做一下變形:
可寫成A*x=b,則模型參數x的值
要解六個參數,至少需要三對特征匹配,因此RANSAC隨機采樣每次需要三對數據來估計仿射變換矩陣。
介紹完相關概念和理論,下面是RANSAC空間幾何信息檢驗的流程:
1. 數據准備:找到兩幅圖像(I1和I2)之間的匹配點對和坐標信息。
2. 模型估計:假設有n>3對的匹配點對,隨機選取3對,根據公式解求仿射變換模型參數m1,m2,m3,m4,tx,ty。
3. 模型評估:對圖像I1中所有的已匹配的點(x,y)做上述仿射變換,得到一系列變換后的坐標(u`,v`)。將這些得到的坐標和I2中對應的匹配點(u,v)求歐氏距離,即仿射變換的估計誤差E。並用I2中相應特征點的尺度信息做歸一化,這樣每一個特征匹配可以求出一個歸一化的估計誤差,最終得到一個估計誤差向量。
4. 根據估計誤差向量確定一個誤差閾值T(該怎么確定閾值?),估計誤差向量中低於T的對應的特征匹配為Inliers。
5. 如果Inliers數目大於目前最大的Inliers數目,則當做找到了當前最好的放射變換,保存此變換(我看到網上說要對其做局部優化,將所有滿足當前最好的仿射變換的Inliers匹配點對,重新做母性估計和模型評估並保存仿射變換信息。一般說來,經過局部優化的新放射變換通常會有更多Inliers,是什么意思啊?)
6. 重復2到6步驟,最終得到的仿射變換認為是I1和I2之間最好的放射變換模型。
這里記錄下做的流程:
(1)推導六參數計算公式,編寫仿射變換六參數類(由於之前沒有檢查數據,數據中有幾組重復的,導致一直報“嘗試除以零”這個錯誤);
代碼如下:
/* * 求解仿射變換模型參數的類 * @ 劉碩編制 */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ImageMatching { class ParameterHelper { public int[] X_Cor { get; set; } public int[] Y_Cor { get; set; } public int[] U_Cor { get; set; } public int[] V_Cor { get; set; } //仿射變換模型六參數 public double m1 { get { return ((U_Cor[1] - U_Cor[0]) - m2 * (Y_Cor[1] - Y_Cor[0])) / (X_Cor[1] - X_Cor[0]); } } public double m2 { get { return ((U_Cor[1] - U_Cor[0])*(X_Cor[2] - X_Cor[0]) - (U_Cor[2] - U_Cor[0])*(X_Cor[1] - X_Cor[0])) / ((Y_Cor[1] - Y_Cor[0])*(X_Cor[2] - X_Cor[0]) - (Y_Cor[2]- Y_Cor[0])*(X_Cor[1] - X_Cor[0])); } } public double m3 { get { return ((V_Cor[1] - V_Cor[0]) - m4 * (Y_Cor[1] - Y_Cor[0])) / (X_Cor[1] - X_Cor[0]); } } public double m4 { get { return ((V_Cor[1] - V_Cor[0]) * (X_Cor[2] - X_Cor[0]) - (V_Cor[2] - V_Cor[0]) * (X_Cor[1] - X_Cor[0])) / ((Y_Cor[1] - Y_Cor[0]) * (X_Cor[2] - X_Cor[0]) - (Y_Cor[2] - Y_Cor[0]) * (X_Cor[1] - X_Cor[0])); } } public double tx { get { return U_Cor[0] - m1 * X_Cor[0] - m2 * Y_Cor[0]; } } public double ty { get { return V_Cor[0] - m3 * X_Cor[0] - m4 * Y_Cor[0]; } } } }(2 )對所有匹配點計算組合數,按RANSAC隨機采樣每次需要三對數據來估計仿射變換矩陣,則共有(C n 3 *C n 3)種組合情況,計算量相當大。
(3)求解完仿射變換模型六參數后,則要進行模型評估。即計算歸一化誤差,得到歸一化誤差向量。
(4)確定閾值,計算Inliers數。這里參照論文,閾值取所有歸一化誤差的均值(按說應該取自適應閾值,奈何不懂啊)。
(5)比較所有組合的Inliers數,得到最優仿射變換,並保存。
(6)輸出仿射變換六參數及匹配后坐標
歡迎留言拍磚!