Learn SFM

1. SFM

Structure from Motion (SfM):從運動中恢復結構,通俗地講:從序列圖像中重建目標三維結構,並估計相機及空間參數。html

用於SfM的主要有三個庫:git

SfM輸出的是稀疏點雲以及相機參數,這些信息將用於後續的稠密重建。app

2. MVS

MultiView Stereo(MVS):多視點匹配,用於生成稠密點雲。post

一般MVS能計匹配到更多的點,生成更稠密的點雲,作到這一點須要用到對極幾何的原理:一副圖像上的一個像素點是空間上一條線(相機視點和該像素連起來的直線)的投影,而這條線在另一幅圖像上每每會投影爲一條線。SFM須要在整個二維圖像上搜索匹配點,而MVS只須要在一條線上搜索。
以上是PMVS2作的事,作到這些須要大量複雜的計算,CMVS就是用於簡化此的。CMVS把SfM輸出的聚類爲區域,PMVS2將在這些「區域」上匹配,最後CMVS將這些區域映射爲三維模型。
關於兩者的聯繫和區別性能

3. bundler

3.1 配置

bundler是經典的單目重建公開庫之一,不少工做都是在此基礎上進行的,其運行過程大體分爲三步:google

  1. 使用Perl腳本 extract_focal.pl 提取圖像焦距信息並存儲到 image list 中;命令行

  2. 在每幅圖像上尋找SIFT特徵點;

  3. 在各個圖像中匹配特徵點,匹配的特徵存儲在 matches.init.txt 中;

  4. 運行bundler,生成點雲和相機參數;

配置的大體步驟是:下載bundler源碼,Windows下安裝cygwin,安裝相關依賴,編譯和運行。其中編譯有兩種方式:make命令和VS編譯,若是是在VS編譯編譯可參考:issue 26

3.2 輸出

  • 格式: bundle_<n>.out

  • 包含內容:場景估計相機幾何參數

  • 具體:

    • 版本信息:# Bundle file v0.3

    • <num_cameras> <num_points>:兩個整數,分別表示相機總數(其實就是輸入圖像的數量)和匹配到的點數;

    • 接下來依次是每一個相機的內參和外參信息;

  • 內參:

    • <f> <k1> <k2>:焦距,兩個徑向畸變參數;

  • 外參:

    • <R>:表示相機旋轉的矩陣,3X3;

    • <T>:相機平移矩陣,1X3;

  • 匹配點:

    • <position>:點空間位置的描述,1X3;

      • <color>:RGB信息,1X3;

      • <view list>:描述點可見性的向量,包括 view list 長度,<camera>第幾個相機,<key>表示該相機中第幾個sift特徵點,<x>和<y>表示在二維圖像上的座標(以圖像中心的原點);

3.3 選項

options.txt默認包含的選項
  • --match_table: 指定點匹配信息存儲的文件,默認:matches.init.txt

  • --output: 指定包含最終計算結果的文件名稱,默認:bundle.out

  • --output_all:指定中間結果存儲的前綴,默認:bundle_

  • --output_dir: 指定計算結果的保存目錄,默認:bundle

  • --variable_focal_length:爲指定每張圖片指定獨立的焦距,默認:無(源碼中爲Option結構);

  • --use_focal_estimate:指定是否使用從EXIF中提取的焦距信息,默認:true

  • --constrain_focal:指定計算出的相機焦距是否被初始焦距(從EXIF中提取)所約束,默認:true

  • --constrain_focal_weight: 指定焦距約束條件的權重,一般一個較小的數可矣,默認:0.0001

  • --estimate_distortion:指定是否爲每一張圖片估計畸變參數,默認:true

  • --ray_angle_threshold默認:2.0;

  • --run_bundle:指定是否運行SFM,默認:true

其它選項
  • --init_pair1,--init_pair2:指定初始匹配的兩張圖像,一般由程序自動選擇匹配點最多的一對圖像,若是效果很差再啓用此選項; - --sift_binary: 指定計算SIFT特徵的外部接口,通常是/usr/bin/sift or /cygdrive/c/usr/bin/siftWin32.exe

  • --add_images: 在已有重建基礎上額外添加新圖像時使用此選項;

  • options_file:指定bundler參數文件,默認:options.txt

  • --help:輸出全部的選項信息;

4. PMVS2

