VisualSFMで画像から3次元形状推定する

VisualSFMは動画や写真などの画像から形状推定を行い、3次元の形状データを作成できるソフトです。

同様のことをできるプログラムはほかにもありますが、VisualSFMの良いところはGUIがあるので簡単に使えるところがあります。

今回はインストールから設定、3次元形状推定を行い3D頂点データを作成します。

ついでに頂点からメッシュの作成も行おうと思います。

インストール&設定

インストールと書いていますが、インストーラは無く、公式サイトにある圧縮ファイルをダウンロードして展開すれば使えるようになります。

まずは公式サイトからダウンロードしましょう。

http://ccwu.me/vsfm/

Visual sfm 768x440

PCにNvidia製のGPUを乗せているならば一番上の「Windows*」のリンク(赤い矢印)からダウンロード、そうでない人やよくわからない人は「Windows」のリンク(青い矢印)からダウンロードしましょう。

Visualsfm download 768x189

ダウンロードしたファイルを適当な場所に解凍します。

VisualSFM 001 768x343

次に形状データを推定した後に密な点群データを作成するためのファイルをダウンロードします。

以下のリンクから実行ファイルをダウンロードします。

https://github.com/pmoulon/CMVS-PMVS

CMVS 768x594

ダウンロードしたファイルを解凍すると「CMVS-PMVS-master」の中の「binariesWin-Linux\Win64-VS2010」にある下の3つの実行ファイルをVisualSFMのフォルダにコピーします。

  • cmvs.exe
  • genOption.exe
  • pmvs2.exe

VisualSFM 002

以上で設定は終わりです。

「VisualSFM.exe」をダブルクリックで起動します。

いざ、3次元形状推定

「VisualSFM.exe」をダブルクリックで起動します。

VisualSFM 003 768x442

「File→Open+ Multi Images」を選択して、形状推定に使用する画像を選択していきます。

VisualSFM 004 768x436

使用する画像を選択していきます。 この時、選択する画像枚数が少ないと推定できる頂点数が少なくなってしまいます。

動画を使用する場合は、(特殊なファイル形式の場合は「HandBrake(日本語版は使わない方がいい)」などでmp4に変換して)「Free Video to JPG Converter」などで画像に変換するといいと思います。 画像が増えると加速度的に時間がかかるので、ある程度フレームを落として使いましょう。

VisualSFM 005 768x472

Nvidia製のGPUを使うときのみ「Tools → Enable GPU → Match using CUDA」にチェックを入れます。

VisualSFM 006 768x399

「SfM → Pairwise Matching → Compute Missing Match」をクリックします。 特徴点を探し、画像同士を対応付けます。

VisualSFM 007 768x446

時間がかかるので待ちます。 進捗具合は右にある「Log Window」で確認できます。 下の図では一番下が「0011 and 0021 …」となっていますが、0011と0021番目の画像を対応付けている段階です。 今回は42枚の画像を入力したので「0040 and 0041 …」くらいで終了します。(若干順番は前後します)

VisualSFM 008 768x576

「SfM → Reconstruct Sparce」をクリックします。

VisualSFM 009 768x442

3次元形状推定を行い点群とカメラパラメータを生成します。

VisualSFM 010 768x445

点群が生成されましたが、このままでは何が映っているのかわからないので密な点群をさらに生成します。

「SfM → Reconstruct Dense」をクリックします。

VisualSFM 011 768x443

適当に名前を付けて保存します。

VisualSFM 012

時間がかかるので多少待ちます。

処理が終わった後、「View → Dense 3D Points」を押すと密なデータが表示されます。

VisualSFM 013 768x445

密なデータが表示されました。

VisualSFM 014 768x477

画像が少なかった部分、単色の部分などはうまく特徴点を取れません。 例えば今回の例だと、地面の部分は木目がある分多少できてますが、ほぼ黒一色のため少なめです。 本の部分の端っこなどは枚数が少ないため穴があります。

密なデータを作り終わると、拡張子が「.ply」「.nvm」のファイルが作成されます。 「.nvm」ファイルは次回以降VisualSFMに読み込む際に使用します。 「.ply」ファイルはBlenderやMeshLabなど他のCGソフトで読み込む際に使います。

もし「.ply」ファイルが作成されてなかったり、自分で作りたい場合は「Sfm → Save NView Match」を選択します。

VisualSFM 015 768x448

この時、ファイル名についている拡張子を「.ply」に変更し保存します。

VisualSFM 016

*多分、密なデータを表示させていれば、そのデータが出力されると思いますが、もしかすると疎なデータが出力されるかもしれません。 「SfM → Load NView → Match」で「.nvm」ファイルを読み込みなおしてやり直してみてください。

メッシュを張る

MeshLabで作成した「.ply」ファイルを読み込みます。 「File → Import Mesh」から先ほど作成したデータを読み込みます。

VisualSFM 017 768x415

1つ目の方法としては、「Filters → Remeshing, Simpleification and Reconstruction → Surface Reconstruction : Ball Pivoting」でメッシュを作成できます。

