#include <iostream> //标准输入输出头文件
#include <pcl/point_types.h> //点类型定义头文件
#include <pcl/io/ply_io.h> //I/O操作头文件
#include <pcl/io/pcd_io.h> //I/O操作头文件
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_line.h>
#include <ctime>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/registration/icp.h> //ICP配准类相关头文件
#include <Eigen/src/Core/util/Macros.h>
#include <pcl/pcl_macros.h>
#include <pcl/common/transforms.h>
#include <Eigen/Geometry>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d_omp.h>
#include <boost/thread/thread.hpp>
#include <algorithm> // 包含std::sort
#include <pcl/surface/mls.h>
#include <vector>
#include <pcl/io/obj_io.h>
#include <pcl/filters/convolution_3d.h>
#include <pcl/filters/median_filter.h>
#include <pcl/filters/random_sample.h>
#include <pcl/point_cloud.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/fpfh.h>
#include <pcl/registration/ia_ransac.h>
#include <thread>
#include <pcl/registration/ndt.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/common/centroid.h>
#include <pcl/common/common.h>
#include <pcl/sample_consensus/sac_model_circle.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/surface/convex_hull.h>
#include <cmath>
#include <memory>
#include < pcl/sample_consensus/sac_model_circle3d.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/common/geometry.h>
#include <pcl/features/boundary.h> // 边界估计头文件
#include <pcl/filters/project_inliers.h>
#include <Eigen/Dense>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/crop_box.h>
#include <pcl/search/kdtree.h>
#include <string>
#include <cstdlib>
#include <pcl/registration/gicp.h>
#include <pcl/console/time.h>
#include <pcl/registration/icp_nl.h> // 注意:这里包含的是非线性ICP(使用LM)的头文件
#include <pcl/filters/approximate_voxel_grid.h>
#include <omp.h>
#include <chrono>
#include <pcl/octree/octree_search.h>
#include <pcl/features/impl/normal_3d_omp.hpp>
#include "fast_gicp.hpp"
#include <open3d/Open3D.h>
#include <iomanip> // 添加这个头文件用于 std::setprecision
#include <random> // 添加这个头文件用于随机数生成
using namespace std;
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
// /********************用于点面ICP配准****************////////////
//void cloudNormal(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointNormal>::Ptr& cloud_normals)
//{
// pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;//OMP加速
// pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
// pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
// n.setNumberOfThreads(8);//含义:设置OpenMP使用的线程数。这里设置为8个线程,用于加速法线估计计算。通常设置为可用CPU核心数。注意:如果系统不支持OpenMP或核心数不足,实际线程数可能受限。
// n.setInputCloud(cloud);
// n.setSearchMethod(tree);
// n.setKSearch(10); //设置法线估计时使用的最近邻点数量(k近邻搜索)。此方法指定每个点的法线基于其最近的k个邻居计算得到。
// n.compute(*normals);
// pcl::concatenateFields(*cloud, *normals, *cloud_normals); // 拼接点云及法向量
//}
// /********************创建带文字标签的自定义坐标轴****************////////////
void addCoordinateSystemWithLabels(
pcl::visualization::PCLVisualizer::Ptr viewer,
float axis_length, // 坐标轴长度
float line_width, // 线宽(粗细)
float text_scale, // 文字大小
const std::string& id_prefix = "axis_",
float origin_x = 0.0f,
float origin_y = 0.0f,
float origin_z = 0.0f
) {
// X轴(红色)
pcl::PointXYZ x_start(origin_x, origin_y, origin_z);
pcl::PointXYZ x_end(origin_x + axis_length, origin_y, origin_z);
viewer->addLine(x_start, x_end, 1.0, 0.0, 0.0, id_prefix + "x_line");
viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, line_width, id_prefix + "x_line");
// 添加X标签
viewer->addText3D("X", x_end, text_scale, 1.0, 0.0, 0.0, id_prefix + "x_label");
// Y轴(绿色)
pcl::PointXYZ y_start(origin_x, origin_y, origin_z);
pcl::PointXYZ y_end(origin_x, origin_y + axis_length, origin_z);
viewer->addLine(y_start, y_end, 0.0, 1.0, 0.0, id_prefix + "y_line");
viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, line_width, id_prefix + "y_line");
// 添加Y标签
viewer->addText3D("Y", y_end, text_scale, 0.0, 1.0, 0.0, id_prefix + "y_label");
// Z轴(蓝色)
pcl::PointXYZ z_start(origin_x, origin_y, origin_z);
pcl::PointXYZ z_end(origin_x, origin_y, origin_z + axis_length);
viewer->addLine(z_start, z_end, 0.0, 0.0, 1.0, id_prefix + "z_line");
viewer->setShapeRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, line_width, id_prefix + "z_line");
// 添加Z标签
viewer->addText3D("Z", z_end, text_scale, 0.0, 0.0, 1.0, id_prefix + "z_label");
}
// 提前声明估算点云平均点间距的辅助函数
double estimatePointSpacing(const std::shared_ptr<open3d::geometry::PointCloud>& cloud, int num_samples = 1000);
// 半径滤波函数
void radiusFilterDemo(const std::string& source_file, const std::string& target_file) {
std::cout << "=== Open3D 半径滤波性能测试 ===" << std::endl;
// 参数设置
const int min_neighbors = 40; // 最小邻居数
const double radius = 1.2; // 搜索半径
// 处理源点云
std::cout << "\n--- 处理源点云: " << source_file << " ---" << std::endl;
auto start_load_source = std::chrono::high_resolution_clock::now();
auto source_cloud = open3d::io::CreatePointCloudFromFile(source_file);
auto end_load_source = std::chrono::high_resolution_clock::now();
if (!source_cloud || source_cloud->points_.empty()) {
std::cerr << "错误: 无法读取源点云文件 " << source_file << std::endl;
return;
}
auto load_duration_source = std::chrono::duration_cast<std::chrono::milliseconds>(
end_load_source - start_load_source);
std::cout << "加载时间: " << load_duration_source.count() << " ms" << std::endl;
std::cout << "滤波前点数: " << source_cloud->points_.size() << std::endl;
// 执行半径滤波
auto start_filter_source = std::chrono::high_resolution_clock::now();
std::shared_ptr<open3d::geometry::PointCloud> filtered_source;
std::vector<size_t> inlier_indices_source;
std::tie(filtered_source, inlier_indices_source) = source_cloud->RemoveRadiusOutliers(
min_neighbors, radius);
auto end_filter_source = std::chrono::high_resolution_clock::now();
auto filter_duration_source = std::chrono::duration_cast<std::chrono::milliseconds>(
end_filter_source - start_filter_source);
std::cout << "滤波时间: " << filter_duration_source.count() << " ms" << std::endl;
std::cout << "滤波后点数: " << filtered_source->points_.size() << std::endl;
double retention_rate_source = (filtered_source->points_.size() * 100.0 / source_cloud->points_.size());
std::cout << "保留比例: " << std::fixed << std::setprecision(2)
<< retention_rate_source << "%" << std::endl;
// 处理目标点云
std::cout << "\n--- 处理目标点云: " << target_file << " ---" << std::endl;
auto start_load_target = std::chrono::high_resolution_clock::now();
auto target_cloud = open3d::io::CreatePointCloudFromFile(target_file);
auto end_load_target = std::chrono::high_resolution_clock::now();
if (!target_cloud || target_cloud->points_.empty()) {
std::cerr << "错误: 无法读取目标点云文件 " << target_file << std::endl;
return;
}
auto load_duration_target = std::chrono::duration_cast<std::chrono::milliseconds>(
end_load_target - start_load_target);
std::cout << "加载时间: " << load_duration_target.count() << " ms" << std::endl;
std::cout << "滤波前点数: " << target_cloud->points_.size() << std::endl;
// 执行半径滤波
auto start_filter_target = std::chrono::high_resolution_clock::now();
std::shared_ptr<open3d::geometry::PointCloud> filtered_target;
std::vector<size_t> inlier_indices_target;
std::tie(filtered_target, inlier_indices_target) = target_cloud->RemoveRadiusOutliers(
min_neighbors, radius);
auto end_filter_target = std::chrono::high_resolution_clock::now();
auto filter_duration_target = std::chrono::duration_cast<std::chrono::milliseconds>(
end_filter_target - start_filter_target);
std::cout << "滤波时间: " << filter_duration_target.count() << " ms" << std::endl;
std::cout << "滤波后点数: " << filtered_target->points_.size() << std::endl;
double retention_rate_target = (filtered_target->points_.size() * 100.0 / target_cloud->points_.size());
std::cout << "保留比例: " << std::fixed << std::setprecision(2)
<< retention_rate_target << "%" << std::endl;
// 保存滤波后的点云(可选)
std::cout << "\n--- 保存结果 ---" << std::endl;
if (open3d::io::WritePointCloud("filtered_source.pcd", *filtered_source)) {
std::cout << "源点云滤波结果保存为: filtered_source.pcd" << std::endl;
}
if (open3d::io::WritePointCloud("filtered_target.pcd", *filtered_target)) {
std::cout << "目标点云滤波结果保存为: filtered_target.pcd" << std::endl;
}
// 汇总统计
std::cout << "\n=== 性能汇总 ===" << std::endl;
std::cout << "源点云 - 加载: " << load_duration_source.count() << " ms, "
<< "滤波: " << filter_duration_source.count() << " ms, "
<< "总处理: " << (load_duration_source.count() + filter_duration_source.count()) << " ms" << std::endl;
std::cout << "目标点云 - 加载: " << load_duration_target.count() << " ms, "
<< "滤波: " << filter_duration_target.count() << " ms, "
<< "总处理: " << (load_duration_target.count() + filter_duration_target.count()) << " ms" << std::endl;
}
// 估算点云平均点间距的辅助函数
double estimatePointSpacing(const std::shared_ptr<open3d::geometry::PointCloud>& cloud, int num_samples) {
if (cloud->points_.size() < 2) return 0.01;
open3d::geometry::KDTreeFlann kdtree(*cloud);
double total_distance = 0.0;
int count = 0;
// 随机采样计算平均最近邻距离
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, static_cast<int>(cloud->points_.size()) - 1);
for (int i = 0; i < std::min(num_samples, static_cast<int>(cloud->points_.size())); ++i) {
int idx = dis(gen);
std::vector<int> indices;
std::vector<double> distances;
if (kdtree.SearchKNN(cloud->points_[idx], 2, indices, distances) == 2) {
total_distance += std::sqrt(distances[1]); // 第一个是自身
count++;
}
}
return count > 0 ? total_distance / count : 0.01;
}
// 自适应参数版本(可选)
void adaptiveRadiusFilterDemo(const std::string& source_file, const std::string& target_file) {
std::cout << "\n=== 自适应参数半径滤波 ===" << std::endl;
// 处理源点云
auto source_cloud = open3d::io::CreatePointCloudFromFile(source_file);
if (!source_cloud || source_cloud->points_.empty()) return;
// 估算点云密度并自适应参数
double avg_spacing = estimatePointSpacing(source_cloud);
double adaptive_radius = avg_spacing * 4.0; // 半径为平均点间距的4倍
int adaptive_min_neighbors = static_cast<int>(15 * (0.01 / avg_spacing)); // 基于密度调整
std::cout << "估算点间距: " << avg_spacing << " m" << std::endl;
std::cout << "自适应参数 - 半径: " << adaptive_radius << ", 最小邻居: " << adaptive_min_neighbors << std::endl;
auto start_time = std::chrono::high_resolution_clock::now();
auto filtered_result = source_cloud->RemoveRadiusOutliers(adaptive_min_neighbors, adaptive_radius);
auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
auto filtered_source = std::get<0>(filtered_result);
std::cout << "自适应滤波时间: " << duration.count() << " ms" << std::endl;
std::cout << "滤波前: " << source_cloud->points_.size() << " 点" << std::endl;
std::cout << "滤波后: " << filtered_source->points_.size() << " 点" << std::endl;
}
int main(int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud3(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud4(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud5(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud6(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered1(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered2(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered3(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered4(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered5(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered6(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered7(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered8(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered9(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered10(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered11(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered12(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered13(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered14(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered15(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered16(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered17(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered18(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered19(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered20(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered21(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered22(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered23(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered24(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered25(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered26(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered27(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered28(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered29(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr clouda(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudb(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudc(new pcl::PointCloud<pcl::PointXYZ>);
//创建两个pcl::PointCloud<pcl::PointXYZ>共享指针,并初始化它们
pcl::PointCloud<pcl::PointXYZ>::Ptr clouda_left(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudb_left(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudb_right(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr clouda_right(new pcl::PointCloud<pcl::PointXYZ>);
//if (pcl::io::loadPCDFile("point_cloud_20251119.pcd", *clouda) < 0)//读取标准点云
//{
// std::cout << "error";
//}
//std::cout << "点云数量: " << clouda->points.size() << std::endl;
clock_t start34 = clock();
if (pcl::io::loadPCDFile("point_cloud_2025119_20_10.pcd", *cloudb) < 0) //读取采集点云
{
std::cout << "error";
}
std::cout << "点云数量: " << cloudb->points.size() << std::endl;
clock_t end34 = clock(); // 记录程序运行到此结束时间
double cpu_time_used34 = static_cast<double>(end34 - start34) / CLOCKS_PER_SEC; //CLOCKS_PER_SEC将结果转为以秒为单位
std::cout << "PCL读取点云文件时间: " << cpu_time_used34 << " s\n"; //显示此段程序运行时间
clock_t start33 = clock();
pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror1; // 半径滤波
ror1.setInputCloud(cloudb); //输入点云
ror1.setRadiusSearch(1.2f); // 设置搜索半径
ror1.setMinNeighborsInRadius(40); // 设置半径范围内的最少点数阈值
ror1.filter(*cloudb); //保存滤波结果
std::cout << "3号相机采集--分割的ZDB点云数量--cloudb_left去除离散点后 " << cloudb->points.size() << std::endl;
clock_t end33 = clock(); // 记录程序运行到此结束时间
double cpu_time_used33 = static_cast<double>(end33 - start33) / CLOCKS_PER_SEC; //CLOCKS_PER_SEC将结果转为以秒为单位
std::cout << "PCL采集离散点滤波时间: " << cpu_time_used33 << " s\n"; //显示此段程序运行时间
// 设置点云文件路径
std::string source_file = "point_cloud_2025119_20_10.pcd";
std::string target_file = "point_cloud_2025119_20_10.pcd";
// 执行标准半径滤波
radiusFilterDemo(source_file, target_file);
// 可选:执行自适应参数版本
// adaptiveRadiusFilterDemo(source_file, target_file);
std::cout << "\n=== 处理完成 ===" << std::endl;
if (pcl::io::loadPCDFile("filtered_source.pcd", *cloudc) < 0) //读取采集点云
{
std::cout << "error";
}
std::cout << "点云数量: " << cloudc->points.size() << std::endl;
////................单个窗口显示两个图像.............//
// 1. 创建PCLVisualizer对象
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setBackgroundColor(0, 0, 0); // 设置背景颜色为黑色
// 添加带文字标签的坐标轴
//参数:viewer, 轴长度, 线宽, 文字大小, 标识前缀, 原点坐标
addCoordinateSystemWithLabels(viewer,800.0, 2.0, 50.0, "main_axis_", 0, 0, 0);
//pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> clouda_color(clouda_left, 0, 255, 0); // 设置为绿色
//viewer->addPointCloud<pcl::PointXYZ>(clouda_left, clouda_color, "clouda");
//viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "clouda"); // 设置点大小
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> clouda_color1(cloudc, 0, 255, 0); // 设置为绿色
viewer->addPointCloud<pcl::PointXYZ>(cloudc, clouda_color1, "cloudb_left");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "clouda"); // 设置点大小
// 5. 将第二个点云添加到可视化窗口并设置颜色(红色)
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud2_color(cloudb, 255, 0, 255); // 设置为粉色
viewer->addPointCloud<pcl::PointXYZ>(cloudb, cloud2_color, "cloud2");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "clouda"); // 设置点大小
//pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud3_color(cloudb_right, 255, 0, 255); // 设置为红色
//viewer->addPointCloud<pcl::PointXYZ>(cloudb_right, cloud3_color, "cloud3");
//viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "cloud3"); // 设置点大小
// 6. 启动可视化
while (!viewer->wasStopped())
{
viewer->spinOnce(100); // 让可视化窗口刷新
}
上述程序中,实现了PCL的半径滤波和Open3D的半径滤波时间对比,但是存在一个问题,原来程序中没有Open3D的半径滤波,PCL读取文件时间约为0.5s,后来添加了Open3D的半径滤波,导致PCL读取文件时间变为5s左右,时间明显变长,原因?开发环境,VS2022 PCL1.14.1版 Open3D 0.19版
最新发布