PMVS 2を試す (1)

ここしばらくbundlerを試しているのですが,(色々と思うところはあるにせよ)とても素晴らしいソフトウェアであると感じています.

さて,bundlerによって疎な点群とカメラの配置を計算した後はPMVSというソフトウェアを利用して密な対応点群を構築して結果を可視化するのが良いようです.そこで今日はこれを試してみます.

例によってFreeBSDを使うため,バイナリをダウンロードして云々ということができません.そこで普段通りにソースコードコンパイルしてソフトウェアをビルドします.まず,PMVSは以下のライブラリに依存します.

jpeg
JPEG画像を扱うためのライブラリです.
cblas
BLASC言語インターフェースです.
lapack
言わずと知れた線型代数ライブラリです.
GSL
GPLで配布される科学技術計算ライブラリです.

これらはいずれもportsからインストール可能であるため,特に迷うことはないでしょう.Makefileには書き間違いが含まれているので修正すると良いと思われます.

--- Makefile.orig	2012-01-28 20:50:54.000000000 +0900
+++ Makefile	2012-01-28 20:52:50.000000000 +0900
@@ -16,7 +16,7 @@
 
 CXXFLAGS = -O2 -Wall -Wno-deprecated ${YOURINCLUDEPATH}
 
-LDFLAGS = ${YOURLDLIBPATH} -lXext -lX11 -ljpeg -lm -lpthread \
+LDFLAGS = ${YOURLDLIBPATH} -ljpeg -lm -lpthread \
 	-llapack -lgsl -lgslcblas
 
 ######################################################################
@@ -27,7 +27,7 @@
 	patchOrganizerS.o seed.o point.o option.o \
 	image.o camera.o photoSetS.o patch.o photo.o \
 	mylapack.o
-	${CXX} ${LDFLAGS} -o $@ $^ ${LDFLAGS}
+	${CXX} ${CXXFLAGS} -o $@ $^ ${LDFLAGS}
 
 %.o : ../base/pmvs/%.cc
 	$(CXX) -c $(CXXFLAGS) $<

また,X11のライブラリは不要なので削除して問題ありません.ATLASやGotoBLASなどCBLASインターフェースを含むライブラリが利用可能ならば-lgslcblasも削除できます.CLAPACKを使うのは色々と問題があるのでFortranLAPACKを使うためにpmvs-2/program/base/numeric/以下のソースコードを多少修正します.例えば以下のようにLAPACK関数のプロトタイプを追加すれば良いでしょう.

diff -uNr ../numeric_/./lapack.h ./lapack.h
--- ../numeric_/./lapack.h	1970-01-01 09:00:00.000000000 +0900
+++ ./lapack.h	2012-01-28 20:56:23.000000000 +0900
@@ -0,0 +1,28 @@
+#ifndef _LAPACK_H_
+#define _LAPACK_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  typedef int integer;
+
+  int sgesvd_(const char *jobu, const char *jobvt, integer *m, integer *n,
+	      float *a, integer *lda, float *s, float *u, integer *ldu, float *vt,
+	      integer *ldvt, float *work, integer *lwork, integer *info);
+
+  int dgesvd_(const char *jobu, const char *jobvt, integer *m, integer *n,
+	      double *a, integer *lda, double *s, double *u, integer *ldu, double *vt,
+	      integer *ldvt, double *work, integer *lwork, integer *info);
+
+  int sgels_(const char *trans, integer *m, integer *n, integer *nrhs,
+	     float *a, integer *lda, float *b, integer *ldb, float *work, integer *lwork,
+	     integer *info);
+
+  int dgels_(const char *trans, integer *m, integer *n, integer *nrhs,
+	     double *a, integer *lda, double *b, integer *ldb, double *work, integer *lwork,
+	     integer *info);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -uNr ../numeric_/./mylapack.cc ./mylapack.cc
--- ../numeric_/./mylapack.cc	2009-08-17 10:06:55.000000000 +0900
+++ ./mylapack.cc	2012-01-28 20:56:23.000000000 +0900
@@ -2,10 +2,7 @@
 #include <cstdlib>
 #include <iostream>
 
-extern "C" {
-#include <clapack/f2c.h>
-#include <clapack/clapack.h>
-};
+#include "lapack.h"
 
 using namespace std;
 
diff -uNr ../numeric_/./mylapack.h ./mylapack.h
--- ../numeric_/./mylapack.h	2009-08-17 10:06:55.000000000 +0900
+++ ./mylapack.h	2012-01-28 20:56:23.000000000 +0900
@@ -28,11 +28,11 @@
 
   static void lls(std::vector<float>& A,
                   std::vector<float>& b,
-                  long int width, long int height);
+                  int width, int height);
   
   static void lls(std::vector<double>& A,
                   std::vector<double>& b,
-                  long int width, long int height);
+                  int width, int height);
 
   // SVD
   // A = U Sigma V^T

これで大体問題ないはずです.

PMVSは画像の存在するディレクトリと各種設定値を記述したファイルを与えることで実行できます.付属するデータを既定値で実行するには次のようにします.

cd pmvs-2/data/hall/
pmvs2 ./ options.txt

処理が成功すればmodels内に以下のデータファイルが出力されます.

  • option.txt.patch
  • option.txt.ply
  • option.txt.pset

option.txt.plyMeshLabというソフトウェアを利用することで可視化することができます.

大雑把な感想としてはbundlerと異なりPMVSはpthreadによって並列化されており,また依存関係も整理されているという印象です.このため,普通のOSを使っている限り特に問題なくビルドすることができそうです.