PageRenderTime 56ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/PCL-1.5.1-Source/filters/include/pcl/filters/impl/normal_space.hpp

#
C++ Header | 321 lines | 211 code | 38 blank | 72 comment | 41 complexity | 4711d9f43451953488b9c8e535eae9d1 MD5 | raw file
  1. /*
  2. * Software License Agreement (BSD License)
  3. *
  4. * Point Cloud Library (PCL) - www.pointclouds.org
  5. * Copyright (c) 2009-2011, Willow Garage, Inc.
  6. *
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * * Redistributions in binary form must reproduce the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer in the documentation and/or other materials provided
  18. * with the distribution.
  19. * * Neither the name of Willow Garage, Inc. nor the names of its
  20. * contributors may be used to endorse or promote products derived
  21. * from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  26. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  27. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  28. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  29. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  30. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  31. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  33. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. * POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. */
  37. #ifndef PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_
  38. #define PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_
  39. #include "pcl/filters/normal_space.h"
  40. #include <vector>
  41. #include <list>
  42. ///////////////////////////////////////////////////////////////////////////////
  43. template<typename PointT, typename NormalT> void
  44. pcl::NormalSpaceSampling<PointT, NormalT>::applyFilter (PointCloud &output)
  45. {
  46. // If sample size is 0 or if the sample size is greater then input cloud size
  47. // then return entire copy of cloud
  48. if (sample_ >= input_->size ())
  49. {
  50. output = *input_;
  51. return;
  52. }
  53. // Resize output cloud to sample size
  54. output.points.resize (sample_);
  55. output.width = sample_;
  56. output.height = 1;
  57. // allocate memory for the histogram of normals.. Normals will then be sampled from each bin..
  58. unsigned int n_bins = binsx_ * binsy_ * binsz_;
  59. // list<int> holds the indices of points in that bin.. Using list to avoid repeated resizing of vectors.. Helps when the point cloud is
  60. // large..
  61. std::vector< std::list <int> > normals_hg;
  62. normals_hg.reserve (n_bins);
  63. for (unsigned int i = 0; i < n_bins; i++)
  64. normals_hg.push_back (std::list<int> ());
  65. for (unsigned int i = 0; i < input_normals_->points.size (); i++)
  66. {
  67. unsigned int bin_number = findBin (input_normals_->points[i].normal, n_bins);
  68. normals_hg[bin_number].push_back (i);
  69. }
  70. // Setting up random access for the list created above.. Maintaining the iterators to individual elements of the list in a vector.. Using
  71. // vector now as the size of the list is known..
  72. std::vector< std::vector <std::list<int>::iterator> > random_access (normals_hg.size ());
  73. for (unsigned int i = 0; i < normals_hg.size (); i++)
  74. {
  75. random_access.push_back (std::vector< std::list<int>::iterator> ());
  76. random_access[i].resize (normals_hg[i].size ());
  77. unsigned int j=0;
  78. for (std::list<int>::iterator itr = normals_hg[i].begin (); itr != normals_hg[i].end (); itr++, j++)
  79. {
  80. random_access[i][j] = itr;
  81. }
  82. }
  83. unsigned int* start_index = new unsigned int[normals_hg.size ()];
  84. start_index[0] = 0;
  85. unsigned int prev_index = start_index[0];
  86. for (unsigned int i = 1; i < normals_hg.size (); i++)
  87. {
  88. start_index[i] = prev_index + normals_hg[i-1].size ();
  89. prev_index = start_index[i];
  90. }
  91. // maintaining flags to check if a point is sampled
  92. boost::dynamic_bitset<> is_sampled_flag (input_normals_->points.size ());
  93. // maintaining flags to check if all points in the bin are sampled
  94. boost::dynamic_bitset<> bin_empty_flag (normals_hg.size ());
  95. unsigned int i = 0;
  96. while (i < sample_)
  97. {
  98. // iterating through every bin and picking one point at random, until the required number of points are sampled..
  99. for (unsigned int j = 0; j < normals_hg.size (); j++)
  100. {
  101. unsigned int M = normals_hg[j].size ();
  102. if (M == 0 || bin_empty_flag.test (j))// bin_empty_flag(i) is set if all points in that bin are sampled..
  103. {
  104. continue;
  105. }
  106. unsigned int pos = 0;
  107. unsigned int random_index = 0;
  108. //picking up a sample at random from jth bin
  109. do
  110. {
  111. random_index = std::rand () % M;
  112. pos = start_index[j] + random_index;
  113. } while (is_sampled_flag.test (pos));
  114. is_sampled_flag.flip (start_index[j] + random_index);
  115. // checking if all points in bin j are sampled..
  116. if (isEntireBinSampled (is_sampled_flag, start_index[j], normals_hg[j].size ()))
  117. {
  118. bin_empty_flag.flip (j);
  119. }
  120. unsigned int index = *(random_access[j][random_index]);
  121. output.points[i] = input_->points[index];
  122. i++;
  123. if (i == sample_)
  124. {
  125. break;
  126. }
  127. }
  128. }
  129. delete[] start_index;
  130. }
  131. ///////////////////////////////////////////////////////////////////////////////
  132. template<typename PointT, typename NormalT> bool
  133. pcl::NormalSpaceSampling<PointT, NormalT>::isEntireBinSampled (boost::dynamic_bitset<> &array, unsigned int start_index, unsigned int length)
  134. {
  135. bool status = true;
  136. for (unsigned int i = start_index; i < start_index + length; i++)
  137. {
  138. status = status & array.test (i);
  139. }
  140. return status;
  141. }
  142. ///////////////////////////////////////////////////////////////////////////////
  143. template<typename PointT, typename NormalT> unsigned int
  144. pcl::NormalSpaceSampling<PointT, NormalT>::findBin (float *normal, unsigned int nbins)
  145. {
  146. unsigned int bin_number = 0;
  147. // holds the bin numbers for direction cosines in x,y,z directions
  148. unsigned int t[3] = {0,0,0};
  149. // dcos is the direction cosine.
  150. float dcos = 0.0;
  151. float bin_size = 0.0;
  152. // max_cos and min_cos are the maximum and minimum values of cos(theta) respectively
  153. float max_cos = 1.0;
  154. float min_cos = -1.0;
  155. dcos = cos(normal[0]);
  156. bin_size = (max_cos - min_cos) / binsx_;
  157. // finding bin number for direction cosine in x direction
  158. unsigned int k = 0;
  159. for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  160. {
  161. if (dcos >= i && dcos <= (i+bin_size))
  162. {
  163. break;
  164. }
  165. }
  166. t[0] = k;
  167. dcos = cos(normal[1]);
  168. bin_size = (max_cos - min_cos) / binsy_;
  169. // finding bin number for direction cosine in y direction
  170. k = 0;
  171. for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  172. {
  173. if (dcos >= i && dcos <= (i+bin_size))
  174. {
  175. break;
  176. }
  177. }
  178. t[1] = k;
  179. dcos = cos(normal[2]);
  180. bin_size = (max_cos - min_cos) / binsz_;
  181. // finding bin number for direction cosine in z direction
  182. k = 0;
  183. for (float i = min_cos; (i + bin_size) < (max_cos - bin_size); i += bin_size , k++)
  184. {
  185. if (dcos >= i && dcos <= (i+bin_size))
  186. {
  187. break;
  188. }
  189. }
  190. t[2] = k;
  191. bin_number = t[0] * (binsy_*binsz_) + t[1] * binsz_ + t[2];
  192. return bin_number;
  193. }
  194. ///////////////////////////////////////////////////////////////////////////////
  195. template<typename PointT, typename NormalT>
  196. void
  197. pcl::NormalSpaceSampling<PointT, NormalT>::applyFilter (std::vector<int> &indices)
  198. {
  199. // If sample size is 0 or if the sample size is greater then input cloud size
  200. // then return all indices
  201. if (sample_ >= input_->width * input_->height)
  202. {
  203. indices = *indices_;
  204. return;
  205. }
  206. // Resize output indices to sample size
  207. indices.resize (sample_);
  208. // allocate memory for the histogram of normals.. Normals will then be sampled from each bin..
  209. unsigned int n_bins = binsx_ * binsy_ * binsz_;
  210. // list<int> holds the indices of points in that bin.. Using list to avoid repeated resizing of vectors.. Helps when the point cloud is
  211. // large..
  212. std::vector< std::list <int> > normals_hg;
  213. normals_hg.reserve (n_bins);
  214. for (unsigned int i = 0; i < n_bins; i++)
  215. normals_hg.push_back (std::list<int> ());
  216. for (unsigned int i=0; i < input_normals_->points.size (); i++)
  217. {
  218. unsigned int bin_number = findBin (input_normals_->points[i].normal, n_bins);
  219. normals_hg[bin_number].push_back (i);
  220. }
  221. // Setting up random access for the list created above.. Maintaining the iterators to individual elements of the list in a vector.. Using
  222. // vector now as the size of the list is known..
  223. std::vector< std::vector <std::list<int>::iterator> > random_access (normals_hg.size ());
  224. for (unsigned int i = 0; i < normals_hg.size (); i++)
  225. {
  226. random_access.push_back (std::vector<std::list<int>::iterator> ());
  227. random_access[i].resize (normals_hg[i].size ());
  228. unsigned int j = 0;
  229. for (std::list<int>::iterator itr = normals_hg[i].begin (); itr != normals_hg[i].end (); itr++, j++)
  230. {
  231. random_access[i][j] = itr;
  232. }
  233. }
  234. unsigned int* start_index = new unsigned int[normals_hg.size ()];
  235. start_index[0] = 0;
  236. unsigned int prev_index = start_index[0];
  237. for (unsigned int i = 1; i < normals_hg.size (); i++)
  238. {
  239. start_index[i] = prev_index + normals_hg[i-1].size ();
  240. prev_index = start_index[i];
  241. }
  242. // maintaining flags to check if a point is sampled
  243. boost::dynamic_bitset<> is_sampled_flag (input_normals_->points.size ());
  244. // maintaining flags to check if all points in the bin are sampled
  245. boost::dynamic_bitset<> bin_empty_flag (normals_hg.size ());
  246. unsigned int i=0;
  247. while (i < sample_)
  248. {
  249. // iterating through every bin and picking one point at random, until the required number of points are sampled..
  250. for (unsigned int j = 0; j < normals_hg.size (); j++)
  251. {
  252. unsigned int M = normals_hg[j].size();
  253. if (M==0 || bin_empty_flag.test (j)) // bin_empty_flag(i) is set if all points in that bin are sampled..
  254. {
  255. continue;
  256. }
  257. unsigned int pos = 0;
  258. unsigned int random_index = 0;
  259. //picking up a sample at random from jth bin
  260. do
  261. {
  262. random_index = std::rand () % M;
  263. pos = start_index[j] + random_index;
  264. } while (is_sampled_flag.test (pos));
  265. is_sampled_flag.flip (start_index[j] + random_index);
  266. // checking if all points in bin j are sampled..
  267. if (isEntireBinSampled (is_sampled_flag, start_index[j], normals_hg[j].size ()))
  268. {
  269. bin_empty_flag.flip (j);
  270. }
  271. unsigned int index = *(random_access[j][random_index]);
  272. indices[i] = index;
  273. i++;
  274. if (i == sample_)
  275. {
  276. break;
  277. }
  278. }
  279. }
  280. delete[] start_index;
  281. }
  282. #define PCL_INSTANTIATE_NormalSpaceSampling(T,NT) template class PCL_EXPORTS pcl::NormalSpaceSampling<T,NT>;
  283. #endif // PCL_FILTERS_IMPL_NORMAL_SPACE_SAMPLE_H_