00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <map>
00040 #include <pcl/common/io.h>
00041 #include <pcl/filters/voxel_grid_label.h>
00042 #include <pcl/filters/impl/voxel_grid.hpp>
00043
00045 void
00046 pcl::VoxelGridLabel::applyFilter (PointCloud &output)
00047 {
00048
00049 if (!input_)
00050 {
00051 PCL_WARN ("[pcl::%s::applyFilter] No input dataset given!\n", getClassName ().c_str ());
00052 output.width = output.height = 0;
00053 output.points.clear ();
00054 return;
00055 }
00056
00057
00058 output.height = 1;
00059 output.is_dense = true;
00060
00061 Eigen::Vector4f min_p, max_p;
00062
00063 if (!filter_field_name_.empty ())
00064 getMinMax3D<pcl::PointXYZRGBL>(input_, filter_field_name_, static_cast<float> (filter_limit_min_), static_cast<float> (filter_limit_max_), min_p, max_p, filter_limit_negative_);
00065 else
00066 getMinMax3D<pcl::PointXYZRGBL>(*input_, min_p, max_p);
00067
00068
00069 int64_t dx = static_cast<int64_t>((max_p[0] - min_p[0]) * inverse_leaf_size_[0])+1;
00070 int64_t dy = static_cast<int64_t>((max_p[1] - min_p[1]) * inverse_leaf_size_[1])+1;
00071 int64_t dz = static_cast<int64_t>((max_p[2] - min_p[2]) * inverse_leaf_size_[2])+1;
00072
00073 if( (dx*dy*dz) > static_cast<int64_t>(std::numeric_limits<int32_t>::max()) )
00074 {
00075 PCL_WARN("[pcl::%s::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow.", getClassName().c_str());
00076 output.clear();
00077 return;
00078 }
00079
00080
00081 min_b_[0] = static_cast<int> (floor (min_p[0] * inverse_leaf_size_[0]));
00082 max_b_[0] = static_cast<int> (floor (max_p[0] * inverse_leaf_size_[0]));
00083 min_b_[1] = static_cast<int> (floor (min_p[1] * inverse_leaf_size_[1]));
00084 max_b_[1] = static_cast<int> (floor (max_p[1] * inverse_leaf_size_[1]));
00085 min_b_[2] = static_cast<int> (floor (min_p[2] * inverse_leaf_size_[2]));
00086 max_b_[2] = static_cast<int> (floor (max_p[2] * inverse_leaf_size_[2]));
00087
00088
00089 div_b_ = max_b_ - min_b_ + Eigen::Vector4i::Ones ();
00090 div_b_[3] = 0;
00091
00092
00093 divb_mul_ = Eigen::Vector4i (1, div_b_[0], div_b_[0] * div_b_[1], 0);
00094
00095 int centroid_size = 4;
00096 if (downsample_all_data_)
00097 centroid_size = boost::mpl::size<FieldList>::value;
00098
00099
00100 std::vector<pcl::PCLPointField> fields;
00101 int rgba_index = -1;
00102 rgba_index = pcl::getFieldIndex (*input_, "rgb", fields);
00103 if (rgba_index == -1)
00104 rgba_index = pcl::getFieldIndex (*input_, "rgba", fields);
00105 if (rgba_index >= 0)
00106 {
00107 rgba_index = fields[rgba_index].offset;
00108 centroid_size += 3;
00109 }
00110
00111
00112 int label_index = -1;
00113 label_index = pcl::getFieldIndex (*input_, "label", fields);
00114
00115 std::vector<cloud_point_index_idx> index_vector;
00116 index_vector.reserve(input_->points.size());
00117
00118
00119 if (!filter_field_name_.empty ())
00120 {
00121
00122 std::vector<pcl::PCLPointField> fields;
00123 int distance_idx = pcl::getFieldIndex (*input_, filter_field_name_, fields);
00124 if (distance_idx == -1)
00125 PCL_WARN ("[pcl::%s::applyFilter] Invalid filter field name. Index is %d.\n", getClassName ().c_str (), distance_idx);
00126
00127
00128
00129
00130 for (unsigned int cp = 0; cp < static_cast<unsigned int> (input_->points.size ()); ++cp)
00131 {
00132 if (!input_->is_dense)
00133
00134 if (!pcl_isfinite (input_->points[cp].x) ||
00135 !pcl_isfinite (input_->points[cp].y) ||
00136 !pcl_isfinite (input_->points[cp].z))
00137 continue;
00138
00139
00140 const uint8_t* pt_data = reinterpret_cast<const uint8_t*> (&input_->points[cp]);
00141 float distance_value = 0;
00142 memcpy (&distance_value, pt_data + fields[distance_idx].offset, sizeof (float));
00143
00144 if (filter_limit_negative_)
00145 {
00146
00147 if ((distance_value < filter_limit_max_) && (distance_value > filter_limit_min_))
00148 continue;
00149 }
00150 else
00151 {
00152
00153 if ((distance_value > filter_limit_max_) || (distance_value < filter_limit_min_))
00154 continue;
00155 }
00156
00157 int ijk0 = static_cast<int> (floor (input_->points[cp].x * inverse_leaf_size_[0]) - min_b_[0]);
00158 int ijk1 = static_cast<int> (floor (input_->points[cp].y * inverse_leaf_size_[1]) - min_b_[1]);
00159 int ijk2 = static_cast<int> (floor (input_->points[cp].z * inverse_leaf_size_[2]) - min_b_[2]);
00160
00161
00162 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
00163 index_vector.push_back (cloud_point_index_idx (static_cast<unsigned int> (idx), cp));
00164 }
00165 }
00166
00167 else
00168 {
00169
00170
00171
00172 for (unsigned int cp = 0; cp < static_cast<unsigned int> (input_->points.size ()); ++cp)
00173 {
00174 if (!input_->is_dense)
00175
00176 if (!pcl_isfinite (input_->points[cp].x) ||
00177 !pcl_isfinite (input_->points[cp].y) ||
00178 !pcl_isfinite (input_->points[cp].z))
00179 continue;
00180
00181 int ijk0 = static_cast<int> (floor (input_->points[cp].x * inverse_leaf_size_[0]) - min_b_[0]);
00182 int ijk1 = static_cast<int> (floor (input_->points[cp].y * inverse_leaf_size_[1]) - min_b_[1]);
00183 int ijk2 = static_cast<int> (floor (input_->points[cp].z * inverse_leaf_size_[2]) - min_b_[2]);
00184
00185
00186 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
00187 index_vector.push_back (cloud_point_index_idx (static_cast<unsigned int> (idx), cp));
00188 }
00189 }
00190
00191
00192
00193 std::sort (index_vector.begin (), index_vector.end (), std::less<cloud_point_index_idx> ());
00194
00195
00196
00197 unsigned int total = 0;
00198 unsigned int index = 0;
00199 while (index < index_vector.size ())
00200 {
00201 unsigned int i = index + 1;
00202 while (i < index_vector.size () && index_vector[i].idx == index_vector[index].idx)
00203 ++i;
00204 ++total;
00205 index = i;
00206 }
00207
00208
00209 output.points.resize (total);
00210 if (save_leaf_layout_)
00211 {
00212 try
00213 {
00214
00215 uint32_t new_layout_size = div_b_[0]*div_b_[1]*div_b_[2];
00216
00217 uint32_t reinit_size = std::min (static_cast<unsigned int> (new_layout_size), static_cast<unsigned int> (leaf_layout_.size()));
00218 for (uint32_t i = 0; i < reinit_size; i++)
00219 {
00220 leaf_layout_[i] = -1;
00221 }
00222 leaf_layout_.resize (new_layout_size, -1);
00223 }
00224 catch (std::bad_alloc&)
00225 {
00226 throw PCLException("VoxelGrid bin size is too low; impossible to allocate memory for layout",
00227 "voxel_grid.hpp", "applyFilter");
00228 }
00229 catch (std::length_error&)
00230 {
00231 throw PCLException("VoxelGrid bin size is too low; impossible to allocate memory for layout",
00232 "voxel_grid.hpp", "applyFilter");
00233 }
00234 }
00235
00236 index = 0;
00237 Eigen::VectorXf centroid = Eigen::VectorXf::Zero (centroid_size);
00238 Eigen::VectorXf temporary = Eigen::VectorXf::Zero (centroid_size);
00239
00240 for (unsigned int cp = 0; cp < index_vector.size ();)
00241 {
00242 std::map<int, int> labels;
00243
00244
00245 if (!downsample_all_data_)
00246 {
00247 centroid[0] = input_->points[index_vector[cp].cloud_point_index].x;
00248 centroid[1] = input_->points[index_vector[cp].cloud_point_index].y;
00249 centroid[2] = input_->points[index_vector[cp].cloud_point_index].z;
00250 }
00251 else
00252 {
00253
00254 if (rgba_index >= 0)
00255 {
00256
00257 pcl::RGB rgb;
00258 memcpy (&rgb, reinterpret_cast<const char*> (&input_->points[index_vector[cp].cloud_point_index]) + rgba_index, sizeof (RGB));
00259 centroid[centroid_size-3] = rgb.r;
00260 centroid[centroid_size-2] = rgb.g;
00261 centroid[centroid_size-1] = rgb.b;
00262 }
00263
00264
00265 if (label_index >= 0)
00266 {
00267
00268 uint32_t label = input_->points[index_vector[cp].cloud_point_index].label;
00269 std::map<int, int>::iterator it = labels.find (label);
00270 if (it == labels.end ())
00271 labels.insert (labels.begin (), std::pair<int, int> (label, 1));
00272 else
00273 it->second = it->second++;
00274 }
00275
00276 pcl::for_each_type <FieldList> (NdCopyPointEigenFunctor <pcl::PointXYZRGBL> (input_->points[index_vector[cp].cloud_point_index], centroid));
00277 }
00278
00279 unsigned int i = cp + 1;
00280 while (i < index_vector.size () && index_vector[i].idx == index_vector[cp].idx)
00281 {
00282 if (!downsample_all_data_)
00283 {
00284 centroid[0] += input_->points[index_vector[i].cloud_point_index].x;
00285 centroid[1] += input_->points[index_vector[i].cloud_point_index].y;
00286 centroid[2] += input_->points[index_vector[i].cloud_point_index].z;
00287 }
00288 else
00289 {
00290
00291 if (rgba_index >= 0)
00292 {
00293
00294 pcl::RGB rgb;
00295 memcpy (&rgb, reinterpret_cast<const char*> (&input_->points[index_vector[i].cloud_point_index]) + rgba_index, sizeof (RGB));
00296 temporary[centroid_size-3] = rgb.r;
00297 temporary[centroid_size-2] = rgb.g;
00298 temporary[centroid_size-1] = rgb.b;
00299 }
00300 pcl::for_each_type <FieldList> (NdCopyPointEigenFunctor <pcl::PointXYZRGBL> (input_->points[index_vector[i].cloud_point_index], temporary));
00301 centroid += temporary;
00302 }
00303 ++i;
00304 }
00305
00306
00307 if (save_leaf_layout_)
00308 leaf_layout_[index_vector[cp].idx] = index;
00309
00310 centroid /= static_cast<float> (i - cp);
00311
00312
00313
00314 if (!downsample_all_data_)
00315 {
00316 output.points[index].x = centroid[0];
00317 output.points[index].y = centroid[1];
00318 output.points[index].z = centroid[2];
00319 }
00320 else
00321 {
00322 pcl::for_each_type<FieldList> (pcl::NdCopyEigenPointFunctor <pcl::PointXYZRGBL> (centroid, output.points[index]));
00323
00324 if (rgba_index >= 0)
00325 {
00326
00327 float r = centroid[centroid_size-3], g = centroid[centroid_size-2], b = centroid[centroid_size-1];
00328 int rgb = (static_cast<int> (r) << 16) | (static_cast<int> (g) << 8) | static_cast<int> (b);
00329 memcpy (reinterpret_cast<char*> (&output.points[index]) + rgba_index, &rgb, sizeof (float));
00330 }
00331
00332 if (label_index >= 0)
00333 {
00334
00335 std::map<int, int>::iterator it = labels.begin ();
00336 int n_occurrence = it->second;
00337 int label = it->first;
00338 if (it != labels.end ())
00339 {
00340 for (it = labels.begin (); it != labels.end (); it++)
00341 {
00342 if (n_occurrence < it->second)
00343 {
00344 n_occurrence = it->second;
00345 label = it->first;
00346 }
00347 }
00348 }
00349 output.points[index].label = label;
00350 }
00351 }
00352 cp = i;
00353 ++index;
00354 }
00355 output.width = static_cast<uint32_t> (output.points.size ());
00356 }
00357