OpenMVG (open Multiple View Geometry):開源多視角立體幾何庫,這是一個cv屆處理多視角立體幾何的著名開源庫,信奉「簡單,可維護」,提供了一套強大的接口,每一個模塊都被測試過,盡力提供一致可靠的體驗。git
openMVG可以:數據結構
解決多視角立體幾何的精準匹配問題;框架
提供一系列SfM須要用到的特徵提取和匹配方法;iview
完整的SfM工具鏈(校訂,參估,重建,表面處理等);ide
openMVG盡力提供可讀性性強的代碼,方便開發者二次開發,核心功能是儘可能精簡的,因此你可能須要其它庫來完善你的系統。openMVG分紅了幾個大的模塊:函數
核心庫:各個功能的核心算法實現;工具
樣例:教你怎麼用;post
工具鏈:也就是連起來用咯(亂序圖像集的特徵匹配,SfM,處理色彩和紋理);
第一步固然是從github clone代碼,而後按照 BUILD 說明操做,須要注意的是:
建議和opencv一塊兒編譯,方法是在CMakeLists.txt
文件中修改相應選項爲 ON,而後在cmake的GUI中添加一個叫OpenCV_DIR
的入口,值就是你已經安裝好的opencv的路徑。
openMVG寫的很是不錯,對Windows也提供了良好的支持,因此cmake以後用VS打開生成的openMVG.sln
解決方案就能夠進行編譯了,編譯的時間稍久。我用的VS2013不支持C++新特性:constexpr
,因此建議你使用VS2015或更新版本,若是必定要用VS2013,能夠這樣作:在src/openMVG/cameras/Camera_Common.hpp
文件中將有constexpr
的地方直接去掉,或者改爲模板函數也是能夠的:
template <class T> inline T operator|(T x, T y){ return static_cast<T>(static_cast<int>(x) | static_cast<int>(y)); };
運行樣例,這裏遇到一個坑:DenseStoraage.h line 86
報錯:R6010 Assertion failed
,這是一個斷言錯誤,在release模式下不會出現,但在debug模式下幾乎是必現。緣由嘛,打開Eigen給出的網址能夠明確:數據結構未對齊(unaligned arrays)。這個問題對於剛接觸openMVG的人來講仍是很煩人的,openMVG代碼很優雅,不少數據類型都是從模板類或函數延伸,經過虛函數擴展各項具體方法,並且很是強烈的依賴Eigen這個庫,因此給定位問題帶來了阻礙。通過一天的攻堅,最後大概確認了緣由:
regions.h
這個文件中定義的Regions
類包含了fixed-size vectorizable Eigen types的stl容器vector,按照Eigen提供的解決方法,須要作的是:
//原來 typedef std::vector<FeatureT> FeatsT; //改爲 typedef std::vector<FeatureT, Eigen::aligned_allocator<FeatureT>> FeatsT; //其它相似的地方都要改,包括返回vector的函數,最好也加上 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
openMVG提供一個基本的類用做圖像容器:Image<T>
,T表明像素類型,這個類能夠處理灰度,RGB,RGBA或者自定義類型的圖像。用法很簡單:
// A 8-bit gray image: Image<unsigned char> grayscale_image_8bit; // Multichannel image: (use pre-defined pixel type) // A 8-bit RGB image: Image<RGBColor> rgb_image_8bit; // 8-bit RGBA image Image<RGBAColor> rgba_image_8bit; Image<Rgba<unsigned char> > rgba_image2_8bit;
這裏的 RGBColor
,RGBAColor
等是openMVG基於Eigen定義好的類型,具體是定義在pixel_types.hpp
中。
openMVG支持ppm/pgm
,jpeg
,png
,tiff
格式的圖片文件,例子:
Image<RGBColor> rgb_image_gray; bool bRet = ReadImage("Foo.imgExtension", &rgb_image);
用於在圖像上畫圓,橢圓,直線等。
openMVG從新包裝了Eigen的基本類型和算法,以便更簡單的調用。好比 Vec2
表明一個二維點(char型)。
這個模塊主要是提供特徵容器的封裝,包括特徵,特徵描述,關鍵點集等,基本都是模板類,好比頂一個sift特徵描述子能夠這樣作:
// SIFT like descriptor typedef Descriptor<float, 128> siftDescriptorData;
此模塊提供不一樣的相機模型的抽象類,包括:
最簡單的相機模型,如圖:
相機模型包括內參和外參,關鍵詞也就是你們熟悉的幾樣:投影矩陣,旋轉、平移矩陣,焦距、主點等,具體參見說明。
看一個例子:openMVG提供的PinholeCamera
類:
/// Pinhole camera P = K[R|t], t = -RC struct PinholeCamera { //構造函數 PinholeCamera( const Mat3 & K = Mat3::Identity(), const Mat3 & R = Mat3::Identity(), const Vec3 & t = Vec3::Zero()) : _K(K), _R(R), _t(t) { _C = -R.transpose() * t; P_From_KRt(_K, _R, _t, &_P); } PinholeCamera(const Mat34 & P) { _P = P; KRt_From_P(_P, &_K, &_R, &_t); _C = -_R.transpose() * _t; } /// Projection matrix P = K[R|t] Mat34 _P; /// Intrinsic parameter (Focal, principal point) Mat3 _K; /// Extrinsic Rotation Mat3 _R; /// Extrinsic translation Vec3 _t; /// Camera center Vec3 _C; };
這部分是比較基礎和重要的模塊之一,包括了:
多視角集幾何中n(>=2)視角的求解算法;
將這些求解算法綜合起來以便進行魯棒估計的通用框架——Kernel;
文檔中講解了單應矩陣,本徵矩陣,本質矩陣,位置矩陣等的概念,講得很是好,建議仔細閱讀文檔。
簡單的解釋一下:
單應矩陣:描述兩個投影平面之間的關係;
本徵矩陣:同一個場景在兩個相機成像下的關係,也就是物體上的點A在兩個視角下成像位置的關係;
本質矩陣:基於本徵矩陣和內參矩陣創建,描述相機和本徵矩陣位置之間的相對關係;
位置矩陣:估計相機的絕對位置(被轉化爲一個最小化問題求解);
Kernel:一個將求解器、數據、度量方案等結合起來的類,這個類將用於魯棒的估計以上的參數和矩陣;
一個用於求解多視角幾何中線性優化(參數估計)的工具集,文檔。
提供一些列魯棒估計方法,好比:Max-Consensus,Max-Consensus,AC-Ransac A Contrario Ransac等。
提供的接口包括:NNS,K-NN,FLANN,KVLD,Cascade hashing Nearest Neighbor等。這些接口可用於在二維或三維點集,以及更高維的特徵描述集中。
多視幾何裏的追蹤是指在一系列的圖片中找到對應的特徵點(同一點在不一樣視角下的位置)。
openMVG提供的sfm模塊包含了處理SfM問題的一系列方法個數據存儲接口,例如相機位置估計,結構測量,BA等。SfM_Data
類包含了SfM全部的輸入:
struct SfM_Data { /// Considered views Views views; // 包含圖像文件名,id_view,id_pose,id_intrinsic,image size。 /// Considered poses (indexed by view.id_pose) Poses poses; // 相機的三維位置 /// Considered camera intrinsics (indexed by view.id_cam) Intrinsics intrinsics; // 相機內參 /// Structure (3D points with their 2D observations) Landmarks structure; // 二維視圖特徵關聯的3D點 }
個人codepen連接:codepen