PCL

31,383 views

Published on

0 Comments
31 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
31,383
On SlideShare
0
From Embeds
0
Number of Embeds
332
Actions
Shares
0
Downloads
353
Comments
0
Likes
31
Embeds 0
No embeds

No notes for slide

PCL

  1. 1. PCL(Point Cloud Library) 第13回 名古屋CV・PRML勉強会 野田 雅文@miyabiarts
  2. 2. 発表の流れ• 紹介編• 導入編• 基礎編• 応用編 2
  3. 3. 紹介編 3
  4. 4. PCLの紹介• Point Cloud Library – 点群(ポ゗ントクラウド)処理のためのラ゗ ブラリ• PCL開発チーム – スポンサー:Willow Garage, NVidia, Google, Toyota, Trimble, Urban Robotics. 4
  5. 5. 姉妹プロジェクト• OpenCV 5
  6. 6. ポ゗ントクラウド(点群)データ• 3次元の点の集合 – 深度(距離)センサから取得 – (ステレオカメラ) 6
  7. 7. どんなことができるか• filters• features• keypoints• registration• kdtree• octree• segmentation• sample_consensus• surface• range_data• io• visualization 7
  8. 8. どんなことができるか 8
  9. 9. フゖルタリング• 点群の削減• 外れ値・無効値の除去• 値の平滑化 削減前 削減後 9
  10. 10. 特徴量• 3次元の特徴量計算 – 任意の点周辺の点群から算出 10
  11. 11. 特徴点• 対応付けなどに利用するユニークな点の 検出 – SIFT、NARF 11
  12. 12. レジストレーション• 複数の点群間の位置合わせ – ICPゕルゴリズム 12
  13. 13. kd木• 空間構造• 最近傍探索 13
  14. 14. 八分木• 空間構造(グリッド構造)• 点群データの圧縮などに利用 14
  15. 15. セグメンテーション• モデルフゖッテゖング – モデル:平面、シリンダーなど• 領域分割 15
  16. 16. サンプリングコンセンサス• モデルフゖッテゖングなどにおけるサン プリング – RANSACなど 直線フゖッテゖング 球面フゖッテゖング 16
  17. 17. 表面データ• 点群データからの面の再構成 17
  18. 18. レンジデータ• 点群データからレンジデータを復元 18
  19. 19. 入出力• Kinect/Xtionからの入力• フゔ゗ル入出力 – PCD(点群)、OBJ・PLY(メッシュ) 19
  20. 20. 可視化• VTK(Visual Toolkit) – 点群・レンジ・メッシュデータ可視化 – GUI表示 20
  21. 21. 応用ゕプリケーション• 3次元再構成• SLAM• ロボットの自律制御 21
  22. 22. 導入編 22
  23. 23. PCLの仕様• プログラミング言語:C++• 対応OS:Windows、MacOS、Linux• ラ゗センス:BSD• 公式サ゗ト: – http://pointclouds.org/ 23
  24. 24. ドキュメント&チュートリゕル• http://pointclouds.org/documentation/ 24
  25. 25. その他の情報• ICCV2011・IROS2011 チュートリゕル 25
  26. 26. ダウンロード• http://pointclouds.org/download 26
  27. 27. 導入• 今回は64bit 、Visual Studio 2010を対象• 最新版:PCL 1.4.0(2012/1/1)• ゗ンストーラで関連するラ゗ブラリを一 括で゗ンストール可能 – OpenNIだけは別途゗ンストール• デフォルトの゗ンストールデゖレクトリ – C:¥Program files¥PCL1.4.0 27
  28. 28. 関連するラ゗ブラリ• Boost:C++準標準ラ゗ブラリ – スマートポ゗ンタ、関数オブジェクト、ス レッド、シグナルなど• VTK:GUIツールキット• Eigen:行列ラ゗ブラリ• FLANN:最近傍探索ラ゗ブラリ• qHull:凸包、三角面化、ドロネー分割• OpenNI:Kinect 28
  29. 29. ゗ンクルードパス• C:¥Program files¥PCL1.4.0¥include¥pcl-1.4• C:¥Program files¥PCL1.4.0¥3rdParty¥Boost¥include• C:¥Program files¥PCL1.4.0¥3rdParty¥Eigen¥include• C:¥Program files¥PCL1.4.0¥3rdParty¥flann¥include• C:¥Program files¥PCL1.4.0¥3rdParty¥qhull¥include• C:¥Program files¥PCL1.4.0¥3rdParty¥VTK 5.8.0¥include¥vtk-5.8• C:¥Program files¥OpenNI¥include 29
  30. 30. ラ゗ブラリパス• C:¥Program files¥PCL1.4.0¥lib• C:¥Program files¥PCL1.4.0¥3rdParty¥Boost¥lib• C:¥Program files¥PCL1.4.0¥3rdParty¥flann¥lib• C:¥Program files¥PCL1.4.0¥3rdParty¥qhull¥lib• C:¥Program files¥PCL1.4.0¥3rdParty¥VTK 5.8.0¥lib¥vtk-5.8• C:¥Program files¥OpenNI¥lib 30
  31. 31. リンクするラ゗ブラリ(Release版)pcl_common.lib openNI64.lib vtkIO.libpcl_features.lib OpenNI.jni64.lib vtkjpeg.libpcl_filters.lib NiSampleModule64.lib vtklibxml2.libpcl_io.lib NiSampleExtensionModule64.lib vtkmetaio.libpcl_kdtree.lib MapReduceMPI.lib vtkNetCDF.libpcl_keypoints.lib mpistubs.lib vtkNetCDF_cxx.libpcl_octree.lib vtkalglib.lib vtkpng.libpcl_range_image.lib vtkCharts.lib vtkproj4.libpcl_range_image_border_extractor.lib vtkCommon.lib vtkRendering.libpcl_registration.lib vtkDICOMParser.lib vtksqlite.libpcl_sample_consensus.lib vtkexoIIc.lib vtksys.libpcl_segmentation.lib vtkexpat.lib vtktiff.libpcl_surface.lib vtkFiltering.lib vtkverdict.libpcl_visualization.lib vtkfreetype.lib vtkViews.libflann.lib vtkftgl.lib vtkVolumeRendering.libflann_s.lib vtkGenericFiltering.lib vtkWidgets.libflann_cpp_s.lib vtkGeovis.lib vtkzlib.libqhull6.lib vtkGraphics.lib opengl32.libqhullcpp.lib vtkHybrid.libqhullstatic.lib vtkImaging.libqhullstatic_p.lib vtkInfovis.lib 31
  32. 32. リンクするラ゗ブラリ• Debug版では「ラ゗ブラリ名-gd.lib」 – PCL関連のラ゗ブラリのみ• OpenNIは32bit版だとラ゗ブラリ名が変わ るので注意 32
  33. 33. 基礎編 33
  34. 34. サンプル• 点群をフゔ゗ルから読み込んで画面に表示 34
  35. 35. サンプルコードint main(){ pcl::PointCloud<pcl::PointXYZ>::Ptr data( new pcl::PointCloud<pcl::PointXYZ>() ); pcl::io::loadPCDFile( “filename.pcd", *data ); pcl::visualization::CloudViewer *viewer = new pcl::visualization::CloudViewer( “Sample" ); viewer->showCloud( cloud_filtered ); while( !viewer->wasStopped() ) { boost::this_thread::sleep (boost::posix_time::microseconds (100000)); } return 0;} 35
  36. 36. 点群データpcl::PointCloud< PointT >::Ptr cloud( new PointCloud< PointT >() ); 点群データクラス スマートポ゗ンタPointT:点の型 pcl::PointXYZ :位置 pcl::PointXYZI :位置+輝度 pcl::PointXYZRGB :位置+輝度(RGB) pcl::PointNormal :位置+法線 ・・・ 36
  37. 37. スマートポ゗ンタ• pcl::PointCloud< PointT >::Ptr• pcl::PointCloud< PointT >::ConstPtr – 中身はboost::shared_ptr• 通常のポ゗ンタ – newしたら必ずdeleteする必要がある• スマートポ゗ンタ – deleteをスマートポ゗ンタが担当 37
  38. 38. フゔ゗ル入力pcl::io::loadPCDFile( “filename.pcd", *cloud );• フゔ゗ルフォーマット:.pcd• 戻り値:-1で読み込み失敗 38
  39. 39. フゔ゗ル出力pcl::io::savePCDFile( “filename.pcd", *cloud ); 39
  40. 40. 点群データの表示• pcl::visualization::CloudViewerを利用pcl::visualization::CloudViewer viewer( "Sample" );viewer.showCloud( data );while( !viewer.wasStopped() ){ boost::this_thread::sleep (boost::posix_time::microseconds (100000));} 40
  41. 41. Viewer 41
  42. 42. Viewer• pcl::visualization名前空間内に存在 – CloudViewer:点群データのみを表示 – PCLVisualizer:点群・法線・メッシュデータな どを表示• 操作方法自体はどれも同じ 42
  43. 43. Viewerの操作方法• 左ドラッグ:視点の回転• Shift+左ドラッグ:視点の平行移動• Ctrl+左ドラッグ:画面上の回転• 右ドラッグ:ズーム• g:メジャーの表示• j:スクリーンショットの保存 43
  44. 44. Viewerの機能拡張• コールバック関数を登録することで機能 を拡張できる – registerKeyboardCallback – registerMouseCallback – registerMousePickCallback 44
  45. 45. pcl::visualization::PCLVisualizerpcl::visualization::PCLVisualizer *viewer = new pcl::visualization::PCLVisualizer();viewer->setBackgroundColor (0, 0, 0);viewer->addCoordinateSystem (0.1);viewer->initCameraParameters ();viewer->addPointCloud( cloud );while( !viewer->wasStopped() ){ viewer->spinOnce(); boost::this_thread::sleep (boost::posix_time::microseconds( 100000 ) );} 45
  46. 46. 点群の作成 • テスト用などに点群を作成したい場合pcl::PointCloud< PointT >::Ptr cloud( new PointCloud< PointT >() );for( int i = 0 ; i < 10000 ; ++i ){ // PointT = PointXYZの場合 PointXYZ point; point.x = rand(); point.y = rand(); point.z = rand(); cloud->points.push_back( point );}cloud->width = cloud->points.size();cloud->height = 1; 46
  47. 47. boost::random• C標準のrand関数は線形合同法 – 高次元で乱数に周期が発生• 任意の乱数生成器、分布を設定可能boost::mt19937 gen( static_cast<unsigned long>(time(0)) );boost::uniform_real<> dst( -0.1, 0.1 );boost::variate_generator< boost::mt19937&, boost::uniform_real<> > rand( gen, dst );// 乱数生成rand() 47
  48. 48. Kinectからの入力• 内部でOpenNIを利用pcl::Grabber* interface = new pcl::OpenNIGrabber();boost::function<void (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr&)> func =boost::bind ( capture, _1);interface->registerCallback ( func );interface->start ();while (!viewer.wasStopped()){ sleep (1);}interface->stop ();コールバック関数void capture(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud ){ viewer.showCloud( cloud );} 48
  49. 49. 無効値の除去 • Kinectからの入力には、NaNが含まれる – NaNが存在すると、レジストレーションなど の結果がおかしくなる pcl::PassThrough<pcl::PointXYZRGB> pass; pass.setInputCloud( input ); pass.filter( output );pass.setFilterLimits( 0.0, 1.0 )とすることで、特定の範囲に制限することも可能 49
  50. 50. 応用編 50
  51. 51. 応用編の流れ• 2つの点群間を位置合わせし、面を再構成 – ICCV2011 チュートリゕルに基づく – 画像処理で言うと、モザ゗キング 統合 51
  52. 52. 処理の流れ複数の点群データ平面検出と除去 初期対応付けクラスタリング 対応付けの高精度化対象物体の抽出 点群の統合 特徴点検出 メッシュ化 特徴量記述 メッシュデータ 52
  53. 53. 平面の検出と除去• 平面推定x2• 平面に属する点群の除去 53
  54. 54. 平面フゖッテゖング• 点群を平面にフゖッテゖング – 平面のパラメータの推定 – 平面に所属する点群の推定 54
  55. 55. 平面フゖッテゖングpcl::SACSegmentation< pcl::PointXYZ > seg;seg.setInputCloud ( data );seg.setOptimizeCoefficients ( true );seg.setModelType ( pcl::SACMODEL_PLANE );seg.setMethodType ( pcl::SAC_RANSAC );seg.setDistanceThreshold ( 0.02 );pcl::ModelCoefficients::Ptr coefficients ( new pcl::ModelCoefficients() );pcl::PointIndices::Ptr inliers ( new pcl::PointIndices() );seg.segment ( *inliers, *coefficients ); 55
  56. 56. 点群の抽出(除去)pcl::ExtractIndices< pcl::PointXYZRGB > extract;extract.setInputCloud( cloud );extract.setIndices( inliers );extract.setNegative( true );extract.filter( *segmented );これを2回繰り返す 56
  57. 57. クラスタリングによる対象領域の抽出• 大きな点群クラスタのみを対象領域とし て残し、ノ゗ズを除去する 57
  58. 58. クラスタリングpcl::PointCloud< pcl::PointXYZRGB >::Ptr tmp( new pcl::PointCloud< pcl::PointXYZRGB >() );pcl::PointCloud< pcl::PointXYZRGB >::Ptr segmented( new pcl::PointCloud< pcl::PointXYZRGB >() );removePlanar( cloud, tmp );removePlanar( tmp, segmented );pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB>);tree->setInputCloud (segmented);std::vector< pcl::PointIndices > cluster_indices;pcl::EuclideanClusterExtraction<pcl::PointXYZRGB> clustering;clustering.setClusterTolerance( 0.03 );clustering.setMinClusterSize( 1000 );clustering.setMaxClusterSize( 300000 );clustering.setSearchMethod( tree );clustering.setInputCloud( segmented );clustering.extract( cluster_indices ); 58
  59. 59. 対象領域の抽出pcl::ExtractIndices< pcl::PointXYZRGB > extract;extract.setInputCloud( segmented );pcl::IndicesPtr indices (new std::vector<int>);*indices = cluster_indices[0].indices;extract.setIndices( indices );extract.setNegative( false );extract.filter( *result ); 59
  60. 60. レジストレーションの流れ 特徴点検出 特徴量記述 初期対応付け 対応付けの高精度化 60
  61. 61. 特徴点検出• 点群から特徴的な点(Keypoint)を検出 61
  62. 62. 特徴点検出• いくつかの特徴点検出手法が存在 – SIFT – Harris(Harris, Tomasi, Noble, Lowe) – Curvature(曲率) 62
  63. 63. 特徴点検出 • SIFT特徴点検出pcl::SIFTKeypoint<pcl::PointXYZRGB, pcl::PointXYZI> sift3D;sift3D.setScales( 0.01, 3, 2 );sift3D.setMinimumContrast( 0.0 );pcl::PointCloud<pcl::PointXYZI>::Ptr keypoints( new pcl::PointCloud<pcl::PointXYZI>() );sift3D.setInputCloud( cloud );sift3D.compute(*keypoints); 63
  64. 64. 特徴量抽出• いくつかの特徴量記述手法が存在 – PFH(Point Feature Histograms) – PFH(RGB) – FPFH(faster approximation of) – SHOT(RGB) 64
  65. 65. 特徴量抽出 • キーポ゗ント周辺からFPFHを算出 • FPFHを算出するためには、点の法線が必要 – 法線の算出法は、後のスラ゗ドで説明pcl::Feature<pcl::PointXYZRGB, pcl::FPFHSignature33> feature_extractor ;feature_extractor.setSearchMethod( pcl::search::Search<pcl::PointXYZRGB>::Ptr( newpcl::search::KdTree<pcl::PointXYZRGB>() ) ); feature_extractor.setRadiusSearch( 0.05 );pcl::PointCloud<pcl::PointXYZRGB>::Ptr kpts(new pcl::PointCloud<pcl::PointXYZRGB>);kpts.points.resize(keypoints->points.size());pcl::copyPointCloud(*keypoints, *kpts);feature_from_normals->setInputNormals( normals );pcl::PointCloud<pcl::FPFHSignature33>::Ptr features( new pcl::PointCloud<pcl::FPFHSignature33>() );feature_extractor->compute (*features); 65
  66. 66. 初期対応付け• 点群1 -> 点群2の対応付けを算出• 点群2 -> 点群1の対応付けを算出• 以上2つ対応付けのうち、共通する対応の みを取得 66
  67. 67. 初期対応付け• 点群1から点群2への対応を計算 – 反対も計算correspondences.resize(source->size() );pcl::KdTreeFLANN<FeatureType> descriptor_kdtree;descriptor_kdtree.setInputCloud ( cloud2 );const int k = 1;std::vector<int> k_indices (k);std::vector<float> k_squared_distances (k);for (size_t i = 0; i < source->size (); ++i){ descriptor_kdtree.nearestKSearch (*cloud1, i, k, k_indices, k_squared_distances); correspondences[i] = k_indices[0];} 67
  68. 68. 初期対応付け• 両方向に共通する対応のみを残す – RANSACを行うことにより、一部の対応を除去std::vector<std::pair<unsigned, unsigned> > c; for (unsigned cIdx = 0; cIdx < c1.size (); ++cIdx) { if ( c2[c1[cIdx]] == cIdx) { c.push_back( std::make_pair( cIdx, c1[cIdx] ) ); }}correspondences->resize( c.size());for (unsigned cIdx = 0; cIdx < c.size(); ++cIdx){ (*correspondences)[cIdx].index_query = c[cIdx].first; (*correspondences)[cIdx].index_match = c[cIdx].second;}pcl::registration::CorrespondenceRejectorSampleConsensus<pcl::PointXYZI> rejector;rejector.setInputCloud( keypoints1 );rejector.setTargetCloud( keypoints2 );rejector.setInputCorrespondences( correspondences );rejector.getCorrespondences( *correspondences ); 68
  69. 69. 初期対応付け • 2つの点群間の幾何関係を計算pcl::registration::TransformationEstimation<pcl::PointXYZI, pcl::PointXYZI>::Ptrtransformation_estimation(new pcl::registration::TransformationEstimationSVD<pcl::PointXYZI,pcl::PointXYZI>);Eigen::Matrix4f initial_transformation_matrix_;transformation_estimation->estimateRigidTransformation( *keypoints1, *keypoints2,*correspondences, initial_transformation_matrix_);pcl::transformPointCloud( *cloud1, *transformed1, initial_transformation_matrix_); 69
  70. 70. 対応付けの高精度化• ICP(Iterative Closest Point)ゕルゴリズム – 距離が最小となる点同士を対応付ける – 点群間の距離の和を最小化 70
  71. 71. 対応付けの高精度化pcl::IterativeClosestPoint<pcl::PointXYZRGB, pcl::PointXYZRGB> icp;icp.setInputCloud( cloud1 );icp.setInputTarget( cloud2 );icp.setTransformationEpsilon( 1e-6 );icp.setMaxCorrespondenceDistance( 5.0 );icp.setMaximumIterations( 200 );icp.setEuclideanFitnessEpsilon( 1.0 );icp.setRANSACOutlierRejectionThreshold( 1.0 );pcl::PointCloud<pcl::PointXYZRGB> final;icp.align(final); 71
  72. 72. 点群の統合• 2つの点群をマージ *merged = *cloud1 + *cloud2ここでは、 *merged = *cloud1_final + *cloud2点群間の重なりがあるので除去する必要がある 72
  73. 73. 点群の削減(ダウンサンプリング)• 不必要な点(同じ座標の点)の除去• 後の処理の計算コストの削減• 点群の分布の均一化 削減前 削減後 73
  74. 74. 点群の削減(ダウンサンプリング)• VoxelGridによる削減手法 – 点間の距離が一定以上になるように削減pcl::VoxelGrid< pcl::PointXYZ > vg;vg.setInputCloud( cloud );vg.setLeafSize( 0.01f, 0.01f, 0.01f );vg.setDownsampleAllData(true);vg.filter( *cloud_filtered );他に、pcl::ApproximateVoxelGridがある 74
  75. 75. メッシュ化 75
  76. 76. メッシュ化の流れ 点の法線を計算 メッシュ化 76
  77. 77. 法線計算 • 任意の点中心から一定の範囲の点群を用 いて法線方向を算出pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;ne.setInputCloud (data);pcl::search::KdTree<pcl::PointXYZ >::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ > ());ne.setSearchMethod (tree);pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);ne.setRadiusSearch (1.0);ne.compute( *normals ); 77
  78. 78. 法線の表示 • pcl::visualization::PCLVisualizerを利用pcl::visualization::PCLVisualizer> viewer ("3D Viewer");viewer.setBackgroundColor (0, 0, 0);viewer.addPointCloud<pcl::PointXY> (cloud, "sample cloud");viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");viewer.addPointCloudNormals<pcl::PointXYZ, pcl::Normal> (cloud, normals, 10, 0.05, "normals");viewer.addCoordinateSystem (1.0);viewer.initCameraParameters (); 78
  79. 79. 法線付き点群の計算 • 点群(位置)と点群(法線)をまとめて、 一つの点群(位置+法線)に変換 位置 法線 位置+法線 位置 法線 位置+法線 位置 + 法線 位置+法線 位置 法線 位置+法線pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals (new pcl::PointCloud<pcl::PointNormal>);pcl::concatenateFields (*cloud, *normals, *cloud_with_normals); 79
  80. 80. メッシュ化• メッシュ化手法がいくつか存在 – pcl::GreedyProjectionTriangulation – pcl::MarchingCubesGreedy – ・・・ 80
  81. 81. メッシュ化• pcl::GreedyProjectionTriangulationで再構成pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;gp3.setSearchRadius (0.01);gp3.setMu (2.5);gp3.setMaximumNearestNeighbors (100);gp3.setMaximumSurfaceAngle(M_PI/4);gp3.setMinimumAngle(M_PI/18);gp3.setMaximumAngle(2*M_PI/3);gp3.setNormalConsistency(false);gp3.setInputCloud (cloud_with_normals);gp3.setSearchMethod (tree2);pcl::PolygonMesh triangles;gp3.reconstruct (triangles); 81
  82. 82. 面の表示• pcl::visualization::PCLVisualizerを利用pcl::visualization::PCLVisualizer *viewer = new pcl::visualization::PCLVisualizer;viewer->setBackgroundColor (0, 0, 0);viewer->addCoordinateSystem (0.1);viewer->initCameraParameters ();viewer->addPolygonMesh( surface_ );while( !viewer->wasStopped() ){ viewer->spinOnce(); boost::this_thread::sleep (boost::posix_time::microseconds (100000));} 82
  83. 83. 構築結果• パラメータ調整が゗マ゗チ? 83

×