ICPアルゴリズムメモ
何したい
3次元点の位置合わせをしたい.
アルゴリズム
ICP(Iterative Closest Point)はデータ形状をモデル形状に合わせるアルゴリズム.
点の対応は未知でも良いけど,大まかな位置合わせは行っている前提で,高精度に位置を合わせる.
- モデル形状:
- データ形状:
- 収束判定閾:
1. 大まかに位置を合わせる.
- 初期並進:
- 初期回転:
2. 近傍点の計算する.
データ点から最も近いモデル形状の点を
とする.
3. 位置合わせパラメータの計算する.
- 重心を計算する.
- 共分散行列を計算する.
- 共分散行列を特異値分解する.
- 回転行列を計算する.
- 並進ベクトルを計算する.
4. 誤差を計算する.
5. 収束判定をする.
- ひとつ前の2乗距離誤差:
もし,
なら,とを返して終了する.
そうでなければ,として2へ戻る.
メモ
- 最近傍の点の対応付けは,KD-treeなどのデータ構造を用いると高速に行えるそう.
- 収束を高速化したり,形状のスケールを調節するパラメータを推定したりする派生もある.
参考
「コンピュータビジョン最先端ガイド3」,アドコム・メディア株式会社
PCLインストールとPLY出力
何したい
3次元点群の見栄えを良くするためにアウトライヤーを取り除きます.
このアウトライヤー除去は,PCL(Point Cloud Library)のフィルタリングを使う.
使い方を記録します.
環境
Ubunut14.04
インストール
Prebuilt binaries for Linux - Point Cloud Library (PCL)を参考にコマンドを入力します.
sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl sudo apt-get update sudo apt-get install libpcl-all
アウトライヤー除去のサンプルプログラム
除去のアルゴリズムはK-means法を使って,近傍の点の距離の平均値が大きいもの(離れている)を除去する.
下のサンプルは,PCL公式のフィルタリングでアウトライヤー除去をするプログラムの出力部分を
PLY形式でも出力するように改良した.
// statistical_removal.cpp #include <iostream> #include <pcl/io/ply_io.h> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/filters/statistical_outlier_removal.h> int main (int argc, char** argv) { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>); // Fill in the cloud data pcl::PCDReader reader; // Replace the path below with the path where you saved your file reader.read<pcl::PointXYZ> ("table_scene_lms400.pcd", *cloud); std::cerr << "Cloud before filtering: " << std::endl; std::cerr << *cloud << std::endl; // Create the filtering object pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; sor.setInputCloud (cloud); sor.setMeanK (50); sor.setStddevMulThresh (1.0); sor.filter (*cloud_filtered); std::cerr << "Cloud after filtering: " << std::endl; std::cerr << *cloud_filtered << std::endl; pcl::PCDWriter writer; pcl::PLYWriter ply_writer; writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.pcd", *cloud_filtered, false); ply_writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.ply", *cloud_filtered, false); sor.setNegative (true); sor.filter (*cloud_filtered); writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *cloud_filtered, false); ply_writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.ply", *cloud_filtered, false); return (0); }
プログラムのコンパイルは,CMakeLists.txtを書いて
# CMakeLists.txt cmake_minimum_required(VERSION 2.8 FATAL_ERROR) project(statistical_removal) find_package(PCL 1.2 REQUIRED) include_directories(${PCL_INCLUDE_DIRS}) link_directories(${PCL_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS}) add_definitions("-Wall -std=c++11") add_executable (statistical_removal statistical_removal.cpp) target_link_libraries (statistical_removal ${PCL_LIBRARIES})
cmakeしてmakeをする.
mkdir build cd build cmake .. make
シャドバはじめました
8月半ばあたりからぼちぼちログインとミッションをこなしてました。
昨日からランクマッチをやるようになったので書き留めます。
現在使用中のデッキは冥府エルフ、疾走ビショップです。
A0突入しました。頑張って続けます
Delaunay 三角形分割
3次元復元の結果で3次元点群が得られます。
2枚の写真の対応点の数が少なかったので、
写真のどのあたりが復元できたか見た目でわかりません。
なので、メッシュを張りってテクスチャを貼付けて、形状をわかりやすく表現します。
Delaunay三角形分割を使って画像中の特徴点を三角形に分割します。
アルゴリズムについては、ただいま学習中。
ブログ
引っ越しを終えて落ち着いてきた.
趣味や生活,勉強のことを綴る備忘録ブログ