噪声过滤,形态学噪声滤除器
墨初 知识笔记 33阅读
_of_point] false;return;}if(z < rgd_params.bounding_box_min_Z || z > rgd_params.bounding_box_max_Z){d_markers_out[index_of_point] false;return;}int ix(x - rgd_params.bounding_box_min_X)/rgd_params.resolution_X;//通过该点的坐标以及格网参数计算该点所在的格网桶的索引int iy(y - rgd_params.bounding_box_min_Y)/rgd_params.resolution_Y;int iz(z - rgd_params.bounding_box_min_Z)/rgd_params.resolution_Z;int index_bucket ix*rgd_params.number_of_buckets_Y *rgd_params.number_of_buckets_Z iy * rgd_params.number_of_buckets_Z iz;//计算该点所在的格网桶的索引if(index_bucket > 0 && index_bucket < rgd_params.number_of_buckets)//如果该点所在的格网桶索引合法,rgd_params三维空间的参数包括空间的大小和每个桶的大小。{int sx, sy, sz, stx, sty, stz;//当前点所在的桶的邻居桶的位置用于遍历周围桶中的点if(ix 0)sx 0; else sx -1;if(iy 0)sy 0; else sy -1;if(iz 0)sz 0; else sz - 1;if(ix rgd_params.number_of_buckets_X - 1)stx 1; else stx 2;if(iy rgd_params.number_of_buckets_Y - 1)sty 1; else sty 2;if(iz rgd_params.number_of_buckets_Z - 1)stz 1; else stz 2;int index_next_bucket;//当前桶的邻居桶的索引int iter;int number_of_points_in_bucket;int l_begin;int l_end;for(int i sx; i < stx; i){for(int j sy; j < sty; j){for(int k sz; k < stz; k)//首先判断当前点所在的桶是否存在即索引是否在合法范围内{index_next_bucket index_bucket i * rgd_params.number_of_buckets_Y * rgd_params.number_of_buckets_Z j * rgd_params.number_of_buckets_Z k;if(index_next_bucket > 0 && index_next_bucket < rgd_params.number_of_buckets)//如果当前点所在的桶存在{number_of_points_in_bucket d_buckets[index_next_bucket].number_of_points;if(number_of_points_in_bucket < 0)continue;int max_number_considered_in_bucket;if(index_next_bucket index_bucket){max_number_considered_in_bucket max_number_considered_in_INNER_bucket;}else{max_number_considered_in_bucket max_number_considered_in_OUTER_bucket;}if(max_number_considered_in_bucket < 0)continue;if(max_number_considered_in_bucket > number_of_points_in_bucket){iter1;}else{iter number_of_points_in_bucket / max_number_considered_in_bucket;if(iter < 0)iter 1;}l_begin d_buckets[index_next_bucket].index_begin;//计算当前桶中的点的索引范围l_end d_buckets[index_next_bucket].index_end;for(int l l_begin; l < l_end; l iter){if(l > 0 && l < number_of_points){int hashed_index_of_point d_hashTable[l].index_of_point;float nn_x d_point_cloud[hashed_index_of_point].x;float nn_y d_point_cloud[hashed_index_of_point].y;float nn_z d_point_cloud[hashed_index_of_point].z;float dist (x - nn_x) * (x - nn_x) (y - nn_y) * (y - nn_y) (z - nn_z) * (z - nn_z);//计算当前点与周围点的距离if(dist < search_radius * search_radius)//计算当前点所在桶的邻居桶的位置遍历周围桶中的点{number_of_found_points_in_search_sphere_threshold;//如果距离小于阈值则计数器加1}}}}}}}}if(number_of_found_points_in_search_sphere_threshold > number_of_points_in_search_sphere_threshold 1)//如果计数器大于阈值则保留该点{d_markers_out[index_of_point] true;//将该点的标记设为true}else{d_markers_out[index_of_point] false;}}}
然后下面就是主调用函数该函数的主要流程是首先调用 kernel_setAllPointsToRemove
函数将所有点标记为噪声这个函数可以在第五章找到。然后调用 kernel_markPointsToRemain
函数使用哈希表和桶进行空间搜索标记不是噪声的点。并在每次 CUDA 调用之后检查是否有错误并在需要时返回错误码。

cudaError_t cudaRemoveNoise(int threads,pcl::PointXYZ *d_point_cloud,int number_of_points,hashElement *d_hashTable,bucket *d_buckets,gridParameters rgd_params,float search_radius,int number_of_points_in_search_sphere_threshold,int max_number_considered_in_INNER_bucket,int max_number_considered_in_OUTER_bucket,bool *d_markers_out){cudaError_t err cudaGetLastError();kernel_setAllPointsToRemove<<<number_of_points/threads1,threads>>>(number_of_points, d_markers_out);err cudaDeviceSynchronize();if(err ! ::cudaSuccess)return err;kernel_markPointsToRemain<<<number_of_points/threads1,threads>>> (d_point_cloud,number_of_points,d_hashTable,d_buckets,rgd_params,search_radius,number_of_points_in_search_sphere_threshold,max_number_considered_in_INNER_bucket,max_number_considered_in_OUTER_bucket,d_markers_out);err cudaDeviceSynchronize();return err;}
3. Thrust代码完成加速 下面这段代码主要是使用Thrust库实现了点云去噪的功能具体实现如下
定义了一个名为PointXYZI的结构体结构体包含了x、y、z和intensity四个成员变量。定义了一个名为squared_euclidean_distance
的结构体这个结构体继承自thrust::binary_function<PointXYZI, PointXYZI, float>
表示计算两个PointXYZI点之间的距离平方即 ( d x ) 2 ( d y ) 2 ( d z ) 2 (dx)^2(dy)^2(dz)^2 (dx)2(dy)2(dz)2。定义了一个名为is_noise
的结构体这个结构体继承自thrust::unary_function<PointXYZI, bool>
表示检查一个PointXYZI点是否为噪点。定义了一个名为removeNoise
的函数这个函数的输入为一组点云数据以及去噪所需的一些参数输出为去除噪点后的点云数据。函数removeNoise
内部首先创建了一个名为sorted_indices
的device_vector<int>
并用thrust::sequence
函数对其进行初始化该函数返回一个按顺序填充的序列。然后使用thrust::sort_by_key对原始点云数据按照z坐标排序并将排序后的点云数据存储在名为points的device_vector<PointXYZI>
中排序后的点云索引存储在名为idxs的device_vector<int>
中。接着使用thrust::remove_if
函数移除噪点其中is_noise
结构体的对象被作为第二个参数传递给thrust::remove_if
函数它表示判断一个PointXYZI点是否为噪点的条件。移除后的点云数据存储在名为new_end
的迭代器中。最后使用thrust::erase
函数删除新点云数据中的已经移除的噪点。返回最终的点云数据points。 …详情请参照居
标签: