1. 程式人生 > >OpenMVG、OpenMVS配置及學習記錄(Win10+VS2015)

OpenMVG、OpenMVS配置及學習記錄(Win10+VS2015)

更新於2018年7月24日
經過了近一年的學習,總結各方面經驗,還是極其強烈的建議初入三維重建的朋友幾點:
1.不要在Windows系統下裝openmvg和openmvs了,直接用上Linux系統吧,Ubuntu14.04或者16都可以,openmvg和openmvs在Linux上的安裝簡直不要太簡單,百度去兩個庫的主頁,通過命令列就全部安裝好了,真的很方便,而且既然接觸程式設計,使用Linux也是很好的選擇。不要再在Windows下掙扎了!
2.目前視覺SLAM很火,而且和三維重建有很多交叉,只是側重不同,目前沒有好的入門三維重建的書,但是入門SLAM的書有一本很好的,視覺SLAM十四講,通過這本書的學習,你也將會對三維重建有更好的瞭解及基礎。

更新於2017年5月12日。

最近開始在做基於二維影象的三維重建專案,OpenMVG和OpenMVS可謂是必不可少的兩個庫,但網上配置及學習資料太少,花了整整一個月的時間才將庫配置好,過程可謂艱難。本人也是入門級,此貼的目的在於將自己的經驗分享給大家,給後來者提供一些方向和提示,望多交流,批評指正,建群一起學習。
OpenMVS是在OpenMVG的基礎上的進一步操作,因此我們先來配置OpenMVG。

1、OpenMVG配置

首先需要一臺比較“乾淨”的電腦,因為配置過程會用到許多的第三方庫,以及對系統環境的配置,若電腦內已經裝了類似opencv、boost等的,容易出現版本不匹配等各種意想不到的錯誤,因此建議還是刪乾淨,或者是在虛擬機器裡搭(前提是電腦配置夠好,不然跑不動程式),或者是用一臺新的電腦,由於我筆記本之前就做影象處理,因此亂七八糟的東西很多,配了半個多月都沒配好,最後還是在一臺新的桌上型電腦上配置好的。另外,我的基本環境是Win10+VS2015,其他的環境沒試過,不能保證可行。
第二點是,本文在配置階段主要參考了http://blog.csdn.net/mitsubishisony/article/details/52332470,然後根據自己的實際操作過程進行了一些補充,具體內容大家可以在http://download.csdn.net/detail/weixin_36408769/9838169下載。前面也說到,整個配置過程會使用到不少的第三方庫,為了大家方便,特將相關的安裝包提供給大家,共有三個壓縮包1:http://download.csdn.net/detail/weixin_36408769/9838075  2:http://download.csdn.net/detail/weixin_36408769/9838077  3:http://download.csdn.net/detail/weixin_36408769/9838150。大家下載好後先把第三個安裝包的cmake及git安裝好。由於上傳檔案大小的限制,還有幾個太大的檔案放網盤了:連結:http://pan.baidu.com/s/1dF5oYtV 密碼:2hdl。最後VS2015社群版的安裝映象檔案也放在了網盤連結:http://pan.baidu.com/s/1pKCLPEF 密碼:s9df,大家下一個虛擬光碟機的軟體就能運行了。

2、OpenMVG學習

openMVG提供了一個可以解決計算機視覺問題並構建完整SFM流程的小型庫集合。下面對庫的內容依次介紹。
**影象庫**
影象容器:
    OpenMVG Image <T>類可以儲存灰度,RGB,RGBA或自定義的影象資料,提供基於畫素的影象讀寫操作。基本方法如下:
// A 8-bit gray image:
Image<unsigned char> grayscale_image_8bit;

// A 32-bit gray image:
Image<double> grayscale_image_32bit;

// Multichannel image: (use pre-defined pixel type)
// A 8-bit RGB image: Image<RGBColor> rgb_image_8bit; Image<Rgb<unsigned char> > rgb_image2_8bit; // 8-bit RGBA image Image<RGBAColor> rgba_image_8bit; Image<Rgba<unsigned char> > rgba_image2_8bit; // 32 bit RGB image: Image<Rgb<double> > rgb_image_32bit;
影象I/O操作:
// Read a grayscale image (if conversion need, it is done on the fly)
Image<unsigned char> gray_image;
bool bRet = ReadImage("Foo.imgExtension", &gray_image);