VisualSFM 019 768x513

頂点数が多いとあほみたいに時間がかかります。

出来上がったメッシュデータがこれ。

VisualSFM 020 768x418

かなりメッシュができましたが、結構穴があります。 結構調整が難しいです。

2つ目の方法は、「Filters → Remeshing, Simpleification and Reconstruction → Screened Position Surface Reconstruction」を選択します。

VisualSFM 021 768x515

パラメータはデフォルトで問題ないと思います。

Applyを押します。

VisualSFM 022

できた結果がこちら。

VisualSFM 023 768x595

周りに色々とついちゃってますが、穴ができないのがメリットですね。

他にもやり方はたくさんあると思います。

Blenderに取り込もう

Blenderにカメラを取り込む際に自分でパラメータを計算してもいいですが、せっかくこちらの方が作っているのでそれを使わせていただきましょう。

下のリンクからプログラムをダウンロードします。

https://github.com/kibekibe/VSFMBundle_to_Blender

VisualSFM 025 768x661

ダウンロードしたファイルを適当な場所に解凍します。

「import vsfm.py」ファイルを後々使います。

VisualSFM 026

Blenderを起動します。

「ファイル→ユーザー設定」を選択します。

VisualSFM 024 768x434

上部で「アドオン」を選択し、「ファイルからアドオンをインストール」を選択します。

VisualSFM 027 1 768x492

UIが独自のもので分かりにくいですが、先ほど解凍した「import vsfm.py」を選択し、「ファイルからアドオンをインストール」をクリックします。

VisualSFM 028 1 768x466

するとこのような画面が出てくると思うので、インストールしたアドオンにチェックを入れます。 もし、先ほどインストールしたアドオンが表示されてなければ、検索欄に「SFM」のように単語を入れて、サポートレベルを「コミュニティ」にしてください。

VisualSFM 029 768x412

「ファイル→インポート→VSFM Cameras File(txt)」を選択します。

VisualSFM 030 768x448

密データを保存していたフォルダの中に「/test.nvm.cmvs/00」というフォルダがあり、その中に「cameras_v2.txt」というファイルがありますので、そのファイルを選択します。

VisualSFM 032

また、「ファイル→インポート→Stanford (.ply)」を選択し、作成した「.ply」ファイルを読み込みます。

VisualSFM 031 768x545

VisualSFM 033

以上で、推定した頂点とカメラデータをBlenderに取り込むことができました。

こんな感じ

VisualSFM 034 768x526

何が映ってるかわかりませんね。。。

そこでMeshLabでメッシュ化したものを読み込んでみます。

VisualSFM 035

できました。 カメラ位置も何となくあっているのが確認できますね。

カメラパラメータの簡単な説明

おまけですが、VisualSFMは推定したカメラのパラメータも出力しています。 その簡単な見方も書いておこうと思います。

密データを保存していたフォルダの中に「/test.nvm.cmvs/00」というフォルダがあり、その中に「cameras_v2.txt」というファイルがあります。 このファイルにカメラパラメータが書かれています。

ファイルにはこのように書かれてます。

00000000.jpg
C:\〇〇\Pictures\ゆるキャン\DSC_0553.JPG
2355.91210938
1632 1224
0.6027042606 0.646708832961 -0.209493646007
-0.611045058142 -0.130407772387 0.659537641624
1.27565737125 0.183042724577 -0.186349228311
0.79544020009 0.593713372197 0.0851913027069 -0.0867302076873
0.970440193446 0.239135654433 0.0325433613891
-0.0368191205935 0.279965540721 -0.959304294712
-0.238514986096 0.929749639595 0.280494713512
0.0553097285466
0 0 0

......省略

1行目 VisualSFM内での画像番号です。 画像番号というより、カメラ番号といった方がいいかもしれません。

2行目 そのカメラに対応する入力したオリジナル画像名です。 ちなみに連番の画像を入力しても番号順とはならないようです。

3行目 焦点距離です。

4行目 [2-vec] Principal Pointと書いてあるので主点のようです。 値を見るに、入力画像の中心、つまり解像度の半分の値が入っています。

5行目 [3-vec] 平行移動配列のようです。 (-1)×(9,10,11行目の回転行列)×(平行移動配列)を計算することでカメラの視点座標を導出できました。

6行目 [3-vec] カメラの中心座標が入っています。

7行目 [3-vec] 軸回転要素です。

8行目 [4-vec] 7行目の長さ4の時版みたいです。クォータニオン回転要素です。つまり軸回転。初めの3つの値が軸を表し、4つ目の値が回転する角度を表します。

9,10,11行目 [3×3 Matrix] 軸回転っぽいのです。カメラの回転行列のようです。

12行目 「Normalized radial distortion」直訳で「正規化された偏位」でしょうか。 カメラのひずみでしょうか?よくわかりません。

13行目 [3-vec] よくわかりませんが、試してみた限り0しか入ってませんでした。

今回はこのくらいにしておこうと思います。