使用 PCL 1.8.1 从点云数据中提取植物结构

本教程演示了如何使用 PCL 1.8.1 从点云数据中提取植物结构,包括茎、叶和轮廓。代码示例展示了点云分割、骨架图分析和点云聚类等关键步骤。

1. 准备工作

首先,你需要安装 PCL 1.8.1 并包含必要的头文件。

#include <iostream>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/region_growing.h>

2. 加载点云数据

从文件加载点云数据。

// 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PLYReader reader;
reader.read('D:\DIANYUNWENJIA\test5_ply.ply', *cloud);

3. 提取植物轮廓

使用 PassThrough 滤波器移除高于植物轮廓的点。

// PassThrough 滤波器移除高于植物轮廓的点
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName('z');
pass.setFilterLimits(0.0, 1.0); // 调整此值以设置植物轮廓
pass.filter(*cloud);

4. 提取茎

使用区域生长分割提取茎点。

// 区域生长分割提取茎点
pcl::search::Search<pcl::PointXYZ>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> >(new pcl::search::KdTree<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
normal_estimator.setSearchMethod(tree);
normal_estimator.setInputCloud(cloud);
normal_estimator.setKSearch(50);
normal_estimator.compute(*normals);
pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
reg.setMinClusterSize(50);
reg.setMaxClusterSize(1000000);
reg.setSearchMethod(tree);
reg.setNumberOfNeighbours(30);
reg.setInputCloud(cloud);
reg.setInputNormals(normals);
reg.setSmoothnessThreshold(3.0 / 180.0 * M_PI);
reg.setCurvatureThreshold(1.0);
std::vector<pcl::PointIndices> clusters;
reg.extract(clusters);

5. 重连接骨架图中的一度节点

你需要根据提取出的茎点重新连接骨架图中的一度节点。这部分代码需要根据具体情况进行调整。

// 重连接骨架图中的一度节点
// ...

6. 分割骨架图并标记节点

将骨架图分割成多个部分,每个部分都以叶尖为起点,以交叉节点为终点。如果部分的一个端点是茎的一部分,则将其标记为叶子。

// 分割骨架图并标记节点
// ...

7. 聚类并标记点云数据

使用点云聚类,并根据聚类结果和骨架图中的连接关系进行分割和标记。

// 聚类并标记点云数据
// ...

8. 保存结果

将分割后的点云数据保存到文件。

// 保存分割后的点云数据
pcl::PLYWriter writer;
writer.write('D:\DIANYUNWENJIA\test6_ply.ply', *cloud);

完整代码

#include <iostream>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/region_growing.h>

int main()
{
    // 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PLYReader reader;
reader.read('D:\DIANYUNWENJIA\test5_ply.ply', *cloud);

    // PassThrough 滤波器移除高于植物轮廓的点
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName('z');
pass.setFilterLimits(0.0, 1.0); // 调整此值以设置植物轮廓
pass.filter(*cloud);

    // 区域生长分割提取茎点
pcl::search::Search<pcl::PointXYZ>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> >(new pcl::search::KdTree<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
normal_estimator.setSearchMethod(tree);
normal_estimator.setInputCloud(cloud);
normal_estimator.setKSearch(50);
normal_estimator.compute(*normals);
pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
reg.setMinClusterSize(50);
reg.setMaxClusterSize(1000000);
reg.setSearchMethod(tree);
reg.setNumberOfNeighbours(30);
reg.setInputCloud(cloud);
reg.setInputNormals(normals);
reg.setSmoothnessThreshold(3.0 / 180.0 * M_PI);
reg.setCurvatureThreshold(1.0);
std::vector<pcl::PointIndices> clusters;
reg.extract(clusters);

    // 重连接骨架图中的一度节点
    // ...

    // 分割骨架图并标记节点
    // ...

    // 聚类并标记点云数据
    // ...

    // 保存分割后的点云数据
pcl::PLYWriter writer;
writer.write('D:\DIANYUNWENJIA\test6_ply.ply', *cloud);

    return 0;
}

注意事项

  • 代码中的参数需要根据具体情况进行调整。
  • 骨架图的分析和节点的标记需要根据具体情况进行实现。
  • 此代码仅提供了一个基本框架,你需要根据实际情况进行修改和完善。

希望本教程能够帮助你使用 PCL 从点云数据中提取植物结构。

使用 PCL 1.8.1 从点云数据中提取植物结构

原文地址: https://www.cveoy.top/t/topic/ozS4 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录