点云欧几里德聚类。包括cuda版本
cluster.cpp单个聚类的属性等
ToROSMessage(std_msgs::Header in_ros_header, autoware_msgs::CloudCluster &out_cluster_message)根据聚类的结果,生成autoware_msgs::cloudcluster消息
SetCloud(const pcl::PointCloud
tf::Quaternion quat = tf::createQuaternionFromRPY(0.0, 0.0, rz);
tf::quaternionTFToMsg(quat, bounding_box_.pose.orientation);
如果点云的数量大于3,则进行pca主成分析,计算特征向量和特征值,分别保存在eigen_vectors_ 和eigen_values中,点云保存在pointcloud_中。
GetFpfhDescriptor(const unsigned int& in_ompnum_threads,const double& in_normal_search_radius, const double& in_fpfh_search_radius) 获取快速点特征直方图描述子,即提取当前聚类点云的特征。首先用KDtree和normalestimationOPM计算点云中每个点的法向量,搜索点附近阈值范围内的点计算法向量。调用FPFHEstimaionOMP计算每个点的直方图,然后将每个点对应位置的直方图合并,每个直方图是一个33个值组成的向量,即将向量累加,并找出33个值的最大和最小。(貌似每一个点都要标准化一次,不知道时为啥,看不懂,留待以后解答)
lidar_euclidean_cluster_detect.cpp
findTransform() 查找对应的坐标变换,返回transform
transformPoint() 根据transform将点云点变换到对应坐标系下
checkPointInGrid(const grid_map::GridMap &in_grid_map, const cv::Mat &in_grid_image,const geometry_msgs::Point &in_point) 检查点是否在gridmap内部
publishDetectedObjects(const autoware_msgs::CloudClusterArray &in_clusters)发布聚类集合消息。每一聚类转换为一个autoware_msgs::DetectedObject,再统一放在autoware_msgs::DetectedObejctArray中,发布。
publishCloudClusters(const ros::Publisher *in_publisher, const autoware_msgs::CloudClusterArray &in_clusters, const std::string &in_target_frame, const std_msgs::Header &in_header) 发布聚类目标物消息。末尾是调用publishDetectedObjects()发送消息,1. 如果目标做标系和当前坐标系不一致,则需要转换聚类的各项参数到目标坐标系下,如cloud,min_point,max_point,avg_point等。_transform_listener->lookupTransform(in_target_frame, _velodyne_header.frame_id, ros::Time(), *_transform);pcl_ros::transformPointCloud(in_target_frame, *_transform, i->cloud, cluster_transformed.cloud);需要先查找坐标变换再转换 2. 如果一致,则直接发送,无需转换
publishCentroids(const ros::Publisher *in_publisher, const autoware_msgs::Centroids &in_centroids,const std::string &in_target_frame, const std_msgs::Header &in_header) 发布中心点消息。1. 如果目标做标系和当前坐标系不一致,则需要转换聚类的各项参数到目标坐标系下。_transform_listener->transformPoint(in_target_frame, ros::Time(), centroid_in, in_header.frame_id, centroid_out);2. 如果一致,则直接发送,无需转换
publishcloud() 发布点云消息
publishColorCloud() 发布rgb点云
keepLanePoints(const pcl::PointCloud
clusterAndColorGpu 点云聚类和着色GPU版本,暂不分析,没看。
clusterAndColor () 聚类和着色。将点云投影到xy平面。构建KDTree,tree的输入为投影到xy的点云。使用欧几里得聚类,搜索方法用kdtree。调用cluster的SetCloud计算每个聚类点云的若干属性,如边框,凸边形,最大,最小点等,并为每个聚类的点着色。将所有聚类保存在cluster的向量中。
checkClusterMerge(size_t in_cluster_id, std::vector
mergeClusters(const std::vector
checkAllForMerge() 调用checClusterMerge() 和 mergeClusters() ,将能够融合的目标融合。最后将融合后的目标和独立目标统一存入out_clusters。
segmentByDistance(const pcl::PointCloud
// 0 => 0-15m d=0.5
// 1 => 15-30 d=1
// 2 => 30-45 d=1.6
// 3 => 45-60 d=2.1
// 4 => >60 d=2.6
聚类结果存储到all_clusters中,查看聚类中是否有可以聚合到一起的目标,如果有,则调用checkAllForMerge----> final_clusters。3. 是否使用地图向量,如果使用,则判断所需要的地图层是否存在,若存在建立类似apollo::roi的grid_map,将每个cluster的centroid转换到雷达坐标系下,判断final_clusters中的每个目标的中心点是否再grid_map中( checkPointInGrid()),如果不在则将cluster的valid_cluster_设置为flase。此处valid_cluster_再setCloud()中已经全部设置为true。将final_cluster中所有valid_cluster_=true的目标转化为autoware::cluster ,并存储在autoware::clustersarray中---->in_out_clusters
removeFloor() 调用pcl::SACSegmentation去除地面,将地面点存储在out_onlyfloor_cloud_ptr中,将非地面点存储在out_nofloor_cloud_ptr中。
downsampleCloud() 点云降采样,体素,leaf_size设置为0.2,实际要比这个大才可以,否则依然很密集。
clipCloud() 裁剪点云,上下高度阈值为-1.3~0.5,保留范围内的点。
differenceNormalsSegmentation(const pcl::PointCloud
0.5------->normals_small_scale 2.0------->normals_large_scale
接下来调用pcl::DifferenceOfNormalsEstimation简称DoN算法,计算点大范围和小范围法向量的差异。
1.点云的频率
今天在阅读分割有关的文献时,惊喜的发现,点云和图像一样,有可能也存在频率的概念。但这个概念并未在文献中出现也未被使用,谨在本博文中滥用一下“高频”一词。点云表达的是三维空间中的一种信息,这种信息本身并没有一一对应的函数值。故点云本身并没有在讲诉一种变化的信号。但在抽象意义上,点云必然是在表达某种信号的,虽然没有明确的时间关系,但应该会存在某种空间关系(例如LiDar点云)。我们可以人为的指定点云空间中的一个点(例如Scan的重心或LiDar的“源”),基于此点来讨论点云在各个方向上所谓的频率。
在传统的信号处理中,高频信号一般指信号变化快,低频信号一般指信号变化缓慢。在图像处理中,高低频的概念被引申至不同方向上图像灰度的变化,傅里叶变换可以用于提取图像的周期成分滤除布纹噪声。在点云处理中,定义:点云法线向量差为点云所表达的信号。换言之,如果某处点云曲率大,则点云表达的是一个变化的信号。如果点云曲率小,则其表达的是一个不变的信号。这和我们的直观感受也是相近的,地面曲率小,它表达的信息量也小;人的五官部分曲率大,其表达了整个Scan中最大的信息量。
2.基于点云频率的滤波方法
虽然点云频率之前并没有被讨论,但使用频率信息的思想已经被广泛的应用在了各个方面,最著名的莫过于DoN算法。DoN算法被作者归类于点云分割算法中,但我认为并不准确,本质上DoN只是一种前处理,应该算是一种比较先进的点云滤波算法。分割本质上还是由欧式分割算法完成的。DoN 是 Difference of Normal 的简写。算法的目的是在去除点云低频滤波,低频信息(例如建筑物墙面,地面)往往会对分割产生干扰,高频信息(例如建筑物窗框,路面障碍锥)往往尺度上很小,直接采用 基于临近信息 的滤波器会将此类信息合并至墙面或路面中。所以DoN算法利用了多尺度空间的思想,算法如下:
在小尺度上计算点云法线1
在大尺度上计算点云法线2
法线1-法线2
滤去3中值较小的点
欧式分割
显然,在小尺度上是可以对高频信息进行检测的,此算法可以很好的小尺度高频信息。其在大规模点云(如LiDar点云)中优势尤其明显
计算出法向量之差后,调用pcl::ConditionOr,创建一个比较器,如果法向量差大于阈值(0.5),则保留,否则去掉。 过滤后的点保存在out_cloud_ptr中。就像上面说的一样,这是一个预处理算法,处理掉高频和低频(不懂)信息。原论文 Yani Ioannou. Automatic Urban Modelling using Mobile Urban LIDAR Data. Thesis (Master, Computing), Queen's University, March, 2010.。
PCL—低层次视觉—点云滤波(基于点云频率) - 相关文章
PCL—低层次视觉—点云滤波(基于点云频率)
removePointsUpTo() 去掉近距离的点
velodyne_callback() 接收点云的回调函数。