COLMAPを使った3次元復元結果の座標変換方法
はじめに
「だーれだ?」
「えっ!?もしかして...よしこちゃん?」
いいえ、Mas-sensyn です。
COLMAPは以前ご紹介したSfM(Structure from Motion)のフリーソフトですが、SfMにはスケールがありません。
また、今回、別の方法で表された座標系に変換したい、という要望がありました。
そこで今日は、COLMAPの3次元復元結果を、別の座標系に座標変換する方法についてご紹介いたします。
目的
COLMAPで作られた3次元復元結果を、撮影したカメラ位置を定義している世界座標系に、座標変換する。
注釈
- COLMAPの復元結果にはスケールがありません。しかし、本手法を適用することによって、復元結果にスケールも与えることができます。
- では、もともとのCOLMAPでの3次元復元結果の座標系は何かと言うと、point cloudの中心位置に原点を定義され、スケールは、最長の方向を[-10,10]mにスケールしています。(ref: google group)
- 本記事でご紹介する方法は、COLMAP自身が提供する機能Geo-registrationを用いる手法です。 RANSACを使用して座標変換とスケール(scale+Euclid変換)を導きます。詳細なアルゴリズムは、こちらのソースコードを参照してください。
- 点群を直接表している座標系には座標変換できません。即ち、point cloudを、直接、point cloudを別の世界座標で表現した世界座標に変換することはできません。 それをしたい場合は、独自にICP等を適用する必要があります。
結果画像の例
やりたいことをイメージしやすいように、結果画像の一例を貼っておきます。
下図のように、座標系が変換されます。この際、画像からは分かりませんが、実際にはスケールも補正されています。
座標変換前のsparse復元結果
前提
今回用いた環境
GPU: Nvidia GeForce GTX1060 (denseな結果を得るにはGPUが必須です。逆にsparseな結果だけでいいなら要りません。)
OS: Ubuntu18.04 or Ubuntu20.04
使用したソフトウェア
COLMAP 3.7
手順概要
はじめにsparseなreconstructionを通常の方法で行い、sparseな結果(point cloud)をCOLMAPのGeo-registrationを用いて座標変換し、その結果をdense reconstructionします。はじめのsparseなreconstructionは通常の方法なので省略しますが、それも含めた方法を知りたい場合は、最後に載せたscript例をご参照下さい。
sparseな結果の座標変換方法
概要
sparseな結果(point cloud)をCOLMAPのGeo-registrationを用いて座標変換します。
入力
画像群
最低3つ以上のカメラ位置、向きを、目的の世界座標系で表した、以下の形式のテキストファイル。ref: COLMAP Geo-registration
image_name1.jpg X1 Y1 Z1
image_name2.jpg X2 Y2 Z2
image_name3.jpg X3 Y3 Z3
...
出力
出力ディレクトリ内に保存された、以下3つのファイル(座標系が変換されただけで、入力と全く同じ形式)
cameras.bin images.bin points3D.bin
手順
以下のreferenceそのままですが、
colmap model_aligner \
--input_path /path/to/model \
--output_path /path/to/geo-registered-model \
--ref_images_path /path/to/text-file
reference
denseな結果の座標変換方法
概要
前節のsparseな結果を用いて、denseな結果を作成するだけです。
入力
sparseなgeoregistration出力ディレクトリ内に保存された、以下3つのファイル
cameras.bin images.bin points3D.bin
出力
座標変換された以下2つのファイル
meshed-poisson.ply, meshed-delaunay.ply
手順
全てを一つのコマンドにしたautomatic_reconstructionが使えないので、以下のreference通りにcommand lineで実行します。
reference: COLMAP command line interface
入力画像群からdenseな座標変換結果を出すまでのscript例
#!/bin/sh
# This is a script for COLMAP georegistration and then run dense reconstruction
####
# treat arguments
USAGE="$0 <work directory which have ../images/>"
if [ $# -lt 1 ]; then
echo $USAGE
exit 1
fi
# sparse reconstruction
# The project directory must contain a directory "images" with all the images.
DATASET_PATH=$1 #work directory. ../images is the image directory.
cd ${DATASET_PATH}
colmap feature_extractor \
--database_path $DATASET_PATH/database.db \
--image_path $DATASET_PATH/../images
--ImageReader.single_camera 1
colmap exhaustive_matcher \
--database_path $DATASET_PATH/database.db
mkdir $DATASET_PATH/sparse
colmap mapper \
--database_path $DATASET_PATH/database.db \
--image_path $DATASET_PATH/../images \
--output_path $DATASET_PATH/sparse
# georegistrate sparse point cloud
GEOREGIDIR=georegistration
mkdir -p sparse/${GEOREGIDIR}
colmap model_aligner --input_path sparse/0 --output_path sparse/${GEOREGIDIR} --ref_images_path ../campose.txt --robust_alignment 1 --robust_alignment_max_error 0.01
# dense reconstruciton for georegistered data
mkdir $DATASET_PATH/dense
colmap image_undistorter \
--image_path $DATASET_PATH/../images \
--input_path $DATASET_PATH/sparse/${GEOREGIDIR} \
--output_path $DATASET_PATH/dense/${GEOREGIDIR} \
--output_type COLMAP \
--max_image_size 2000
colmap patch_match_stereo \
--workspace_path $DATASET_PATH/dense/${GEOREGIDIR} \
--workspace_format COLMAP \
--PatchMatchStereo.geom_consistency true
colmap stereo_fusion \
--workspace_path $DATASET_PATH/dense/${GEOREGIDIR} \
--workspace_format COLMAP \
--input_type geometric \
--output_path $DATASET_PATH/dense/${GEOREGIDIR}/fused.ply
colmap poisson_mesher \
--input_path $DATASET_PATH/dense/${GEOREGIDIR}/fused.ply \
--output_path $DATASET_PATH/dense/${GEOREGIDIR}/meshed-poisson.ply
colmap delaunay_mesher \
--input_path $DATASET_PATH/dense/${GEOREGIDIR} \
--output_path $DATASET_PATH/dense/${GEOREGIDIR}/meshed-delaunay.ply
reference
#!/bin/sh
# This is a script for COLMAP georegistration and then run dense reconstruction
####
# treat arguments
USAGE="$0 <work directory which have ../images/>"
if [ $# -lt 1 ]; then
echo $USAGE
exit 1
fi
# sparse reconstruction
# The project directory must contain a directory "images" with all the images.
DATASET_PATH=$1 #work directory. ../images is the image directory.
cd ${DATASET_PATH}
colmap feature_extractor \
--database_path $DATASET_PATH/database.db \
--image_path $DATASET_PATH/../images
--ImageReader.single_camera 1
colmap exhaustive_matcher \
--database_path $DATASET_PATH/database.db
mkdir $DATASET_PATH/sparse
colmap mapper \
--database_path $DATASET_PATH/database.db \
--image_path $DATASET_PATH/../images \
--output_path $DATASET_PATH/sparse
# georegistrate sparse point cloud
GEOREGIDIR=georegistration
mkdir -p sparse/${GEOREGIDIR}
colmap model_aligner --input_path sparse/0 --output_path sparse/${GEOREGIDIR} --ref_images_path ../campose.txt --robust_alignment 1 --robust_alignment_max_error 0.01
# dense reconstruciton for georegistered data
mkdir $DATASET_PATH/dense
colmap image_undistorter \
--image_path $DATASET_PATH/../images \
--input_path $DATASET_PATH/sparse/${GEOREGIDIR} \
--output_path $DATASET_PATH/dense/${GEOREGIDIR} \
--output_type COLMAP \
--max_image_size 2000
colmap patch_match_stereo \
--workspace_path $DATASET_PATH/dense/${GEOREGIDIR} \
--workspace_format COLMAP \
--PatchMatchStereo.geom_consistency true
colmap stereo_fusion \
--workspace_path $DATASET_PATH/dense/${GEOREGIDIR} \
--workspace_format COLMAP \
--input_type geometric \
--output_path $DATASET_PATH/dense/${GEOREGIDIR}/fused.ply
colmap poisson_mesher \
--input_path $DATASET_PATH/dense/${GEOREGIDIR}/fused.ply \
--output_path $DATASET_PATH/dense/${GEOREGIDIR}/meshed-poisson.ply
colmap delaunay_mesher \
--input_path $DATASET_PATH/dense/${GEOREGIDIR} \
--output_path $DATASET_PATH/dense/${GEOREGIDIR}/meshed-delaunay.ply
注
上記では1つのカメラを使用することを前提としています。
その場合、上記"feature_extractor"のところにあるように、"--ImageReader.single_camera 1"としておくことにより、カメラ位置復元のエラーをかなり削減できます。
下記は、single_camera optionあり、なしの比較一例です。実際のカメラ経路が不明なので、正解が分からないでしょうが、single_camera optionあり、の方が現実に近かったです。
single_camera optionあり(--ImageReader.single_camera 1)
まとめ
以上、最低3つ以上のカメラ位置、向きを、目的の世界座標系で表したテキストファイルを入力として、
COLMAPで作られた3次元復元結果を、撮影したカメラ位置を定義している世界座標系に、座標変換する方法についてまとめました。
おわりに
COLMAPは結構メジャーなソフトなので、こういう機能も実装されていて便利だな、と感じました。
ただ、カメラ位置を定義した世界座標系を用いて座標変換を行うため、カメラ位置復元の誤差が乗るため、直接の目的が復元結果を合わせることであれば、誤差は大きくなってしまうため、ICP等で直接point cloudを合わせ込みにいったほうがいいでしょう。
それでは皆様、よいCOLMAPライフを!Ciao!
Author And Source
この問題について(COLMAPを使った3次元復元結果の座標変換方法), 我々は、より多くの情報をここで見つけました https://qiita.com/Mas-sensyn/items/0784bf96fa9ae64b83b7著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .