#include #include <pcl/io/ply_io.h> #include <pcl/point_types.h> #include <pcl/features/normal_3d.h> #include <pcl/surface/mls.h> #include <pcl/kdtree/kdtree_flann.h> #include <pcl/visualization/pcl_visualizer.h>

int main() { // 输入文件路径 std::string input_file = "D:\DIANYUNWENJIANJIA\kruskal_ply.ply";

// 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPLYFile(input_file, *cloud) == -1) {
	std::cerr << "Failed to load input file!" << std::endl;
	return -1;
}

// 手动计算法线
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud);

// 设置计算法线的K值
int k = 10;

// 遍历每个点,计算其法线
for (size_t i = 0; i < cloud->size(); i++) {
	pcl::Normal normal;
	std::vector<int> k_indices(k);
	std::vector<float> k_distances(k);
	tree->nearestKSearch(cloud->points[i], k, k_indices, k_distances);

	// 计算协方差矩阵
	Eigen::Matrix3f covariance_matrix;
	Eigen::Vector4f centroid;
	pcl::computeMeanAndCovarianceMatrix(*cloud, k_indices, covariance_matrix, centroid);

	// 使用特征值分解计算法线
	Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance_matrix, Eigen::ComputeEigenvectors);
	Eigen::Vector3f normal_vector = eigen_solver.eigenvectors().col(0);

	normal.normal_x = normal_vector[0];
	normal.normal_y = normal_vector[1];
	normal.normal_z = normal_vector[2];
	normals->push_back(normal);
}

// 阈值α
float alpha = 3.0;

// 骨架修减和节点分类
pcl::PointCloud<pcl::PointXYZ>::Ptr skeleton(new pcl::PointCloud<pcl::PointXYZ>);
std::vector<int> labels(cloud->size(), -1);
for (size_t i = 0; i < cloud->size(); i++) {
	int neighbor_count = 0;
	std::vector<int> k_indices(5);
	std::vector<float> k_distances(5);
	tree->nearestKSearch(cloud->points[i], 5, k_indices, k_distances);

	for (int j = 0; j < k_indices.size(); j++) {
		int neighbor_index = k_indices[j];
		if (cloud->points[i].y < cloud->points[neighbor_index].y) {
			neighbor_count++;
		}
	}

	if (neighbor_count < alpha) {
		labels[i] = 3;  // 丢弃的分支
	}
	else if (neighbor_count == 1) {
		labels[i] = 0;  // 叶尖
	}
	else if (neighbor_count == 2) {
		labels[i] = 1;  // 内部节点
	}
	else if (neighbor_count >= 3) {
		labels[i] = 2;  // 结点
		skeleton->push_back(cloud->points[i]);
	}
}

// 保存输出点云数据
std::string output_file = "D:\\DIANYUNWENJIANJIA\\gujiaxiujianhejiedianfenlei_ply.ply";
pcl::PointCloud<pcl::PointXYZRGB> colored_cloud;
colored_cloud.width = cloud->size();
colored_cloud.height = 1;
colored_cloud.is_dense = false;
colored_cloud.points.resize(colored_cloud.width * colored_cloud.height);
for (size_t i = 0; i < colored_cloud.points.size(); i++) {
	colored_cloud.points[i].x = cloud->points[i].x;
	colored_cloud.points[i].y = cloud->points[i].y;
	colored_cloud.points[i].z = cloud->points[i].z;
	if (labels[i] == 0) {
		colored_cloud.points[i].r = 255;
		colored_cloud.points[i].g = 0;
		colored_cloud.points[i].b = 0;
	}
	else if (labels[i] == 1) {
		colored_cloud.points[i].r = 255;
		colored_cloud.points[i].g = 255;
		colored_cloud.points[i].b = 255;
	}
	else if (labels[i] == 2) {
		colored_cloud.points[i].r = 0;
		colored_cloud.points[i].g = 255;
		colored_cloud.points[i].b = 0;
	}
	else if (labels[i] == 3) {
		colored_cloud.points[i].r = 0;
		colored_cloud.points[i].g = 0;
		colored_cloud.points[i].b = 255;
	}
}
pcl::io::savePLYFile(output_file, colored_cloud);

// 可视化点云数据
pcl::visualization::PCLVisualizer viewer("Point Cloud Viewer");
viewer.setBackgroundColor(0, 0, 0);
viewer.addPointCloud<pcl::PointXYZRGB>(colored_cloud.makeShared(), "colored_cloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "colored_cloud");
viewer.spin();

// 输出信息
std::cout << "骨架修减和节点分类已完成,结果保存在文件:" << output_file << std::endl;

return 0;

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

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