您现在的位置是:首页 >技术教程 >Ubuntu2204环境下Pcl1.14中GPU/CUDA网站首页技术教程

Ubuntu2204环境下Pcl1.14中GPU/CUDA

朱永博 2025-05-19 00:01:02
简介Ubuntu2204环境下Pcl1.14中GPU/CUDA

pcl_gpu_test.cpp

#include <chrono>
#include <random>
#include <omp.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/surface/poisson.h>
#include <pcl/gpu/features/features.hpp>
#include <pcl/gpu/containers/device_array.h>
#include <pcl/visualization/pcl_visualizer.h>
pcl::PointCloud<pcl::PointNormal>::Ptr generateBallCloud(int numPoints,float radius){
    pcl::PointCloud<pcl::PointNormal>::Ptr cloud(new pcl::PointCloud<pcl::PointNormal>);
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(-1.0,1.0);
    for(int i = 0; i < numPoints; ++i){
        float theta = 2 * M_PI * dis(gen);
        float phi = acos(dis(gen));
        float r = radius * std::cbrt(dis(gen) + 1);
        pcl::PointNormal point;
        point.x = r * sin(phi) * cos(theta);
        point.y = r * sin(phi) * sin(theta);
        point.z = r * cos(phi);
        float norm = sqrt(point.x * point.x + point.y * point.y + point.z * point.z);
        point.normal_x = point.x / norm;
        point.normal_y = point.y / norm;
        point.normal_z = point.z / norm;
        cloud->points.push_back(point);
    }
    cloud->width = cloud->points.size();
    cloud->height = 1;
    return cloud;
}
void compute_poisson_mesh(pcl::PointCloud<pcl::PointNormal>::Ptr cloud_normals,pcl::PolygonMesh& mesh,int depth){
    int default_depth = depth;
    int default_solver_divide = 8;
    int default_iso_divide = 8;
    float default_point_weight = 4.0f;
    pcl::search::KdTree<pcl::PointNormal>::Ptr tree(new pcl::search::KdTree<pcl::PointNormal>);
    tree->setInputCloud(cloud_normals);
    pcl::Poisson<pcl::PointNormal> poisson;
    poisson.setSearchMethod(tree);
    poisson.setDepth(default_depth);
    poisson.setSolverDivide(default_solver_divide);
    poisson.setIsoDivide(default_iso_divide);
    poisson.setPointWeight(default_point_weight);
    poisson.setInputCloud(cloud_normals);
    poisson.reconstruct(mesh);
}
int main(){
    const int numPoints = 100000;
    const float radius = 10.0;
    const int depth = 8;
    pcl::PointCloud<pcl::PointNormal>::Ptr cloud_pointnormal = generateBallCloud(numPoints,radius);
    std::cout << "Generated point cloud with " << cloud_pointnormal->size() << " points." << std::endl;
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    for(const auto& pt : cloud_pointnormal->points){
        cloud->points.push_back(pcl::PointXYZ(pt.x,pt.y,pt.z));
    }
    pcl::PolygonMesh mesh;
    compute_poisson_mesh(cloud_pointnormal,mesh,6);
    pcl::visualization::PCLVisualizer viewer = pcl::visualization::PCLVisualizer("Normal Viewer");
    viewer.addPolygonMesh(mesh,"mesh");
    viewer.addPointCloudNormals<pcl::PointNormal>(cloud_pointnormal,10,0.05,"cloud_pointnormal");
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH,10,"cloud_pointnormal");
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,1,0,0,"cloud_pointnormal");
    viewer.spin();
    auto start_time_gpu = omp_get_wtime();
    pcl::gpu::DeviceArray<pcl::PointXYZ> cloud_device;
    cloud_device.upload(cloud->points);
    pcl::gpu::NormalEstimation ne_gpu;
    ne_gpu.setInputCloud(cloud_device);
    const float search_radius = radius * 0.03f;
    const int max_neighbors = 30;
    ne_gpu.setRadiusSearch(search_radius,max_neighbors);
    pcl::gpu::DeviceArray<pcl::PointXYZ> normals_device;
    ne_gpu.compute(normals_device);
    std::vector<pcl::PointXYZ> normals_host;
    normals_device.download(normals_host);
    std::cout << "gpu time: " << omp_get_wtime() - start_time_gpu << std::endl;
    auto start_time_cpu = omp_get_wtime();
    pcl::PointCloud<pcl::Normal>::Ptr cloud_normal_out(new pcl::PointCloud<pcl::Normal>);
    pcl::NormalEstimation<pcl::PointXYZ,pcl::Normal> ne_cpu;
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
    ne_cpu.setSearchMethod(tree);
    ne_cpu.setInputCloud(cloud);
    ne_cpu.setKSearch(20);
    ne_cpu.compute(*cloud_normal_out);
    std::cout << "cpu time: " << omp_get_wtime() - start_time_cpu << std::endl;
    pcl::PointCloud<pcl::PointNormal>::Ptr cloud_normal_out_gpu(new pcl::PointCloud<pcl::PointNormal>);
    cloud_normal_out_gpu->resize(normals_host.size());
    for(size_t i = 0; i < normals_host.size(); ++i){
        cloud_normal_out_gpu->points[i].x = cloud->points[i].x;
        cloud_normal_out_gpu->points[i].y = cloud->points[i].y;
        cloud_normal_out_gpu->points[i].z = cloud->points[i].z;
        cloud_normal_out_gpu->points[i].normal_x = normals_host[i].x;
        cloud_normal_out_gpu->points[i].normal_y = normals_host[i].y;
        cloud_normal_out_gpu->points[i].normal_z = normals_host[i].z;
        cloud_normal_out_gpu->points[i].curvature = 0;
    }
    pcl::visualization::PCLVisualizer viewer2 = pcl::visualization::PCLVisualizer("Normal Viewer");
    viewer2.addPolygonMesh(mesh,"mesh");
    viewer2.addPointCloudNormals<pcl::PointNormal>(cloud_normal_out_gpu,10,0.05,"cloud_normal_out_gpu");
    viewer2.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH,10,"cloud_normal_out_gpu");
    viewer2.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR,1,0,0,"cloud_normal_out_gpu");
    viewer2.spin();
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(pcl_gpu_test)
find_package(PCL 1.14 REQUIRED)
find_package(VTK REQUIRED)
find_package(CUDA REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable(pcl_gpu_test pcl_gpu_test.cpp)
target_link_libraries(pcl_gpu_test ${PCL_LIBRARIES} ${VYK_LIBRARIES})
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。