// Read a color image
Image<RGBColor> rgb_image_gray;
bool bRet = ReadImage("Foo.imgExtension", &rgb_image);
影象繪製操作:
Image<unsigned char> image(10,10);
image.fill(0);

// Pixel access is done as matrix (row, line)
int row = 2;
int column = 4;
image(row, column) = 127;

// Horizontal scanline
DrawLine( 0, 5, w-1, 5, 255, &image);

// Circle of radius 3 and center (5,5)
const int radius = 3;
const int x = 5, y = 5;
DrawCircle(x, y, radius, (unsigned char)255, &image);

// Ellipse of center (5,5) and (3,0
const int radius1 = 3, radius2 = 1, angle = 0;
const int x = 5, y = 5;

DrawEllipse(x, y, radius1, radius2, (unsigned char)255, &image, (double)angle);

// Example with a RGB image
Image<RGBColor> imageRGB(10,10);
DrawCircle(x, y, radius, RGBColor(255,0,0), &imageRGB);

數學和線性代數庫

該模組提供依賴於[Eigen]庫的數學和線性代數工具。 Eigen是線性代數的C ++模板庫。基本思想是提供給openMVG:

•用於矩陣和向量的高級別記憶體容器,
•容易的矩陣和向量操縱,
•數字求解器和相關演算法的集合。
向量,矩陣容器:
OpenMVG重新定義了程式碼一致性和清晰度的一些特徵基型別(點,向量,矩陣):
•Vec2將單個2d點儲存為列矩陣(x,y)
•Vec3將單個3d點儲存為列矩陣(x,y,z)
•Vec2f,Vec3f浮點版本。
•Vec是一個值的向量(雙精度)
•Vecf一個浮點值的向量
•Mat對於通用矩陣容器,
•Mat2X收集由2d列儲存的列,
•Mat3X將3d點的集合儲存為列。
// Create a set of 2D points store as column
//建立一組2D點儲存為列
Mat2X A(2, 5);//2行5列
A << 1, 2, 3, 4, 5,
6, 7, 8, 9, 10;
A.col(); // return a column vector : (1,6)^T
A.row(); // return a row vector : (1,2,3,4,5)
線性代數
SVD/QR/LU 分解

特徵庫

該模組為特徵和相關描述符提供通用容器。
特徵:提供基本結構和IO來儲存基於Point的特徵。
儲存點特徵的類:PointFeature儲存特徵的位置(x,y)。SIOPointFeature儲存特徵(x,y,s,o)的位置,方向和尺度。

特徵描述符:提供描述符資料的基本結構和IO。
模板

// SIFT like descriptor
using siftDescriptorData Descriptor<float, 128>;

// SURF like descriptor
using surfDescriptorData = Descriptor<float, 64>;

// Binary descriptor (128 bits)
using binaryDescriptor_bitset = Descriptor<std::bitset<128>,1> binaryDescriptor_bitset;
// or using unsigned chars
using binaryDescriptor_uchar = Descriptor<unsigned char, 128/sizeof(unsigned char)>;

特徵點集:
儲存特徵點及其相關描述符:

template<typename FeaturesT, typename DescriptorsT> class KeypointSet
// Define SIFT Keypoints:

// Define the SIFT descriptor [128 floating point value]
using Descriptor<float, 128> DescriptorT;

// Use SIFT compatible features (scale, orientation and position)
using FeatureT = SIOPointFeature;

// Describe what a collection of local feature is for a given image:
using FeatsT = std::vector<FeatureT>;
using DescsT = std::vector<DescriptorT>;

// Link features and their descriptors as a collection:
using KeypointSetT = KeypointSet<FeatsT, DescsT>;

相機庫

該模組提供不同的相機模型。
針孔相機模型:
相機可以由投影模型近似,通常稱為針孔投影。 相機的最簡單的表示是光敏表面(感測器):影象平面,在給定位置處的透鏡(投影投影)和空間中的取向。

