PCL-B样条曲面重建

1. 算法原理

Fitting trimmed B-splines to unordered point clouds

2. 代码实现

main.cpp

#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>

#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/surface/on_nurbs/fitting_surface_tdm.h>
#include <pcl/surface/on_nurbs/fitting_curve_2d_asdm.h>
#include <pcl/surface/on_nurbs/triangulation.h>

using Point = pcl::PointXYZ;

void
PointCloud2Vector3d(pcl::PointCloud<Point>::Ptr cloud, pcl::on_nurbs::vector_vec3d &data);

void
visualizeCurve(ON_NurbsCurve &curve,
               ON_NurbsSurface &surface,
               pcl::visualization::PCLVisualizer &viewer);

int
main() {
    std::string pcd_file = "bunny.pcd";
    std::string file_3dm = "bunny.ply";

    pcl::visualization::PCLVisualizer viewer("B-spline surface fitting");
    viewer.setSize(800, 600);

    // ############################################################################
    // load point cloud

    printf("  loading %s\n", pcd_file.c_str());
    pcl::PointCloud<Point>::Ptr cloud(new pcl::PointCloud<Point>);
    pcl::PCLPointCloud2 cloud2;
    pcl::on_nurbs::NurbsDataSurface data;

    if (pcl::io::loadPCDFile(pcd_file, cloud2) == -1)
        throw std::runtime_error("  PCD file not found.");

    fromPCLPointCloud2(cloud2, *cloud);
    PointCloud2Vector3d(cloud, data.interior);
    pcl::visualization::PointCloudColorHandlerCustom<Point> handler(cloud, 0, 255, 0);
    viewer.addPointCloud<Point>(cloud, handler, "cloud_cylinder");
    printf("  %lu points in data set\n", cloud->size());

    // ############################################################################
    // fit B-spline surface

    // parameters
    unsigned order(3);
    unsigned refinement(5);
    unsigned iterations(10);
    unsigned mesh_resolution(256);

    pcl::on_nurbs::FittingSurface::Parameter params;
    params.interior_smoothness = 0.2;
    params.interior_weight = 1.0;
    params.boundary_smoothness = 0.2;
    params.boundary_weight = 0.0;

    // initialize
    printf("  surface fitting ...\n");
    ON_NurbsSurface nurbs = pcl::on_nurbs::FittingSurface::initNurbsPCABoundingBox(order, &data);
    pcl::on_nurbs::FittingSurface fit(&data, nurbs);
    //  fit.setQuiet (false); // enable/disable debug output

    // mesh for visualization
    pcl::PolygonMesh mesh;
    pcl::PointCloud<pcl::PointXYZ>::Ptr mesh_cloud(new pcl::PointCloud<pcl::PointXYZ>);
    std::vector<pcl::Vertices> mesh_vertices;
    std::string mesh_id = "mesh_nurbs";
    pcl::on_nurbs::Triangulation::convertSurface2PolygonMesh(fit.m_nurbs, mesh, mesh_resolution);
    viewer.addPolygonMesh(mesh, mesh_id);

    // surface refinement
    for (unsigned i = 0; i < refinement; i++) {
        fit.refine(0);
        fit.refine(1);
        fit.assemble(params);
        fit.solve();
        pcl::on_nurbs::Triangulation::convertSurface2Vertices(fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution);
        viewer.updatePolygonMesh<pcl::PointXYZ>(mesh_cloud, mesh_vertices, mesh_id);
        viewer.spinOnce();
    }

    // surface fitting with final refinement level
    for (unsigned i = 0; i < iterations; i++) {
        fit.assemble(params);
        fit.solve();
        pcl::on_nurbs::Triangulation::convertSurface2Vertices(fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution);
        viewer.updatePolygonMesh<pcl::PointXYZ>(mesh_cloud, mesh_vertices, mesh_id);
        viewer.spinOnce();
    }

    // ############################################################################
    // fit B-spline curve

    // parameters
    pcl::on_nurbs::FittingCurve2dAPDM::FitParameter curve_params;
    curve_params.addCPsAccuracy = 5e-2;
    curve_params.addCPsIteration = 3;
    curve_params.maxCPs = 200;
    curve_params.accuracy = 1e-3;
    curve_params.iterations = 100;

    curve_params.param.closest_point_resolution = 0;
    curve_params.param.closest_point_weight = 1.0;
    curve_params.param.closest_point_sigma2 = 0.1;
    curve_params.param.interior_sigma2 = 0.00001;
    curve_params.param.smooth_concavity = 1.0;
    curve_params.param.smoothness = 1.0;

    // initialisation (circular)
    printf("  curve fitting ...\n");
    pcl::on_nurbs::NurbsDataCurve2d curve_data;
    curve_data.interior = data.interior_param;
    curve_data.interior_weight_function.push_back(true);
    ON_NurbsCurve curve_nurbs = pcl::on_nurbs::FittingCurve2dAPDM::initNurbsCurve2D(order, curve_data.interior);

    // curve fitting
    pcl::on_nurbs::FittingCurve2dASDM curve_fit(&curve_data, curve_nurbs);
    // curve_fit.setQuiet (false); // enable/disable debug output
    curve_fit.fitting(curve_params);
    visualizeCurve(curve_fit.m_nurbs, fit.m_nurbs, viewer);

    // ############################################################################
    // triangulation of trimmed surface

    printf("  triangulate trimmed surface ...\n");
    viewer.removePolygonMesh(mesh_id);
    pcl::on_nurbs::Triangulation::convertTrimmedSurface2PolygonMesh(fit.m_nurbs, curve_fit.m_nurbs, mesh,
                                                                    mesh_resolution);
    viewer.addPolygonMesh(mesh, mesh_id);


    // save trimmed B-spline surface
    if (fit.m_nurbs.IsValid()) {
        ONX_Model model;
        ONX_Model_Object &surf = model.m_object_table.AppendNew();
        surf.m_object = new ON_NurbsSurface(fit.m_nurbs);
        surf.m_bDeleteObject = true;
        surf.m_attributes.m_layer_index = 1;
        surf.m_attributes.m_name = "surface";

        ONX_Model_Object &curv = model.m_object_table.AppendNew();
        curv.m_object = new ON_NurbsCurve(curve_fit.m_nurbs);
        curv.m_bDeleteObject = true;
        curv.m_attributes.m_layer_index = 2;
        curv.m_attributes.m_name = "trimming curve";

        model.Write(file_3dm.c_str());
        printf("  model saved: %s\n", file_3dm.c_str());
    }

    printf("  ... done.\n");

    viewer.spin();
    return 0;
}

