点云技术相关产学研社区

 找回密码
 立即注册加入PCL中国点云技术相关产学研社区

扫一扫,访问微社区

查看: 13110|回复: 10

使用convex_hull计算体积为0

[复制链接]
发表于 2014-7-13 21:56:43 | 显示全部楼层 |阅读模式
大家好,我尝试用convex_hall去计算点云的体积,但是编译通过之后体积算出来是0,不知道是哪里出了问题。希望大家能不吝赐教,谢谢大家~下面贴出我的代码:
#include <pcl/io/pcd_io.h>
#include <pcl/io/vtk_io.h>
#include <pcl/surface/concave_hull.h>
#include <pcl/surface/convex_hull.h>

#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

using namespace std;
using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

float default_alpha = 0.15f;

void
printHelp (int, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.vtk [optional_arguments]\n", argv[0]);
  print_info ("  where the optional arguments are:\n");
  print_info ("                     -alpha X = the alpha value for the ConcaveHull (Alpha Shapes) algorithm. If alpha is not specified, the tool will run the ConvexHull method (default: ");
  print_value ("%f", default_alpha); print_info (")\n");
}


float
compute (PointCloud<PointXYZ>::ConstPtr cloud_in,
         bool convex_concave_hull,
         float alpha,
         PolygonMesh &mesh_out)
{
  float volume;
  if (!convex_concave_hull)
  {
    print_info ("Computing the convex hull of a cloud with %zu points.\n", cloud_in->size ());
    ConvexHull<PointXYZ> convex_hull;
    convex_hull.setInputCloud (cloud_in);
    convex_hull.reconstruct (mesh_out);
        convex_hull.setComputeAreaVolume(true);
        volume=convex_hull.getTotalVolume();
        return volume;
  }
  else
  {
    print_info ("Computing the concave hull (alpha shapes) with alpha %f of a cloud with %zu points.\n", alpha, cloud_in->size ());
    ConcaveHull<PointXYZ> concave_hull;
    concave_hull.setInputCloud (cloud_in);
    concave_hull.setAlpha (alpha);
    concave_hull.reconstruct (mesh_out);
  }
}


/* ---[ */
int
main (int argc, char** argv)
{
   float volume;
        print_info ("Compute the convex or concave hull of a point cloud. For more information, use: %s -h\n", argv[0]);

// if (argc < 3)
//  {
     printHelp (argc, argv);
//  return (-1);
//  }

  // Command line parsing
  bool convex_concave_hull = false;
  float alpha = default_alpha;

  if (parse_argument (argc, argv, "-alpha", alpha) != -1)
    convex_concave_hull = true;

  vector<int> pcd_file_indices;
  pcd_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (pcd_file_indices.size () != 1)
  {
    print_error ("Need one input PCD file to continue.\n");
    return (-1);
  }

  vector<int> vtk_file_indices;
  vtk_file_indices = parse_file_extension_argument (argc, argv, ".vtk");
  if (vtk_file_indices.size () != 1)
  {
    print_error ("Need one ouput VTK file to continue.\n");
    return (-1);
  }


  // Load in the point cloud
  PointCloud<PointXYZ>::Ptr cloud_in (new PointCloud<PointXYZ> ());
  if (loadPCDFile (argv[pcd_file_indices[0]], *cloud_in) != 0)
  {
    print_error ("Could not load input file %s\n", argv[pcd_file_indices[0]]);
    return (-1);
  }

  // Compute the hull
  PolygonMesh mesh_out;
  volume=compute (cloud_in, convex_concave_hull, alpha, mesh_out);

  // Save the mesh
  io::saveVTKFile (argv[vtk_file_indices[0]], mesh_out);
  cout<<"The volume is "<<volume;
  return (0);
}

回复

使用道具 举报

发表于 2014-7-14 01:45:51 | 显示全部楼层
没用过,不过你的数据是什么样的,2d hull输出肯定不对的。我以前好像看过个帖子,目前貌似就是3D的hull正常吧。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-14 02:26:11 | 显示全部楼层
guohaolys 发表于 2014-7-14 01:45
没用过,不过你的数据是什么样的,2d hull输出肯定不对的。我以前好像看过个帖子,目前貌似就是3D的hull正 ...

为了方便比较结果,我导入的PCD是一个标准的半径为1的球体,我尝试用2d的hull做每个面的凸包,再积分求体积,但是没有做出来,这个是用体凸包做的,不知道在reconstruct后,设置convex_hull.setComputeAreaVolume(true),是否就可以直接调用convex_hull.getTotalVolume()计算体积?难道是形状对计算结果影响非常大?
回复 支持 反对

