2012年11月4日日曜日

PCL メッシュの再構築のテスト2

pcl::GreedyProjectionTriangulationのテスト

入力元の点群


フィルタリング結果


再構築結果

残念、欠けている部分がちらほらとある



pcl::GreedyProjectionTriangulationのテスト

#include <stdio.h>
#include <boost/thread/thread.hpp>
// pcl
#include <pcl/point_cloud.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>


// PCLVisualizer のテスト
void TestCloudViewer003(const char* pFilePath)
{
  // テキストファイルから頂点を取得
  FILE* fp = fopen(pFilePath, "rt");
  
  int n;
  char buf[256];
  fscanf(fp, "%s %d", buf, &n);

  int num = n;

  // 点群の作成
  pcl::PointCloud::Ptr cloud( new pcl::PointCloud );

  cloud->width = num;
  cloud->height = 1;
  cloud->points.resize( cloud->width * cloud->height );

  int txtFmt = 1;
  float x, y, z;
  for(int i = 0; i < num; i++)
  {
    switch(txtFmt) {
    case 0:
      fscanf(fp, "%f %f %f", &x, &y, &z);
      break;
    case 1:
      fscanf(fp, "%f, %f, %f", &x, &y, &z);
      break;
    }
    cloud->points[i] = pcl::PointXYZ(x, y, z);
  }
  fclose(fp);

  // 点群の削減

  // フィルタリング結果の格納用
  pcl::PointCloud::Ptr filtered_cloud( new pcl::PointCloud );

  // ボクセルグリッドで点群のフィルタリングを行う
  pcl::VoxelGrid sor;
  sor.setInputCloud (cloud);
  sor.setLeafSize(1.0f, 1.0f, 1.0f);
  sor.filter(*filtered_cloud);

  // 点群の数を出力
  printf("source cloud size = %d\n", cloud->size());
  printf("filtered cloud size = %d\n", filtered_cloud->size());

  // 元データ
  pcl::PointCloud::Ptr src_cloud = filtered_cloud;

  pcl::PolygonMesh polyMesh;

  // KdTreeを作成
  pcl::search::KdTree::Ptr tree(new pcl::search::KdTree);
  float epsilon = tree->getEpsilon();
  tree->setEpsilon(0.01f);
    tree->setInputCloud(src_cloud); 

  // 法線ベクトルの推定
  pcl::NormalEstimation ne; 
    ne.setInputCloud(src_cloud); 
    ne.setSearchMethod(tree); 
    ne.setKSearch(8);

  // 法線ベクトル格納用
  pcl::PointCloud::Ptr norm(new pcl::PointCloud); 
    ne.compute(*norm);

  // 座標と法線ベクトルの点群
  pcl::PointCloud::Ptr clPosNormal(new pcl::PointCloud);
    pcl::concatenateFields(*src_cloud, *norm, *clPosNormal); 

  // ↓今回のテスト対象
  pcl::GreedyProjectionTriangulation gpt;

  pcl::search::KdTree::Ptr tree2 (new pcl::search::KdTree);
    tree2->setInputCloud(clPosNormal); 

  // パラメータをいろいろ設定
  gpt.setSearchRadius(20.0);
  gpt.setMu(2.5);
  gpt.setMaximumNearestNeighbors (150);
//  gpt.setMaximumSurfaceAngle(M_PI/4);
//  gpt.setMinimumAngle(M_PI/18);
//  gpt.setMaximumAngle(2*M_PI/3);
//  gpt.setNormalConsistency(false);

  // 入力データ等をセット
  gpt.setInputCloud (clPosNormal);
  gpt.setSearchMethod (tree2);

  // 再構築
  gpt.reconstruct (polyMesh);

  // 点群のビューア
  pcl::visualization::PCLVisualizer viewer("Cloud Viewer");
  
  viewer.setBackgroundColor (0.0, 0.2, 0.6);

  // 原点に座標軸を追加
  viewer.addCoordinateSystem(100.0, 0.0, 0.0, 0.0);

  // カメラ座標のセット
  double camPos[] = { 0.0, 60.0, 350.0 };
  double camLookAt[] = { 0.0, 60.0, 0.0 };
  double camUp[] = { 0.0, 1.0, 0.0 };
  viewer.setCameraPose(camPos[0], camPos[1], camPos[2], 
    camLookAt[0], camLookAt[1], camLookAt[2], camUp[0], camUp[1], camUp[2]);

  // ビューアに点群を追加
//  viewer.addPointCloud(filtered_cloud);
  viewer.addPointCloud(cloud);

  // ビューアにポリゴンメッシュを追加
//  viewer.addPolygonMesh(polyMesh);

    while (!viewer.wasStopped ())
    {
    viewer.spinOnce(10);

    boost::this_thread::sleep (boost::posix_time::microseconds (100000));
    }
}

int main(int argc, char** argv)
{
  TestCloudViewer003(argv[1]);

  return 0;
}