針孔相機模型,定向中心投影攝像機

針孔攝像機幾何模型的投影相機具有兩個子引數,內在和外在引數。 內在引數對光學元件(無變形)進行建模,外在模型將相機的位置和方向置於空間中。 相機的投影描述如下:

這裡寫圖片描述

內部引數:ku和kv通常為1,f表示焦距,cu和cv為主點,表示影象的理想中心。外部引數:R,t分別表示旋轉矩陣和平移矩陣。

OpenMVG針孔相機模型

Pinhole_Intrinsic : public IntrinsicBase

classic pinhole camera (Focal + principal point and image size).焦距、主點與影象大小

Pinhole_Intrinsic_Radial_K1 : public Pinhole_Intrinsic

classic pinhole camera (Focal + principal point and image size) + radial distortion defined by one factor.使用一個因素設定徑向畸變。

Pinhole_Intrinsic_Radial_K3 : public Pinhole_Intrinsic

classic pinhole camera (Focal + principal point and image size) + radial distortion by three factors.使用三個因素設定徑向畸變。

Pinhole_Intrinsic_Brown_T2 : public Pinhole_Intrinsic

classic pinhole camera (Focal + principal point and image size) + radial distortion by three factors + tangential distortion by two factors.使用三個因素設定徑向畸變,使用兩個因素設定切向畸變。

Pinhole_Intrinsic_Fisheye : public Pinhole_Intrinsic

classic pinhole camera (Focal + principal point and image size) + fish-eye distortion by four factors.使用四個因素設定魚眼畸變。

// Setup a simple pinhole camera at origin
// Pinhole camera P = K[R|t], t = -RC
Mat3 K;
K << 1000, 0, 500,
     0, 1000, 500,
     0, 0, 1;
PinholeCamera cam(K, Mat3::Identity(), Vec3::Zero());

多視角庫

多視角模板主要包括:
用於在多檢視幾何中出現的2到n維檢視幾何約束的求解器的集合。
一個通用框架“核心”可以嵌入這些求解器進行魯棒估計。
列出並解釋了第一個可訪問的解算程式,並記錄了“核心”概念。

2維求解(2D到2D對應)

openMVG為以下幾何估計提供求解器:
仿射,同形異義,基本矩陣,7到n pt,8到n pt(直線變換)[HZ]。必要矩陣,8到n pt(直線變換)[HZ],5pt +內在引數[Stewenius],[Nister]。

N-View幾何估計

三角測量,旋轉,平移

單應性矩陣:

單應性矩陣繪製了一個平面的兩個投影之間的關係。H是一個(3×3)矩陣,它將左右影象中的座標與以下關係聯絡起來。

單應性矩陣以及點與點之間的約束
H可由四對以上的對應點估計出來。

基本矩陣:

基本矩陣是觀察相同場景的兩個影象之間的關係,其中這些點的投影在兩個影象中是可見的。 給定兩個檢視之間的點對應:

這裡寫圖片描述

F是(3×3)基本矩陣,它將點x與屬於3D X點的投影的線相關聯。F有七個自由度,需要至少七個以上的已知對應點關係才能進行計算。

相對姿態估計(本質矩陣)

向基本矩陣新增內在引數,得到本質矩陣,該本質矩陣將相機的相對位置與基本矩陣關係相連。

這裡寫圖片描述

絕對姿態估計/相機切除(位姿矩陣)

給定3D-2D點對應的列表,可以計算相機姿態估計。 它包括估計右側相機的相機引數,使3D點重新投影的殘差可以最小化,這是一個優化問題,試圖解決P引數,以便最小化:

這裡寫圖片描述

openMVG 提供了三種不同的方法來解決這個問題:
6pt直接線性變換[HZ],
具有內在EPnP [EPnP]的4pt,
3pt內在P3P [Kneip]。

核心概念

為了在通用的魯棒估計框架中使用求解器,我們將它們與允許連結的Kernel類結合使用:

這裡寫圖片描述

線型規劃