使用道具 举报

发表于 2014-7-14 09:02:08 | 显示全部楼层
玉阳呈映 发表于 2014-7-14 02:26
为了方便比较结果,我导入的PCD是一个标准的半径为1的球体,我尝试用2d的hull做每个面的凸包,再积分求体 ...

用一个标准球来测试挺有意思的,你可以直接试一试,就先setComputeAreaVolume设置为true之后,再重建,再获取体积getTotalVolume,pcl其实什么都没做,就是直接把qhull的计算结果给输出了。qhull我以前用过,是可以有个体积的输出,直接的准确度,的确不好说了。
回复 支持 反对

使用道具 举报

发表于 2014-7-14 09:03:17 | 显示全部楼层
guohaolys 发表于 2014-7-14 09:02
用一个标准球来测试挺有意思的,你可以直接试一试,就先setComputeAreaVolume设置为true之后,再重建,再 ...

  ConvexHull<PointXYZ> convex_hull;
    convex_hull.setInputCloud (cloud_in);
    convex_hull.reconstruct (mesh_out);
        convex_hull.setComputeAreaVolume(true);
        volume=convex_hull.getTotalVolume();
        return volume;
这里的顺序,你可以调整下,把设置 convex_hull.setComputeAreaVolume(true);放在重建调用之前。反馈下测试结果啊,谢谢了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-14 10:14:28 | 显示全部楼层
guohaolys 发表于 2014-7-14 09:03
ConvexHull convex_hull;
    convex_hull.setInputCloud (cloud_in);
    convex_hull.reconstruct (me ...

刚刚按照您所说的,将convex_hull.setInputCloud (cloud_in) 和convex_hull.reconstruct (mesh_out)交换了一下位置,用标准球进行测试得到的结果为4.23263,相比标准值4.1888的误差为1%.而用标准立方体测试的结果为1.26654,相比标准值的误差为26.65%,误差非常大。理论上,正方体的误差应该比球要小得多,因为没办法对参数进行调整,这个凸包算法的唯一输入就只有xyz点云,所以不知道原因是什么?
E:\1.pngE:\1.png
回复 支持 反对

使用道具 举报

发表于 2014-7-14 10:28:18 | 显示全部楼层
凸包算法对不闭合的曲面也试用吗?它不闭合的面是怎么处理的?
回复 支持 反对

使用道具 举报

发表于 2014-7-14 12:29:26 | 显示全部楼层
玉阳呈映 发表于 2014-7-14 10:14
刚刚按照您所说的,将convex_hull.setInputCloud (cloud_in) 和convex_hull.reconstruct (mesh_out)交换 ...

蛮好啊,既然你有现成的测试代码,就带大家多测试下。
对于立方体测试的误差大,我的理解是,你测试的点云采样的密度?是多少,8个点确定一个立方体,可能是最准确的,可以试一试持续增加采样密度,结果应该很不一样。因为qhull它不可能准确的把这些重建的三角面都放在一个平面上。我对qhull本身实现不了解,但它这个convex_hull名字,就让我想到它应该尽可能使所有8个平面上的所有小三角形都往外凸,因为最终必须形成凸包,体积是不是就大很多了。
但圆球上就有点不一样了,它本身这些小三角形,就自然形成convex啊。所以可能测试就准确些。
假设我说的是对的,你如果测试了,应该立方体,的采样密度和体积的误差是成正比的。但圆球可能就刚好相反了,你采样点越少误差自然越大,采样点越多就貌似天然的精度高了。
试一试啊,结果截个图看看,你发的图片(前个帖子看不到)。。期待回复,谢谢啊。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-14 14:57:13 | 显示全部楼层
刚刚做了下测试,采用下采样的方法减小点云密度,测试pcd为扫描得到的一个直三棱锥(正方体的一角)原始点云的点数为52801,用matlab的convexhull作面凸包积分测得的体积为19.288,下采样后,点数为20741时,面凸包积分得到的体积为19.111,点数为8871时,面凸包积分得到的体积为19.233.
用上面的程序做体凸包,未处理时体积为 25.8631   点数为20741时,体积为25.7876 点数为8871时,体积为25.6336   和理论值相差有点大。
回复 支持 反对

使用道具 举报

发表于 2017-8-30 10:10:16 | 显示全部楼层
解释很好
回复 支持 反对

使用道具 举报

本版积分规则

QQ|小黑屋|点云技术相关产学研社区 ( 陕ICP备13001629号 )

GMT+8, 2024-5-5 17:42 , Processed in 7.099525 second(s), 16 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表