把涉及PCL库的计算算法提取成不使用PCL库的代码,需要自己实现以下几个函数:

  1. rand()函数用于生成随机数,可以使用C++标准库中的std::rand()函数代替。
  2. 欧几里得距离计算函数可以自己实现,代码如下:
float euclideanDistance(const pcl::PointXYZ& p1, const pcl::PointXYZ& p2)
{
    float dx = p1.x - p2.x;
    float dy = p1.y - p2.y;
    float dz = p1.z - p2.z;
    return std::sqrt(dx*dx + dy*dy + dz*dz);
}
  1. 半径内近邻搜索可以使用kd-tree实现,代码如下:
class KDNode
{
public:
    pcl::PointXYZ point;
    int index;
    KDNode* left;
    KDNode* right;

    KDNode(const pcl::PointXYZ& p, int i) : point(p), index(i), left(nullptr), right(nullptr) {}
};

class KDTree
{
public:
    KDTree(const pcl::PointCloud<pcl::PointXYZ>& cloud)
    {
        std::vector<int> indices(cloud.size());
        std::iota(indices.begin(), indices.end(), 0);
        root = buildTree(cloud, indices, 0, cloud.size()-1, 0);
    }

    std::vector<int> radiusSearch(const pcl::PointXYZ& searchPoint, float radius)
    {
        std::vector<int> indices;
        radiusSearch(root, searchPoint, radius, indices);
        return indices;
    }

private:
    KDNode* root;

    float getAxisValue(const pcl::PointXYZ& p, int axis)
    {
        switch (axis)
        {
        case 0: return p.x;
        case 1: return p.y;
        case 2: return p.z;
        }
        return 0;
    }

    KDNode* buildTree(const pcl::PointCloud<pcl::PointXYZ>& cloud, const std::vector<int>& indices, int start, int end, int depth)
    {
        if (start > end) return nullptr;
        int mid = (start + end) / 2;
        int axis = depth % 3;
        std::nth_element(indices.begin()+start, indices.begin()+mid, indices.begin()+end+1,
            [&](int i1, int i2) { return getAxisValue(cloud[i1], axis) < getAxisValue(cloud[i2], axis); });
        KDNode* node = new KDNode(cloud[indices[mid]], indices[mid]);
        node->left = buildTree(cloud, indices, start, mid-1, depth+1);
        node->right = buildTree(cloud, indices, mid+1, end, depth+1);
        return node;
    }

    void radiusSearch(KDNode* node, const pcl::PointXYZ& searchPoint, float radius, std::vector<int>& indices)
    {
        if (node == nullptr) return;
        float dist = euclideanDistance(searchPoint, node->point);
        if (dist < radius)
        {
            indices.push_back(node->index);
        }
        int axis = indices.size() % 3;
        if (searchPoint.data[axis] - radius < node->point.data[axis])
        {
            radiusSearch(node->left, searchPoint, radius, indices);
        }
        if (searchPoint.data[axis] + radius > node->point.data[axis])
        {
            radiusSearch(node->right, searchPoint, radius, indices);
        }
    }
};

完整代码如下:

#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>

using namespace std;

float euclideanDistance(const pcl::PointXYZ& p1, const pcl::PointXYZ& p2)
{
    float dx = p1.x - p2.x;
    float dy = p1.y - p2.y;
    float dz = p1.z - p2.z;
    return std::sqrt(dx*dx + dy*dy + dz*dz);
}

class KDNode
{
public:
    pcl::PointXYZ point;
    int index;
    KDNode* left;
    KDNode* right;

    KDNode(const pcl::PointXYZ& p, int i) : point(p), index(i), left(nullptr), right(nullptr) {}
};

class KDTree
{
public:
    KDTree(const pcl::PointCloud<pcl::PointXYZ>& cloud)
    {
        std::vector<int> indices(cloud.size());
        std::iota(indices.begin(), indices.end(), 0);
        root = buildTree(cloud, indices, 0, cloud.size()-1, 0);
    }

    std::vector<int> radiusSearch(const pcl::PointXYZ& searchPoint, float radius)
    {
        std::vector<int> indices;
        radiusSearch(root, searchPoint, radius, indices);
        return indices;
    }

private:
    KDNode* root;

    float getAxisValue(const pcl::PointXYZ& p, int axis)
    {
        switch (axis)
        {
        case 0: return p.x;
        case 1: return p.y;
        case 2: return p.z;
        }
        return 0;
    }

    KDNode* buildTree(const pcl::PointCloud<pcl::PointXYZ>& cloud, const std::vector<int>& indices, int start, int end, int depth)
    {
        if (start > end) return nullptr;
        int mid = (start + end) / 2;
        int axis = depth % 3;
        std::nth_element(indices.begin()+start, indices.begin()+mid, indices.begin()+end+1,
            [&](int i1, int i2) { return getAxisValue(cloud[i1], axis) < getAxisValue(cloud[i2], axis); });
        KDNode* node = new KDNode(cloud[indices[mid]], indices[mid]);
        node->left = buildTree(cloud, indices, start, mid-1, depth+1);
        node->right = buildTree(cloud, indices, mid+1, end, depth+1);
        return node;
    }

    void radiusSearch(KDNode* node, const pcl::PointXYZ& searchPoint, float radius, std::vector<int>& indices)
    {
        if (node == nullptr) return;
        float dist = euclideanDistance(searchPoint, node->point);
        if (dist < radius)
        {
            indices.push_back(node->index);
        }
        int axis = indices.size() % 3;
        if (searchPoint.data[axis] - radius < node->point.data[axis])
        {
            radiusSearch(node->left, searchPoint, radius, indices);
        }
        if (searchPoint.data[axis] + radius > node->point.data[axis])
        {
            radiusSearch(node->right, searchPoint, radius, indices);
        }
    }
};

int main(int argc, char** argv)
{
    srand((unsigned int)time(NULL));
    vector<pcl::PointXYZ> cloudData(1000);
    // 创建点云数据
    for (size_t i = 0; i < cloudData.size(); ++i)
    {
        cloudData[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f);
        cloudData[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);
        cloudData[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);
    }
    vector<vector<int>> octreeData(1000);
    float resolution = 0.1;
    for (size_t i = 0; i < cloudData.size(); ++i)
    {
        int x = std::floor(cloudData[i].x / resolution);
        int y = std::floor(cloudData[i].y / resolution);
        int z = std::floor(cloudData[i].z / resolution);
        int index = x + y*10 + z*100;
        octreeData[index].push_back(i);
    }
    pcl::PointXYZ searchPoint;
    searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f);
    searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f);
    searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);
    //半径内近邻搜索
    vector<int>pointIdxRadiusSearch;
    vector<float>pointRadiusSquaredDistance;
    float radius = 256.0f * rand() / (RAND_MAX + 1.0f);
    cout << "Neighbors within radius search at (" << searchPoint.x
        << " " << searchPoint.y
        << " " << searchPoint.z
        << ") with radius=" << radius << endl;
    KDTree kdTree(cloudData);
    auto indices = kdTree.radiusSearch(searchPoint, radius);
    for (size_t i = 0; i < indices.size(); ++i)
    {
        int index = indices[i];
        cout << "    " << cloudData[index].x
            << " " << cloudData[index].y
            << " " << cloudData[index].z
            << " (squared distance: " << euclideanDistance(searchPoint, cloudData[index]) << ")" << endl;
    }
    // 初始化点云可视化对象
    boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("显示点云"));
    viewer->setBackgroundColor(0, 0, 0);  //设置背景颜色为黑色
    // 对点云着色可视化 (red).
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    cloud->width = cloudData.size();
    cloud->height = 1;
    cloud->points.resize(cloud->width * cloud->height);
    for (size_t i = 0; i < cloud->points.size(); ++i)
    {
        cloud->points[i] = cloudData[i];
    }
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>target_color(cloud, 255, 0, 0);
    viewer->addPointCloud<pcl::PointXYZ>(cloud, target_color, "target cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "target cloud");
    // 等待直到可视化窗口关闭
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(1000));
    }
    return (0);
}
#include-iostreamn#include-vectorn#include-ctimen#include-pclpoint_cloudhn#include-pcloctreeoctreehn#include-boostthreadthreadhppn#include-pclvisualizationpcl_visualizerhnusing-namespace-std;nintnmainint-argc-char-argvnn--------srandunsigned-inttimeN

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

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