|
論文閱讀模塊將分享點云處理,SLAM,三維視覺,高精地圖相關的文章。公眾號致力于理解三維視覺領域相關內(nèi)容的干貨分享,歡迎各位加入我,我們一起每天一篇文章閱讀,開啟分享之旅,有興趣的可聯(lián)系微信dianyunpcl@163.com。 單應矩陣介紹 單應性在計算機視覺領域是一個非常重要的概念,它在圖像校正、圖像拼接、俯視圖生成,相機位姿估計、視覺SLAM等領域有非常重要的作用。 單應性(Homography)變換是將一幅圖像中的點映射到另一幅圖像中相應點的變換關系: 單應矩陣是一個3x3矩陣,具有8個自由度,通常為歸一化后表達式,其尺度為1。 下面展示了不同類型的變換,但都與兩個平面之間的變換有關。 (1)真實平面和圖像平面 (2)由兩個相機位置拍攝的平面 (3)圍繞其投影軸旋轉(zhuǎn)的相機采集的圖像進行拼接 所以單應性矩陣主要用來解決兩個問題: 一是表述真實世界中一個平面與對應它圖像的透視變換 二是從通過透視變換實現(xiàn)圖像從一種視圖變換到另外一種視圖 外參求解單應矩陣理論 這里將主要講解以下已知兩個相機的位姿如何實現(xiàn)圖像的拼接,主要公式就是根據(jù)外參計算H矩陣。 單應性將兩個平面之間的變換聯(lián)系起來,這樣就可以計算出從第二個平面視圖轉(zhuǎn)到第一個平面視圖下相應相機位移,在已知內(nèi)外參的情況下有 使用齊次坐標系表達式將三維世界點轉(zhuǎn)轉(zhuǎn)到相機坐標系下: 使用矩陣乘法可以輕松地將一圖像幀中表示的點轉(zhuǎn)換為另一幀圖像中:c1Mo是第一幀的位姿,c2Mo是第二幀的位姿。要將相機1中表示的三維點變換為相機2幀的坐標下,其變換公式為: 以上公式對應的是:同一平面兩個不同相機坐標系的單應矩陣。如果要同一平面計算出兩個圖像間的單應矩陣H,則需要內(nèi)參,此時左邊乘以K,右邊乘以K的逆矩陣。 為了更好的理解,這里寫了一個demo,并與上述的理論對應(注意這里是將第二幀轉(zhuǎn)到第一幀的坐標系下)。 Mat cameraMatrix = (Mat_<double>(3, 3) << 700.0, 0.0, 320.0, 0.0, 700.0, 240.0, 0, 0, 1);Mat R1 = c1Mo(Range(0, 3), Range(0, 3));Mat R2 = c2Mo(Range(0, 3), Range(0, 3)); //c1Mo * oMc2Mat R_2to1 = R1*R2.t();//同一平面兩個不同相機坐標系的單應矩陣// [compute-homography]Mat H = cameraMatrix * R_2to1 * cameraMatrix.inv();//同一平面計算出兩個圖像間的單應矩陣HH /= H.at<double>(2, 2);//歸一化cout << "H:\n" << H << endl;根據(jù)求解的單應矩陣實現(xiàn)兩個視圖的拼接實例顯示如下 拼接的結(jié)果如下: warpPerspective(img2, img_stitch, H, Size(img2.cols * 2, img2.rows)); Mat half = img_stitch(Rect(0, 0, img1.cols, img1.rows));完整代碼如下: void basicPanoramaStitching(const string &img1Path, const string &img2Path){ Mat img1 = imread("Blender_Suzanne1.jpg"); Mat img2 = imread("Blender_Suzanne2.jpg"); //! [camera-pose-from-Blender-at-location-1] Mat c1Mo = (Mat_<double>(4, 4) << 0.9659258723258972, 0.2588190734386444, 0.0, 1.5529145002365112, 0.08852133899927139, -0.3303661346435547, -0.9396926164627075, -0.10281121730804443, -0.24321036040782928, 0.9076734185218811, -0.342020183801651, 6.130080699920654, 0, 0, 0, 1); //! [camera-pose-from-Blender-at-location-1] //! [camera-pose-from-Blender-at-location-2] Mat c2Mo = (Mat_<double>(4, 4) << 0.9659258723258972, -0.2588190734386444, 0.0, -1.5529145002365112, -0.08852133899927139, -0.3303661346435547, -0.9396926164627075, -0.10281121730804443, 0.24321036040782928, 0.9076734185218811, -0.342020183801651, 6.130080699920654, 0, 0, 0, 1); //! [camera-pose-from-Blender-at-location-2] Mat cameraMatrix = (Mat_<double>(3, 3) << 700.0, 0.0, 320.0, 0.0, 700.0, 240.0, 0, 0, 1); Mat R1 = c1Mo(Range(0, 3), Range(0, 3)); Mat R2 = c2Mo(Range(0, 3), Range(0, 3)); //c1Mo * oMc2 Mat R_2to1 = R1*R2.t(); //! [compute-homography] Mat H = cameraMatrix * R_2to1 * cameraMatrix.inv(); H /= H.at<double>(2, 2); cout << "H:\n" << H << endl; //! [compute-homography] //! [stitch] Mat img_stitch; warpPerspective(img2, img_stitch, H, Size(img2.cols * 2, img2.rows)); Mat half = img_stitch(Rect(0, 0, img1.cols, img1.rows)); img1.copyTo(half); //! [stitch] Mat img_compare; Mat img_space = Mat::zeros(Size(50, img1.rows), CV_8UC3); hconcat(img1, img_space, img_compare); hconcat(img_compare, img2, img_compare); imshow("Compare images", img_compare); imshow("Panorama stitching", img_stitch); waitKey(); }以上是根據(jù)外參實現(xiàn)了同一相機不同位姿采集的圖像的拼接,其主要原理主要是根據(jù)外參計算出單應性矩陣,將第二幀采集的圖像變換到第一幀視角下的結(jié)果,最終實現(xiàn)拼接。這里我想到了前視圖轉(zhuǎn)換俯視圖的方法,同樣也是變換視角的問題,只是這里的俯視圖的虛擬相機的參數(shù)需要自己設置,有時間再更新。 資源 三維點云論文及相關應用分享 【點云論文速讀】基于激光雷達的里程計及3D點云地圖中的定位方法 3D-MiniNet: 從點云中學習2D表示以實現(xiàn)快速有效的3D LIDAR語義分割(2020) win下使用QT添加VTK插件實現(xiàn)點云可視化GUI PCL中outofcore模塊---基于核外八叉樹的大規(guī)模點云的顯示 更多文章可查看:點云學習歷史文章大匯總 SLAM及AR相關分享 【論文速讀】AVP-SLAM:自動泊車系統(tǒng)中的語義SLAM 【點云論文速讀】StructSLAM:結(jié)構(gòu)化線特征SLAM |
|
|