PMVS是 Yasutaka Furukawa開發的 Patch-based Multi-view Stereo Software(PMVS)——分段式多視角匹配軟件(目前是第二版)。PMVS的輸入爲一組圖像和相應的相機參數,輸出是「半稠密」的點雲。須要注意的是,PMVS只重建剛性機構的目標,自動忽略行人等柔性目標。關於MVS有一個跑分排行

文檔

4.1 輸入

  • images:要求jpeg或者ppm格式,命名必須是8位(兼容4位)的數字:%08d.jpg

  • camera parameters:命名格式與圖像命名相同,內容含義:

-------------------------------------------
CONTOUR //固定的header
//P[3][4]表示投影矩陣(三維點和投影矩陣相乘獲得二維座標)
P[0][0] P[0][1] P[0][2] P[0][3]
P[1][0] P[1][1] P[1][2] P[1][3]
P[2][0] P[2][1] P[2][2] P[2][3]
-------------------------------------------
  • segmentation masks:以pgm格式文件給定,灰度小於127是背景,不然爲前景;

  • option file:指定使用的參數文件,具體選項以下:

    • timages:指定目標圖像(必選項),能夠用列舉(timages 5 1 3 5 7 9)或者範圍(timages -1 0 6)的方式指定;

    • oimages:other images(必選項),用於指定那些圖片能輸出重建結果(重建結果會等全部timages運算完輸出,可是經過oimages指定的圖像會在中間過程輸出),指定方式和timages相同,若是不想用此選項,指定爲0;

    • level:指定圖像金字塔(降採樣的層次)的高度,指定1(默認)表示降採樣一半(寬高縮小一倍,總像素量爲原來的四分之一),指定爲0表示不進行降採樣;

    • csize:指定重建的最小區塊,用於控制重建結果的密度,默認爲2(重建中每 2X2 個像素生成一個點雲中的點);

    • threshold:區塊重建可接受的最小閾值(默認0.7),總的範圍是-1到1,算法有三次迭代,每次迭代自動減0.05;

    • wsize:指定光度一致性計算的視口大小,默認爲7;

    • minImageNum:一個3D點必須至少在minImageNum張圖像中可見纔會被輸出,默認爲3(必須同時出如今三張以上的圖像中才會被輸出,選項應該和紋理密度成反比);

    • CPU:程序支持多線程,CPU表示線程數,默認爲4;

    • useVisData:指定是否利用已知(從SFM計算而來)的圖像關聯信息加速重建過程,程序會利用SFM的輸出生成vis.dat文件生成PMVS須要的格式(0 2 1 2:0的含義自定義,2表示後面共2個數,1和2表示相應的圖像序列,若是這是第一行則表示,圖像0和圖像二、圖像2將聚合到一起以重建點雲)。默認爲0表示不使用此信息,使用時設置爲1;

    • sequence:用於序列化圖像,默認爲-1,表示不使用此選項,若是爲3則表示當前圖像的先後各3個圖像將用於重建;

    • quad:重建的點周圍的點中,與之類似的越多則該點越不可能被濾除。一般此選項不須要調節,可省略;

    • maxAngle:當兩個相機的夾角大於此閾值則不被重建,減少maxAngle將容許更大範圍的目標被重建出來,同時噪點也更多;

4.2 輸出

輸出包含三種格式的文件:

  1. .ply:點雲文件咯;

  2. .patch:包含全部重建信息:以PATCHS開頭,包含全部重建點的信息

PATCHES
452393  //共452393個點
PATCHS
-1.20727 -0.718245 -7.1088 1  //三維座標
-0.0750093 -0.981341 -0.177041 0  //估計的法線
0.992487 0.0207491 0.385701  //第一個數表示光度一致性測度,後兩個供debug
3  //該點在3張圖像中可見且紋理匹配良好
2 0 1  //三張圖像的index
15  //該點在15張圖像中可見,可是紋理匹配不夠好
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  //這15張圖像的index
  1. .pset:簡化版的重建信息,包括點座標和法線信息;

由於最新的CMVS包含了PMVS2,並且我使用的Windows也很差編譯,因此就不運行了。

5. CMVS

Clustering Views for Multi-view Stereo (CMVS)也是 Yasutaka Furukawa (博士後時期)寫的,它包含了PMVS2的內容,提高的地方在於:更高的性能,更好的效果。CMVS將SFM的輸出分紅一個個小的圖片簇,而後獨立並行的重建。幾者的關係的關係:

