c++ pcl点云变换骨架枝干添加树叶源码实例

2023-10-22 13:36

本文主要是介绍c++ pcl点云变换骨架枝干添加树叶源码实例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

程序示例精选
c++ pcl点云变换骨架枝干添加树叶源码实例
如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助!

前言

这篇博客针对《c++ pcl点云变换骨架枝干添加树叶源码实例》编写代码,代码整洁,规则,易读。 学习与应用推荐首选。


运行结果

运行结果 运行结果 ***

文章目录

一、所需工具软件
二、使用步骤
       1. 主要代码
       2. 运行结果
三、在线协助

一、所需工具软件

       1. VS2019, Qt
       2. C++

二、使用步骤

代码如下(示例):

/*
*	Copyright (C) 2019 by
*       Shenglan Du (dushenglan940128@163.com)
*       Liangliang Nan (liangliang.nan@gmail.com)
*       3D Geoinformation, TU Delft, https://3d.bk.tudelft.nl
*
*	This file is part of AdTree, which implements the 3D tree
*   reconstruction method described in the following paper:
*   -------------------------------------------------------------------------------------
*       Shenglan Du, Roderik Lindenbergh, Hugo Ledoux, Jantien Stoter, and Liangliang Nan.
*       AdTree: Accurate, Detailed, and Automatic Modeling of Laser-Scanned Trees.
*       Remote Sensing. 2019, 11(18), 2074.
*   -------------------------------------------------------------------------------------
*   Please consider citing the above paper if you use the code/program (or part of it).
*
*	AdTree is free software; you can redistribute it and/or modify
*	it under the terms of the GNU General Public License Version 3
*	as published by the Free Software Foundation.
*
*	AdTree is distributed in the hope that it will be useful,
*	but WITHOUT ANY WARRANTY; without even the implied warranty of
*	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*	GNU General Public License for more details.
*
*	You should have received a copy of the GNU General Public License
*	along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// save the smoothed skeleton into a PLY file (where each vertex has a radius)
void save_skeleton(Skeleton* skeleton, PointCloud* cloud, const std::string& file_name) {const ::Graph& sgraph = skeleton->get_smoothed_skeleton();if (boost::num_edges(sgraph) == 0) {std::cerr << "failed to save skeleton (no edge exists)" << std::endl;return;}// convert the boost graph to Graph (avoid modifying easy3d's GraphIO, or writing IO for boost graph)std::unordered_map<SGraphVertexDescriptor, easy3d::Graph::Vertex>  vvmap;easy3d::Graph g;auto vertexRadius = g.add_vertex_property<float>("v:radius");auto vts = boost::vertices(sgraph);for (SGraphVertexIterator iter = vts.first; iter != vts.second; ++iter) {SGraphVertexDescriptor vd = *iter;if (boost::degree(vd, sgraph) != 0) { // ignore isolated verticesconst vec3& vp = sgraph[vd].cVert;auto v = g.add_vertex(vp);vertexRadius[v] = sgraph[vd].radius;vvmap[vd] = v;}}auto egs = boost::edges(sgraph);for (SGraphEdgeIterator iter = egs.first; iter != egs.second; ++iter) {SGraphEdgeDescriptor ed = *iter;    // the edge descriptorSGraphEdgeProp ep = sgraph[ed];   // the edge propertySGraphVertexDescriptor s = boost::source(*iter, sgraph);SGraphVertexDescriptor t = boost::target(*iter, sgraph);g.add_edge(vvmap[s], vvmap[t]);}auto offset = cloud->get_model_property<dvec3>("translation");if (offset) {auto prop = g.model_property<dvec3>("translation");prop[0] = offset[0];}if (GraphIO::save(file_name, &g))std::cout << "model of skeletons saved to: " << file_name << std::endl;elsestd::cerr << "failed to save the model of skeletons into file" << std::endl;
}// returns the number of processed input files.
int batch_reconstruct(std::vector<std::string>& point_cloud_files, const std::string& output_folder, bool export_skeleton) {int count(0);for (std::size_t i=0; i<point_cloud_files.size(); ++i) {const std::string& xyz_file = point_cloud_files[i];std::cout << "------------- " << i + 1 << "/" << point_cloud_files.size() << " -------------" << std::endl;std::cout << "processing xyz_file: " << xyz_file << std::endl;if (!file_system::is_directory(output_folder)) {if (file_system::create_directory(output_folder))std::cout << "created output directory '" << output_folder << "'" << std::endl;else {std::cerr << "failed creating output directory" << std::endl;return 0;}}// load point_cloudPointCloud *cloud = PointCloudIO::load(xyz_file);if (cloud) {std::cout << "cloud loaded. num points: " << cloud->n_vertices() << std::endl;// compute bboxBox3 box;auto points = cloud->get_vertex_property<vec3>("v:point");for (auto v : cloud->vertices())box.add_point(points[v]);// remove duplicated pointsconst float threshold = box.diagonal() * 0.001f;const auto &points_to_remove = RemoveDuplication::apply(cloud, threshold);for (auto v : points_to_remove)cloud->delete_vertex(v);cloud->garbage_collection();std::cout << "removed too-close points. num points: " << cloud->n_vertices() << std::endl;}else {std::cerr << "failed to load point cloud from '" << xyz_file << "'" << std::endl;continue;}// reconstruct branchesSurfaceMesh *mesh = new SurfaceMesh;const std::string &branch_filename = file_system::base_name(cloud->name()) + "_branches.obj";mesh->set_name(branch_filename);Skeleton *skeleton = new Skeleton();bool status = skeleton->reconstruct_branches(cloud, mesh);if (!status) {std::cerr << "failed in reconstructing branches" << std::endl;delete cloud;delete mesh;delete skeleton;continue;}// copy translation property from point_cloud to surface_meshSurfaceMesh::ModelProperty<dvec3> prop = mesh->add_model_property<dvec3>("translation");prop[0] = cloud->get_model_property<dvec3>("translation")[0];// save branches modelconst std::string branch_file = output_folder + "/" + branch_filename;if (SurfaceMeshIO::save(branch_file, mesh)) {std::cout << "model of branches saved to: " << branch_file << std::endl;++count;}elsestd::cerr << "failed to save the model of branches" << std::endl;if (export_skeleton) {const std::string& skeleton_file = output_folder + "/" + file_system::base_name(cloud->name()) + "_skeleton.ply";save_skeleton(skeleton, cloud, skeleton_file);}delete cloud;delete mesh;delete skeleton;}return count;
}int main(int argc, char *argv[]) {
//    argc = 2;
//    argv[1] = "/Users/lnan/Projects/adtree/data";
//    argv[2] = "/Users/lnan/Projects/adtree/data-results";if (argc == 1) {TreeViewer viewer;viewer.run();return EXIT_SUCCESS;} else if (argc >= 3) {bool export_skeleton = false;for (int i = 0; i < argc; ++i) {if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-skeleton") == 0) {export_skeleton = true;break;}}if (export_skeleton) {std::cout << "You have requested to save the reconstructed tree skeleton(s) in PLY format into the output directory." << std::endl;std::cout << "The skeleton file(s) can be visualized using Easy3D: https://github.com/LiangliangNan/Easy3D" << std::endl;}elsestd::cout << "Tree skeleton(s) will not be saved (append '-s' or '-skeleton' in commandline to enable it)" << std::endl;std::string first_arg(argv[1]);std::string second_arg(argv[2]);if (file_system::is_file(second_arg))std::cerr << "WARNING: second argument cannot be an existing file (expecting a directory)." << std::endl;else {std::string output_dir = second_arg;if (file_system::is_file(first_arg)) {std::vector<std::string> cloud_files = {first_arg};return batch_reconstruct(cloud_files, output_dir, export_skeleton) > 0;} else if (file_system::is_directory(first_arg)) {std::vector<std::string> entries;file_system::get_directory_entries(first_arg, entries, false);std::vector<std::string> cloud_files;for (const auto &file_name : entries) {if (file_name.size() > 3 && file_name.substr(file_name.size() - 3) == "xyz")cloud_files.push_back(first_arg + "/" + file_name);}return batch_reconstruct(cloud_files, output_dir, export_skeleton) > 0;} elsestd::cerr<< "WARNING: unknown first argument (expecting either a point cloud file in *.xyz format or a\n""\tdirectory containing *.xyz point cloud files)." << std::endl;}}return EXIT_FAILURE;
}
运行结果
运行结果 运行结果

三、在线协助:

如需安装运行环境或远程调试,见文章底部个人 QQ 名片,由专业技术人员远程协助!

1)远程安装运行环境,代码调试
2)Visual Studio, Qt, C++, Python编程语言入门指导
3)界面美化
4)软件制作
5)云服务器申请
6)网站制作

当前文章连接:https://blog.csdn.net/alicema1111/article/details/132666851
个人博客主页:https://blog.csdn.net/alicema1111?type=blog
博主所有文章点这里:https://blog.csdn.net/alicema1111?type=blog

博主推荐:
Python人脸识别考勤打卡系统:
https://blog.csdn.net/alicema1111/article/details/133434445
Python果树水果识别:https://blog.csdn.net/alicema1111/article/details/130862842
Python+Yolov8+Deepsort入口人流量统计:https://blog.csdn.net/alicema1111/article/details/130454430
Python+Qt人脸识别门禁管理系统:https://blog.csdn.net/alicema1111/article/details/130353433
Python+Qt指纹录入识别考勤系统:https://blog.csdn.net/alicema1111/article/details/129338432
Python Yolov5火焰烟雾识别源码分享:https://blog.csdn.net/alicema1111/article/details/128420453
Python+Yolov8路面桥梁墙体裂缝识别:https://blog.csdn.net/alicema1111/article/details/133434445

这篇关于c++ pcl点云变换骨架枝干添加树叶源码实例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/261770

相关文章

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

C++11委托构造函数和继承构造函数的实现

《C++11委托构造函数和继承构造函数的实现》C++引入了委托构造函数和继承构造函数这两个重要的特性,本文主要介绍了C++11委托构造函数和继承构造函数的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、委托构造函数1.1 委托构造函数的定义与作用1.2 委托构造函数的语法1.3 委托构造函

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C

C++链表的虚拟头节点实现细节及注意事项

《C++链表的虚拟头节点实现细节及注意事项》虚拟头节点是链表操作中极为实用的设计技巧,它通过在链表真实头部前添加一个特殊节点,有效简化边界条件处理,:本文主要介绍C++链表的虚拟头节点实现细节及注... 目录C++链表虚拟头节点(Dummy Head)一、虚拟头节点的本质与核心作用1. 定义2. 核心价值二