void
PointCloud2Vector3d(pcl::PointCloud<Point>::Ptr cloud, pcl::on_nurbs::vector_vec3d &data) {
    for (const auto &p : *cloud) {
        if (!std::isnan(p.x) && !std::isnan(p.y) && !std::isnan(p.z))
            data.emplace_back(p.x, p.y, p.z);
    }
}

void
visualizeCurve(ON_NurbsCurve &curve, ON_NurbsSurface &surface, pcl::visualization::PCLVisualizer &viewer) {
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr curve_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);

    pcl::on_nurbs::Triangulation::convertCurve2PointCloud(curve, surface, curve_cloud, 4);
    for (std::size_t i = 0; i < curve_cloud->size() - 1; i++) {
        pcl::PointXYZRGB &p1 = curve_cloud->at(i);
        pcl::PointXYZRGB &p2 = curve_cloud->at(i + 1);
        std::ostringstream os;
        os << "line" << i;
        viewer.removeShape(os.str());
        viewer.addLine<pcl::PointXYZRGB>(p1, p2, 1.0, 0.0, 0.0, os.str());
    }

    pcl::PointCloud<pcl::PointXYZRGB>::Ptr curve_cps(new pcl::PointCloud<pcl::PointXYZRGB>);
    for (int i = 0; i < curve.CVCount(); i++) {
        ON_3dPoint p1;
        curve.GetCV(i, p1);

        double pnt[3];
        surface.Evaluate(p1.x, p1.y, 0, 3, pnt);
        pcl::PointXYZRGB p2;
        p2.x = float(pnt[0]);
        p2.y = float(pnt[1]);
        p2.z = float(pnt[2]);

        p2.r = 255;
        p2.g = 0;
        p2.b = 0;

        curve_cps->push_back(p2);
    }
    viewer.removePointCloud("cloud_cps");
    viewer.addPointCloud(curve_cps, "cloud_cps");
}

CmakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(BSurface)

set(CMAKE_CXX_STANDARD 11)

find_package(PCL 1.10 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable(BSurface main.cpp)
target_link_libraries(BSurface ${PCL_LIBRARIES})

3. 结果展示

实验环境:ubuntu 18.04,PCL 1.10
在这里插入图片描述
存在问题是曲面拟合速度很慢。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
pcl(Point Cloud Library)是一个用于点云处理的开源库,其中包含了许多用于点云获取、处理和分析的算法和工具。其中,基于b样条曲线的曲面重建pcl中的一项重要功能。 b样条曲线(B-spline curve)是一种通过一系列控制点来定义曲线的数学曲线。在pcl中,基于b样条曲线的曲面重建是通过平滑点云数据来生成连续曲面的一种方法。它能够将离散的点云数据转换为连续的曲面模型,从而更好地描述点云的形状和表面特征。 基于b样条曲线的曲面重建pcl中的实现过程主要包括以下几个步骤: 1. 数据准备:从采集的点云数据中提取出感兴趣的区域。 2. 点云预处理:对提取的点云进行滤波、去噪、降采样等操作,以减少噪声和计算复杂度。 3. 曲面重建参数设置:设置曲面生成的参数,如平滑度、控制点个数等。 4. 点云转换:将点云数据转换为pcl中的曲面表示方式,如三角网格、曲面片等。 5. 曲面重建算法应用:使用曲面重建算法,如Moving Least Squares(MLS)方法,基于局部邻域进行平滑曲面估计。 6. 优化与调整:对生成的曲面进行进一步优化和调整,以获得更精确和平滑的曲面模型。 7. 结果可视化:将曲面重建结果进行可视化展示,以便用户查看和分析。 基于b样条曲线的曲面重建能够有效地处理点云数据,生成平滑的曲面模型。这在许多领域中都有广泛的应用,如数字化建模、三维重建、医学图像处理等。通过pcl提供的功能,我们可以方便地实现基于b样条曲线的曲面重建,并应用于实际问题中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值