Bundler->CMVS->PMVS2

5.1 輸出

  • ske.dat:包含集羣信息;

  • vis.dat:可見性信息;

  • centers-%04d.ply:各個圖片簇的相機位置;

  • centers-all.ply:全部的相機位置信息;

  • option-%04d:PMVS2配置文件;

  • pmvs.sh or pmvs.bat:用於執行PMVS2;

5.2 編譯(Windows & VS2013)

這裏以 Pierre Moulon 開發的Windows版本 CMVS + genOption + PMVS2 爲例說明(連接github)。
首先,代碼中包含自帶的已經編譯好的程序,目錄:./binariesWin-Linux/Win64-VS2010。如下是本身編譯的過程:

  • 使用CMake生成VS工程,CMake文件是 ./program/CMakeLists.txt,打開CMake GUI,選擇源碼路徑爲program,配置好,點擊生成,最後會生成一個叫作 CMVS-PMVS2.sln 的VS工程。

  • 打開工程,使用VS編譯,固然,通常都會報幾個錯誤:

    • 命令行 error D8016: 「/O1」和「/RTC1」命令行選項不兼容:將 項目->C/C++->代碼生成->基本運行時檢查設置爲default,問題解決(參考)。

解決了這個問題以後就沒有遇到其餘問題了!接下來就是將要用到的輸出copy出來運行(在main的Debug目錄下)。

5.3 運行

  1. 運行bundler:cd到example下的ET或者kermit目錄下,運行 ../../RunBundler.sh,參數默認的就行,成功後會生成./bundle目錄,成功的話會有 bundle_XXX.out 和 pointsXXX.ply 文件;

  2. 轉換bundler輸出爲PMVS所需格式:cd 到 kermit 目錄下,運行:../../bin/Bundle2PMVS.exe prepare/list.txt bundle/bundle.out,獲得結果以下(可見的結果就是生成了一個pmvs的目錄):

    [ReadBundleFile] Bundle version: 0.300
    [ReadBundleFile] Reading 11 images and 671 points...
    [GetJPEGDimensions] File ./kermit000.jpg: ( 640 , 480 )
    ......
    @@ Conversion complete, execute "sh pmvs/prep_pmvs.sh" to finalize
    @@ (you will first need to edit prep_pmvs.sh to specify your bundler path,
    @@  so that the script knows where to find your
    @@  RadialUndistort and Bundle2Vis binaries)
  3. 運行pmvs目錄下的prep_pmvs.sh校訂和生成vis.dat文件:先修改prep_pmvs.shBUNDLER_BIN_PATH的值,我是在kermit路徑下運行的,因此改成:"../../bin"

    > 這裏遇到一個bug:提示沒法找到「XXXXX.rd.jpg」,實際pmvs目錄下生成的圖像不帶「rd」。看了哈源代碼,是**RadialUndistort.cpp**中出的問題,大概是C字符串和string轉換形成的吧,將`file[i].rfint('.')`改爲`file[i].fint('.',1)`,**file[i]**爲list.txt下的一行,後面帶的數字中有小數點,致使源代碼提取basename出錯。
  4. 執行CMVS:先執行CMVS prefix 20 2,這裏已經到了cmvs的部分了,須要先把編譯好的三個文件copy過來(cmvs.exe,genOption.exe,pmvs2.exe),參數的含義能夠看cmvs自帶的release路徑下的readme。

  5. 生成pmvs的參數文件:通過cmvs以後,原來的圖片被分紅一個個的圖片簇(若是你的圖片較少則只會有一個簇),因此相應的pmvs參數也要改變,這正是這一步的意義。命令:genOption path,這裏的path建議和上一步的path一致。

  6. 生成稠密點雲:最後執行pmvs.bat生成稠密點雲,運行前可能須要修改路徑。

5.4 關於路徑

我是在Windows下運行的,全部用到的路徑都是相對方式給定,若是運行指令沒有獲得正確結果,請着重檢查你的路徑!總結起來就是一句話:

正確的路徑(相對) + 正確的參數(參數中的路徑也是相對於執行命令所在目錄的)

遇到問題能夠這樣作:

仔細查看readme -> 到github或者官網看issue和文檔 -> google或者問答社區 -> 源代碼(有基礎能夠直接看源碼)。

個人codepen:連接

相關文章
相關標籤/搜索