场景:
一平板上沾有多个球,使用激光扫描仪获取点云,包括平板点云+多个球冠点云;
问题:
提取各球点云,拟合球面参数,求取球到平板距离。
解决思路:
(1)求平板平面:降采样,提取最大平面;
(2)剔除距离平面一定距离范围内的点,余下所有球冠点;
(3)点云聚类,忽略点数较少的簇,剩余较大的簇拟合球,计算球-平面距离。
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h> // 用于保存点云(可选)
#include <pcl/common/centroid.h>
#include <pcl/common/common.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_sphere.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/segmentation/conditional_euclidean_clustering.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/statistical_outlier_removal.h> // 包含StatisticalOutlierRemoval头文件
#include <pcl/filters/random_sample.h> // 包含RandomSample头文件
#include <pcl/visualization/pcl_visualizer.h>
#include <chrono>
#include <iomanip> // 用于格式化输出
#include <ctime> // 用于将时间转换为可读格式
#include<thread>
// 读取.xyz文件并存储到pcl::PointCloud<pcl::PointXYZ>::Ptr
pcl::PointCloud<pcl::PointXYZ>::Ptr readXYZFile(const std::string& filename) {
// 创建点云对象
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 打开文件
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Error: Could not open file " << filename << std::endl;
return cloud;
}
std::string line;
while (std::getline(file, line)) {
std::istringstream iss(line);
std::string token;
pcl::PointXYZ point;
// 读取X坐标
if (std::getline(iss, token, ';')) {
point.x = std