Filter.cpp
Go to the documentation of this file.
1 
18 #include <Filter.h>
19 #include <pcl/filters/voxel_grid.h>
20 #include <pcl/filters/crop_box.h>
21 #include <pcl/filters/statistical_outlier_removal.h>
22 #include <pcl/filters/radius_outlier_removal.h>
23 #include <pcl/filters/extract_indices.h>
24 #include <pcl/common/angles.h>
25 #include <pcl/segmentation/sac_segmentation.h>
26 #include <pcl/segmentation/segment_differences.h>
27 
28 Filter::Filter(double leaf_size)
29 {
30  leaf_size_ = leaf_size;
31  noise_threshold_ = 0;
32  floor_threshold_ = 0;
33  given_center_ = false;
34 }
35 
36 Filter::Filter(double leaf_size, double noise_threshold, double floor_threshold)
37 {
38  leaf_size_ = leaf_size;
39  noise_threshold_ = noise_threshold;
40  floor_threshold_ = floor_threshold;
41  given_center_ = false;
42 }
43 
44 void Filter::setLeafSize(double leaf_size)
45 {
46  leaf_size_ = leaf_size;
47 }
48 
49 void Filter::setCloudCenter(Eigen::Vector3f cloud_center)
50 {
51  cloud_center_[0] = cloud_center[0];
52  cloud_center_[1] = cloud_center[1];
53  cloud_center_[2] = cloud_center[2];
54  given_center_ = true;
55 }
56 
57 void Filter::setNoiseThreshold(double noise_th)
58 {
59  noise_threshold_ = noise_th;
60 }
61 
62 void Filter::setFloorThreshold(double floor_th)
63 {
64  floor_threshold_ = floor_th;
65 }
66 
67 void Filter::run(PointCloudRGB::Ptr cloud, PointCloudRGB::Ptr cloud_filtered)
68 {
69  // outlierRemove(cloud, cloud_filtered);
70  pcl::copyPointCloud(*cloud, *cloud_filtered);
71 
72  // Filter floor
73  if (floor_threshold_ > 0)
74  filterFloor(cloud_filtered, cloud_filtered);
75 
76  // Filter noise
77  if (noise_threshold_ > 0)
78  filterNoise(cloud_filtered, cloud_filtered);
79 }
80 
81 void Filter::outlierRemove(PointCloudRGB::Ptr cloud, PointCloudRGB::Ptr cloud_filtered)
82 {
83  ROS_INFO("Filtering outliers");
84  pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> outlier_filter;
85  outlier_filter.setInputCloud(cloud);
86  outlier_filter.setMeanK(50);
87  outlier_filter.setStddevMulThresh(1.0);
88  outlier_filter.filter(*cloud_filtered);
89 }
90 
91 void Filter::downsampleCloud(PointCloudRGB::Ptr cloud, PointCloudRGB::Ptr cloud_downsampled)
92 {
93  ROS_INFO("Downsample cloud with leaf_size : %f", leaf_size_);
94  double res = Utils::computeCloudResolution(cloud);
95  ROS_INFO("Pointcloud resolution before downsampling: %f", res);
96 
97  const Eigen::Vector4f downsampling_leaf_size(leaf_size_, leaf_size_, leaf_size_, 0.0f);
98  pcl::VoxelGrid<pcl::PointXYZRGB> downsampling_filter;
99  downsampling_filter.setInputCloud(cloud);
100  downsampling_filter.setLeafSize(downsampling_leaf_size);
101  downsampling_filter.filter(*cloud_downsampled);
102 
103  res = Utils::computeCloudResolution(cloud_downsampled);
104  ROS_INFO("Pointcloud resolution after downsampling: %f", res);
105 }
106 
107 void Filter::filterNoise(PointCloudRGB::Ptr cloud, PointCloudRGB::Ptr cloud_filtered)
108 {
109  pcl::CropBox<pcl::PointXYZRGB> boxFilter;
110 
111  if(!given_center_)
112  pcl::compute3DCentroid(*cloud, cloud_center_);
113 
114  Eigen::Vector3f boxTranslatation;
115  boxTranslatation[0] = cloud_center_[0];
116  boxTranslatation[1] = cloud_center_[1];
117  boxTranslatation[2] = cloud_center_[2];
118  ROS_INFO("Point cloud center: (%f,%f,%f)", cloud_center_[0], cloud_center_[1], cloud_center_[2]);
119  ROS_INFO("Filter noise with threshold: (%f,%f,%f)", noise_threshold_, noise_threshold_, noise_threshold_/5);
120 
121  boxFilter.setTranslation(boxTranslatation);
122  boxFilter.setMin(Eigen::Vector4f(-noise_threshold_, -noise_threshold_, -noise_threshold_/5, 1.0));
123  boxFilter.setMax(Eigen::Vector4f(noise_threshold_, noise_threshold_, noise_threshold_/5, 1.0));
124  boxFilter.setInputCloud(cloud);
125  boxFilter.filter(*cloud_filtered);
126 
127  if (!Utils::isValidCloud(cloud_filtered))
128  {
129  ROS_ERROR("Unable to filter noise. Unfiltered cloud");
130  pcl::copyPointCloud(*cloud, *cloud_filtered);
131  }
132 }
133 
134 void Filter::filterFloor(PointCloudRGB::Ptr cloud, PointCloudRGB::Ptr cloud_filtered)
135 {
136  // Move cloud up if it has negative values
137  bool displace = false;
138  for (size_t i = 0; i < cloud->points.size() && !displace; i++)
139  {
140  if (cloud->points[i].z < 0)
141  displace = true;
142  }
143 
144  // Apply z_offset
145  if (displace)
146  Utils::translateCloud(cloud, cloud, 0, 0, 0.35);
147 
148  // Search for a plane perpendicular to z axis
149  Eigen::Vector3f axis(0, 0, 1);
150 
151  pcl::SACSegmentation<pcl::PointXYZRGB> seg;
152  seg.setAxis(axis);
153  seg.setEpsAngle(pcl::deg2rad(1.0)); // 1 degree tolerance
154  seg.setOptimizeCoefficients(true);
155  seg.setModelType(pcl::SACMODEL_PERPENDICULAR_PLANE);
156  seg.setMethodType(pcl::SAC_RANSAC);
157  seg.setDistanceThreshold(floor_threshold_);
158  seg.setInputCloud(cloud);
159 
160  pcl::ModelCoefficients coeff;
161  pcl::PointIndices floor;
162  seg.segment(floor, coeff);
163 
164  if(floor.indices.size() == 0)
165  {
166  ROS_ERROR("Unable to find floor. Unfiltered cloud");
167  pcl::copyPointCloud(*cloud, *cloud_filtered);
168  }
169  else
170  {
171  Filter::extractIndicesNegative(cloud, cloud_filtered,
172  boost::make_shared<std::vector<int>>(floor.indices));
173  }
174 }
175 
176 void Filter::removeFromCloud(PointCloudRGB::Ptr input_cloud,
177  PointCloudRGB::Ptr substract_cloud,
178  double threshold,
179  PointCloudRGB::Ptr cloud_filtered)
180 {
181  ROS_INFO("Difference from segment with threshold: %f", threshold);
182  pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>);
183  pcl::SegmentDifferences<pcl::PointXYZRGB> segment;
184  segment.setInputCloud(input_cloud);
185  segment.setTargetCloud(substract_cloud);
186  segment.setSearchMethod(tree);
187  segment.setDistanceThreshold(threshold);
188  segment.segment(*cloud_filtered);
189 }
190 
191 void Filter::extractIndicesNegative(PointCloudRGB::Ptr cloud_in,
192  PointCloudRGB::Ptr cloud_out,
193  pcl::IndicesPtr indices)
194 {
195  pcl::ExtractIndices<pcl::PointXYZRGB> extract_indices_filter;
196  extract_indices_filter.setInputCloud(cloud_in);
197  extract_indices_filter.setIndices(indices);
198  extract_indices_filter.setNegative(true);
199  extract_indices_filter.filter(*cloud_out);
200 }
201 
202 void Filter::extractIndices(PointCloudRGB::Ptr cloud_in,
203  PointCloudRGB::Ptr cloud_out,
204  pcl::IndicesPtr indices)
205 {
206  pcl::ExtractIndices<pcl::PointXYZRGB> extract_indices_filter;
207  extract_indices_filter.setInputCloud(cloud_in);
208  extract_indices_filter.setIndices(indices);
209  extract_indices_filter.filter(*cloud_out);
210 }
211 
212 void Filter::extractIndices(PointCloudNormal::Ptr normals_in,
213  PointCloudNormal::Ptr normals_out,
214  pcl::IndicesPtr indices)
215 {
216  pcl::ExtractIndices<pcl::Normal> extract_indices_filter;
217  extract_indices_filter.setInputCloud(normals_in);
218  extract_indices_filter.setIndices(indices);
219  extract_indices_filter.filter(*normals_out);
220 }
static bool isValidCloud(PointCloudXYZ::Ptr cloud)
Check whether cloud contains data and is not empty.
Definition: Utils.cpp:46
#define ROS_INFO(...)
static void translateCloud(PointCloudRGB::Ptr cloud_in, PointCloudRGB::Ptr cloud_out, double x_offset=0, double y_offset=0, double z_offset=0)
Apply translation to Cloud. Values given in [m].
Definition: Utils.cpp:203
static double computeCloudResolution(PointCloudXYZ::Ptr cloud)
Obtain the resolution of the cloud.
Definition: Utils.cpp:114
#define ROS_ERROR(...)


leica_point_cloud_processing
Author(s): Ines Lara Sicilia
autogenerated on Fri Feb 5 2021 03:20:30