c++实现基于kd树的3d点云半径滤波 不使用pcl库

c++实现基于kd树的3d点云半径滤波 不使用pcl库

可优化的地方挺多的 是不使用kd树的运算时间的大约四分之一

  1 #include <iostream>
  2 #include <fstream>
  3 #include <vector>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <chrono>
  7  
  8 struct Point3D
  9 {
 10     float x, y, z;
 11 };
 12  
 13 struct TreeNode
 14 {
 15     Point3D point;
 16     int split_dim;
 17     TreeNode* left_child;
 18     TreeNode* right_child;
 19     TreeNode(const Point3D& p) : point(p), split_dim(0), left_child(nullptr), right_child(nullptr) {}
 20 };
 21  
 22 bool compare_x(const Point3D& p1, const Point3D& p2)
 23 {
 24     return p1.x < p2.x;
 25 }
 26  
 27 bool compare_y(const Point3D& p1, const Point3D& p2)
 28 {
 29     return p1.y < p2.y;
 30 }
 31  
 32 bool compare_z(const Point3D& p1, const Point3D& p2)
 33 {
 34     return p1.z < p2.z;
 35 }
 36  
 37 float distance(const Point3D& p1, const Point3D& p2)
 38 {
 39     return std::sqrt(std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2) + std::pow(p1.z - p2.z, 2));
 40 }
 41  
 42 void build_kd_tree(TreeNode*& node, std::vector<Point3D>& pointclouds, int start_index, int end_index, int depth)
 43 {
 44     if (start_index > end_index) {
 45         node = nullptr;
 46         return;
 47     }
 48     int middle_index = start_index + (end_index - start_index) / 2;
 49     if (depth % 3 == 0) {
 50         std::sort(pointclouds.begin() + start_index, pointclouds.begin() + end_index + 1, compare_x);
 51     }
 52     else if (depth % 3 == 1) {
 53         std::sort(pointclouds.begin() + start_index, pointclouds.begin() + end_index + 1, compare_y);
 54     }
 55     else {
 56         std::sort(pointclouds.begin() + start_index, pointclouds.begin() + end_index + 1, compare_z);
 57     }
 58     node = new TreeNode(pointclouds[middle_index]);
 59     node->split_dim = depth % 3;
 60     build_kd_tree(node->left_child, pointclouds, start_index, middle_index - 1, depth + 1);
 61     build_kd_tree(node->right_child, pointclouds, middle_index + 1, end_index, depth + 1);
 62 }
 63  
 64 void search_knn(TreeNode* node, const Point3D& p, float radius, int k, std::vector<int>& indices, std::vector<float>& distances)
 65 {
 66     if (node == nullptr) {
 67         return;
 68     }
 69     float dist = distance(node->point, p);
 70     if (dist <= radius) {
 71         indices.push_back(indices.size());
 72         distances.push_back(dist);
 73     }
 74     if (indices.size() < k || dist < distances[indices.size() - 1]) {
 75         if (node->split_dim == 0) {
 76             if (p.x < node->point.x) {
 77                 search_knn(node->left_child, p, radius, k, indices, distances);
 78                 search_knn(node->right_child, p, radius, k, indices, distances);
 79             }
 80             else {
 81                 search_knn(node->right_child, p, radius, k, indices, distances);
 82                 search_knn(node->left_child, p, radius, k, indices, distances);
 83             }
 84         }
 85         else if (node->split_dim == 1) {
 86             if (p.y < node->point.y) {
 87                 search_knn(node->left_child, p, radius, k, indices, distances);
 88                 search_knn(node->right_child, p, radius, k, indices, distances);
 89             }
 90             else {
 91                 search_knn(node->right_child, p, radius, k, indices, distances);
 92                 search_knn(node->left_child, p, radius, k, indices, distances);
 93             }
 94         }
 95         else {
 96             if (p.z < node->point.z) {
 97                 search_knn(node->left_child, p, radius, k, indices, distances);
 98                 search_knn(node->right_child, p, radius, k, indices, distances);
 99             }
100             else {
101                 search_knn(node->right_child, p, radius, k, indices, distances);
102                 search_knn(node->left_child, p, radius, k, indices, distances);
103             }
104         }
105  
106     }
107 }
108  
109 int main()
110 {
111     // 获取当前系统时间点
112     auto start_time = std::chrono::high_resolution_clock::now();
113  
114     float radius = 0.25f;
115     int k = 10;
116  
117     // 读取点云数据
118     std::vector<Point3D> pointclouds;
119     std::ifstream infile(".txt");
120     if (!infile) {
121         std::cerr << "Failed to open file: filtered_points5.txt" << std::endl;
122         return -1;
123     }
124     Point3D p;
125     while (infile >> p.x >> p.y >> p.z) {
126         pointclouds.emplace_back(p);
127     }
128  
129     // 构建kd树
130     TreeNode* root = nullptr;
131     build_kd_tree(root, pointclouds, 0, pointclouds.size() - 1, 0);
132  
133     // 搜索邻域点
134     std::vector<Point3D> filtered_cloud;
135     for (int i = 0; i < pointclouds.size(); i++) {
136         std::vector<int> indices;
137         std::vector<float> distances;
138         search_knn(root, pointclouds[i], radius, k, indices, distances);
139         if (indices.size() >= k) {
140             filtered_cloud.emplace_back(pointclouds[i]);
141         }
142     }
143  
144     std::ofstream outFile(".txt");
145     for (int i = 0; i < filtered_cloud.size(); ++i)
146     {
147         outFile << filtered_cloud[i].x << " " << filtered_cloud[i].y << " " << filtered_cloud[i].z << std::endl;
148     }
149  
150     outFile.close();
151  
152     auto end_time = std::chrono::high_resolution_clock::now();
153     auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
154     std::cout << "Execution time: " << duration.count() << " microseconds" << std::endl;
155  
156     return 0;
157 }

 

posted @ 2024-07-26 22:31  量子与太极  阅读(7)  评论(0)    收藏  举报