激光雷達(dá)作為自動(dòng)駕駛最常用的傳感器,經(jīng)常需要使用激光雷達(dá)來做建圖、定位和感知等任務(wù)。
而這時(shí)候使用降低點(diǎn)云規(guī)模的預(yù)處理方法,可以能夠去除無關(guān)區(qū)域的點(diǎn)以及降低點(diǎn)云規(guī)模。并能夠給后續(xù)的PCL點(diǎn)云分割帶來有效的收益。
點(diǎn)云預(yù)處理
1.1 指定區(qū)域獲取點(diǎn)云
在實(shí)際使用中,我們可以看出,雖然點(diǎn)云的分布范圍較廣,但大部分的點(diǎn)都集中的中間區(qū)域,距離越遠(yuǎn)點(diǎn)云越稀疏,相對(duì)的信息量也越小。
此外還能明顯看到一些離群點(diǎn),因此我們可以篩選掉一些較遠(yuǎn)的點(diǎn),只保留我們感興趣范圍內(nèi)的點(diǎn)。以下為保留 x 在 30m,y 在 15m,z 在 2m 范圍內(nèi)的點(diǎn)的效果:
template < class PointType >void removePointsOutsideRegion(boost::shared_ptr< pcl::PointCloud< PointType > >& src_cloud_ptr, boost::shared_ptr< pcl::PointCloud< PointType > >& dst_cloud_ptr, const std::pair< double, double >& x_range, const std::pair< double, double >& y_range, const std::pair< double, double >& z_range) { int num_points = src_cloud_ptr- >points.size(); boost::shared_ptr< pcl::PointCloud< PointType > > cloud_ptr(new pcl::PointCloud< PointType >()); cloud_ptr- >points.reserve(num_points); for (const auto& pt : src_cloud_ptr- >points) { bool inside = (pt.x >= x_range.first && pt.x < = x_range.second && pt.y >= y_range.first && pt.y < = y_range.second && pt.z >= z_range.first && pt.z < = z_range.second); if (inside) { cloud_ptr- >points.push_back(pt); } } dst_cloud_ptr = cloud_ptr;} // 或者使用CropBox來實(shí)現(xiàn)去除給定區(qū)域外的點(diǎn) pcl::CropBox< pcl::PointXYZ > box_filter; box_filter.setInputCloud(cloud_ptr); box_filter.setMin(Eigen::Vector4f(keep_x_range.first, keep_y_range.first, keep_z_range.first, 1.0)); box_filter.setMax(Eigen::Vector4f(keep_x_range.second, keep_y_range.second, keep_z_range.second, 1.0)); box_filter.filter(*temp_cloud_ptr);
1.2 去除給定區(qū)域的點(diǎn)
在某些情況下,我們也會(huì)需要去除給定區(qū)域內(nèi)部的點(diǎn),比如在自動(dòng)駕駛中激光掃描的區(qū)域有一部分來自搭載激光雷達(dá)的車子本身
template < class PointType >void filterPointsWithinRegion(boost::shared_ptr< pcl::PointCloud< PointType > >& src_cloud_ptr, boost::shared_ptr< pcl::PointCloud< PointType > >& dst_cloud_ptr, const std::pair< double, double >& x_range, const std::pair< double, double >& y_range, const std::pair< double, double >& z_range, bool remove) { int num_points = src_cloud_ptr- >points.size(); boost::shared_ptr< pcl::PointCloud< PointType > > cloud_ptr(new pcl::PointCloud< PointType >()); cloud_ptr- >points.reserve(num_points); for (const auto& pt : src_cloud_ptr- >points) { bool inside = (pt.x >= x_range.first && pt.x < = x_range.second && pt.y >= y_range.first && pt.y < = y_range.second && pt.z >= z_range.first && pt.z < = z_range.second); if (inside ^ remove) { cloud_ptr- >points.push_back(pt); } } dst_cloud_ptr = cloud_ptr;}// PassThrough: 可以指定點(diǎn)云中的點(diǎn)的某個(gè)字段進(jìn)行范圍限制,將其設(shè)為 true 時(shí)可以進(jìn)行給定只保留給定范圍內(nèi)的點(diǎn)的功能 pcl::PassThrough< pcl::PointXYZ > pass_filter; bool reverse_limits = true; pass_filter.setInputCloud(filtered_cloud_ptr); pass_filter.setFilterFieldName("x"); pass_filter.setFilterLimits(-5, 5); pass_filter.getFilterLimitsNegative(reverse_limits); // reverse the limits pass_filter.filter(*filtered_cloud_ptr); pass_filter.setFilterFieldName("y"); pass_filter.setFilterLimits(-2, 2); pass_filter.getFilterLimitsNegative(reverse_limits); // reverse the limits pass_filter.filter(*filtered_cloud_ptr); pass_filter.setFilterFieldName("z"); pass_filter.setFilterLimits(-2, 2); pass_filter.getFilterLimitsNegative(reverse_limits); // reverse the limits pass_filter.filter(*filtered_cloud_ptr);
1.3 點(diǎn)云下采樣
1.3.1 柵格化采樣
這里第一點(diǎn)介紹柵格化的下采樣,在 PCL 中對(duì)應(yīng)的函數(shù)為體素濾波。柵格化下采樣大致的思路是計(jì)算整體點(diǎn)云的中心。
通過計(jì)算每個(gè)點(diǎn)到中心的距離結(jié)合要求的分辨率計(jì)算柵格對(duì)應(yīng)的坐標(biāo),并入其中,最后遍歷每個(gè)包含點(diǎn)的柵格計(jì)算其中點(diǎn)的幾何中心或者取該柵格中心加入目標(biāo)點(diǎn)云即可。
pcl::VoxelGrid< pcl::PointXYZ > voxel_filter; voxel_filter.setLeafSize(0.1, 0.1, 0.1); voxel_filter.setInputCloud(cloud_ptr); voxel_filter.filter(*filtered_cloud_ptr);
1.3.2 點(diǎn)云所在區(qū)域密度規(guī)律濾波
該方法直接基于點(diǎn)云分布密度進(jìn)行去噪,直觀的感受是可以根據(jù)點(diǎn)云中每個(gè)點(diǎn)所在區(qū)域判斷其是否是噪聲,一般來說噪聲點(diǎn)所在區(qū)域都比較稀疏。
pcl::RadiusOutlierRemoval< pcl::PointXYZ >::Ptr radius_outlier_removal( new pcl::RadiusOutlierRemoval< pcl::PointXYZ >(true)); radius_outlier_removal- >setInputCloud(cloud_ptr); radius_outlier_removal- >setRadiusSearch(1.0); radius_outlier_removal- >setMinNeighborsInRadius(10); radius_outlier_removal- >filter(*filtered_cloud_ptr);
1.3.3 點(diǎn)云所在區(qū)域分布規(guī)律濾波
除了根據(jù)稠密意以外還可以根據(jù)距離來篩選濾波,每個(gè)點(diǎn)計(jì)算其到周圍若干點(diǎn)的平均距離,如果這個(gè)平均距離相對(duì)于整體點(diǎn)云中所有點(diǎn)的平均距離較近,則認(rèn)為其不是噪點(diǎn)
// PCL built-in radius removal pcl::StatisticalOutlierRemoval<pcl::PointXYZ>::Ptr statistical_outlier_removal( new pcl::StatisticalOutlierRemoval<pcl::PointXYZ>(true)); // set to true if we want to extract removed indices statistical_outlier_removal->setInputCloud(cloud_ptr); statistical_outlier_removal->setMeanK(20); statistical_outlier_removal->setStddevMulThresh(2.0); statistical_outlier_removal->filter(*filtered_cloud_ptr);
1.3.4 根據(jù)點(diǎn)云是否可以被穩(wěn)定觀察到篩選
LOAM 中對(duì)點(diǎn)云中的點(diǎn)是否能形成可靠特征的一個(gè)判斷標(biāo)準(zhǔn)是它能否被穩(wěn)定觀察到。
LOAM 中著重提了這兩種情況的點(diǎn)是不穩(wěn)定的:
- 特征成平面和掃描線近乎平行
- 特征掃描到的其中一端被另一個(gè)平面擋住,這部分的點(diǎn)也不穩(wěn)定
template < typename PointType >void filter_occuluded_points(boost::s
-
傳感器
+關(guān)注
關(guān)注
2548文章
50678瀏覽量
752010 -
激光雷達(dá)
+關(guān)注
關(guān)注
967文章
3939瀏覽量
189598 -
自動(dòng)駕駛
+關(guān)注
關(guān)注
783文章
13684瀏覽量
166147 -
點(diǎn)云
+關(guān)注
關(guān)注
0文章
58瀏覽量
3786
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論