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

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

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

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

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

インストール&設定

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

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

http://ccwu.me/vsfm/

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

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

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

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

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

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

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

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

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

いざ、3次元形状推定

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

メッシュを張る

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

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

頂点数が多いとあほみたいに時間がかかります。
出来上がったメッシュデータがこれ。

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

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

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

できた結果がこちら。

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

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

Blenderに取り込もう

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

下のリンクからプログラムをダウンロードします。
https://github.com/kibekibe/VSFMBundle_to_Blender

ダウンロードしたファイルを適当な場所に解凍します。
「import vsfm.py」ファイルを後々使います。

Blenderを起動します。

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

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

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

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

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

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

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

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

こんな感じ

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

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

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

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

おまけですが、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の時版みたいです。

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

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

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

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

あわせて読みたい