31 #ifndef NORM_EST_PCL_OMP_H
32 #define NORM_EST_PCL_OMP_H
34 #include <pcl/kdtree/kdtree_flann.h>
35 #include <pcl/point_cloud.h>
36 #include <pcl/point_types.h>
38 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
65 template <
class Po
int,
class Normal>
92 typename pcl::PointCloud<Normal>::Ptr
normals)
94 set_default_parameters();
109 return lower_neighbor_bound_neighbors;
112 return lower_neighbor_bound_neighbors;
119 typename pcl::PointCloud<Point>::Ptr &
point_cloud() {
return pts; }
120 typename pcl::PointCloud<Point>::Ptr
point_cloud()
const {
return pts; }
122 typename pcl::PointCloud<Normal>::Ptr
normal_cloud()
const {
return nls; }
125 int neighborhood_type =
KNN,
126 float neighborhood_size = 200) {
127 std::cout <<
"Normal_Estimation ";
130 std::cout <<
"Points ";
131 switch (neighborhood_type) {
134 std::cout << (int)neighborhood_size <<
std::endl;
135 points_knn((
int)neighborhood_size);
138 std::cout <<
"radius=";
139 std::cout << neighborhood_size <<
std::endl;
140 points_radius(neighborhood_size);
143 std::cout <<
"Parameter Error : bad neighborhood type"
149 std::cout <<
"Unif ";
150 switch (neighborhood_type) {
153 std::cout << (int)neighborhood_size <<
std::endl;
154 unif_knn((
int)neighborhood_size);
157 std::cout <<
"radius=";
158 std::cout << neighborhood_size <<
std::endl;
159 unif_radius(neighborhood_size);
162 std::cout <<
"Parameter Error : bad neighborhood type"
168 std::cout <<
"Cubes ";
169 switch (neighborhood_type) {
172 std::cout << (int)neighborhood_size <<
std::endl;
173 cubes_knn((
int)neighborhood_size);
176 std::cout <<
"radius=";
177 std::cout << neighborhood_size <<
std::endl;
178 cubes_radius(neighborhood_size);
181 std::cout <<
"Parameter Error : bad neighborhood type"
187 std::cout <<
"Parameter Error : bad method" <<
std::endl;
194 int lower_neighbor_bound_neighbors;
202 float small_radius_factor;
208 typename pcl::PointCloud<Point>::Ptr pts;
209 typename pcl::PointCloud<Normal>::Ptr nls;
214 void set_default_parameters() {
219 tol_angle_rad = 0.79f;
220 small_radius_factor = 4;
222 lower_neighbor_bound_neighbors = 10;
232 inline void generate_rotation_matrix(
233 std::vector<Eigen::Matrix3f> &rotMat,
234 std::vector<Eigen::Matrix3f> &rotMatInv,
239 if (rotations == 0) {
240 Eigen::Matrix3f rMat;
241 rMat << 1, 0, 0, 0, 1, 0, 0, 0, 1;
242 rotMat.push_back(rMat);
243 rotMatInv.push_back(rMat);
245 for (
int i = 0; i < rotations; i++) {
246 float theta = (rand() + 0.f) / RAND_MAX * 2 * 3.14159265f;
247 float phi = (rand() + 0.f) / RAND_MAX * 2 * 3.14159265f;
248 float psi = (rand() + 0.f) / RAND_MAX * 2 * 3.14159265f;
252 Rt << 1, 0, 0, 0, cos(theta), -sin(theta), 0, sin(theta),
254 Rph << cos(phi), 0, sin(phi), 0, 1, 0, -sin(phi), 0, cos(phi);
255 Rps << cos(psi), -sin(psi), 0, sin(psi), cos(psi), 0, 0, 0, 1;
256 Eigen::Matrix3f Rtinv;
257 Eigen::Matrix3f Rphinv;
258 Eigen::Matrix3f Rpsinv;
259 Rtinv << 1, 0, 0, 0, cos(theta), sin(theta), 0, -sin(theta),
261 Rphinv << cos(phi), 0, -sin(phi), 0, 1, 0, sin(phi), 0,
263 Rpsinv << cos(psi), sin(psi), 0, -sin(psi), cos(psi), 0, 0, 0,
266 Eigen::Matrix3f rMat = Rt * Rph * Rps;
267 Eigen::Matrix3f rMatInv = Rpsinv * Rphinv * Rtinv;
268 rotMat.push_back(rMat);
269 rotMatInv.push_back(rMatInv);
279 inline void generate_random_points_vector(
280 std::vector<Eigen::Vector3f> &
points,
int point_number) {
281 points.resize(point_number);
282 for (
int i = 0; i < point_number; i++) {
285 x = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
286 y = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
287 z = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
288 }
while (x * x + y * y + z * z > 1);
301 inline void generate_random_int_vector(std::vector<int> &vecInt,
303 vecInt.resize(point_number);
304 for (
int i = 0; i < point_number; i++) {
318 inline void list_of_triplets(std::vector<Eigen::Vector3i> &triplets,
319 const int &number_of_points,
320 const unsigned int &plane_number,
321 std::vector<int> &vecInt) {
328 unsigned long long total_comb = number_of_points;
329 total_comb *= (number_of_points - 1);
330 total_comb *= (number_of_points - 2);
333 std::vector<unsigned long long> tab_binome_3(number_of_points + 1);
334 std::vector<unsigned long long> tab_binome_2(number_of_points + 1);
336 for (
int i = 0; i < number_of_points + 1; i++) {
338 tab_binome_3[i] = tab_binome_3[i - 1] * i / (i - 3);
345 tab_binome_2[i] = tab_binome_2[i - 1] * i / (i - 2);
353 std::vector<unsigned long long> comb_idx(plane_number);
354 for (
int i = 0; i < plane_number; i++) {
355 comb_idx[i] = i % total_comb;
357 if (total_comb < RAND_MAX) {
358 std::map<int, int> table_next;
359 for (
int i = 0; i < plane_number; i++) {
360 int temp_idx = vecInt[i % vecInt.size()] % total_comb;
361 if (temp_idx < plane_number) {
362 int temp = comb_idx[i];
363 comb_idx[i] = comb_idx[temp_idx];
364 comb_idx[temp_idx] = temp;
366 std::map<int, int>::iterator itmap =
367 table_next.find(temp_idx);
368 if (itmap != table_next.end()) {
369 int temp = comb_idx[i];
370 comb_idx[i] = itmap->second;
371 itmap->second = temp;
373 comb_idx[i] = temp_idx;
374 table_next.insert(std::pair<int, int>(temp_idx, i));
379 unsigned long long ref_RAND_MAX = RAND_MAX;
381 while (ref_RAND_MAX < total_comb) {
383 ref_RAND_MAX *= RAND_MAX;
385 std::map<unsigned long long, unsigned long long> table_next;
387 for (
int i = 0; i < plane_number; i++) {
389 unsigned long long random_int = vecInt[pos % vecInt.size()];
391 for (
int j = 0; j < size_test; j++) {
393 ((
unsigned long long)vecInt[pos % vecInt.size()]) *
398 random_int = random_int % total_comb;
399 if (random_int < plane_number) {
400 int temp = comb_idx[i];
401 comb_idx[i] = comb_idx[random_int];
402 comb_idx[random_int] = temp;
404 std::map<unsigned long long, unsigned long long>::iterator
405 itmap = table_next.find(random_int);
406 if (itmap != table_next.end()) {
407 int temp = comb_idx[i];
408 comb_idx[i] = itmap->second;
409 itmap->second = temp;
411 comb_idx[i] = random_int;
413 std::pair<
unsigned long long,
414 unsigned long long>(random_int, i));
421 triplets.resize(plane_number);
422 for (
int pos = 0; pos < plane_number; pos++) {
424 unsigned long long idx = comb_idx[pos];
426 while (tab_binome_3[pos_temp] <= idx) {
431 idx -= tab_binome_3[pos_temp];
440 while (tab_binome_2[pos_temp] <= idx) {
445 idx -= tab_binome_2[pos_temp];
453 while (pos_temp != idx) {
467 inline void generate_cube_vector(std::vector<int> &cubes_idx,
int n) {
470 std::vector<float> probas(n_cubes * n_cubes * n_cubes);
471 float step = 2.f / n_cubes;
472 float xmin = -(n_cubes / 2.f) * step;
473 float ymin = -(n_cubes / 2.f) * step;
474 float zmin = -(n_cubes / 2.f) * step;
476 for (
int k = 0; k < n_cubes; k++) {
477 for (
int j = 0; j < n_cubes; j++) {
478 for (
int i = 0; i < n_cubes; i++) {
481 float x1 = xmin + i * step;
482 float y1 = ymin + j * step;
483 float z1 = zmin + k * step;
484 float x2 = x1 + step;
485 float y2 = y1 + step;
486 float z2 = z1 + step;
488 Eigen::Vector3f pt(x1, y1, z1);
489 if (pt.squaredNorm() <= 1) {
492 pt = Eigen::Vector3f(x2, y1, z1);
493 if (pt.squaredNorm() <= 1) {
496 pt = Eigen::Vector3f(x1, y2, z1);
497 if (pt.squaredNorm() <= 1) {
500 pt = Eigen::Vector3f(x2, y2, z1);
501 if (pt.squaredNorm() <= 1) {
504 pt = Eigen::Vector3f(x1, y1, z2);
505 if (pt.squaredNorm() <= 1) {
508 pt = Eigen::Vector3f(x2, y1, z2);
509 if (pt.squaredNorm() <= 1) {
512 pt = Eigen::Vector3f(x1, y2, z2);
513 if (pt.squaredNorm() <= 1) {
516 pt = Eigen::Vector3f(x2, y2, z2);
517 if (pt.squaredNorm() <= 1) {
521 probas[i + j * n_cubes + k * n_cubes * n_cubes] = prob;
527 probas[0] /= sum_prob;
528 for (
int i = 1; i < n_cubes * n_cubes * n_cubes; i++) {
529 probas[i] /= sum_prob;
530 probas[i] += probas[i - 1];
535 for (
int i = 0; i < n; i++) {
536 float pos = (rand() + 0.f) / RAND_MAX;
538 int end = n_cubes * n_cubes * n_cubes - 1;
539 int temp = (begin + end) / 2;
540 while (temp != begin) {
541 if (probas[temp] < pos) {
546 temp = (begin + end) / 2;
562 inline void assign_points_to_cubes(std::vector<int> &pointIdxRadiusSearch,
563 std::vector<int> cubes[],
567 Eigen::Matrix3f &rotMat) {
568 float step = 2.f / n_cubes * radius;
569 for (
unsigned int i = 0; i < pointIdxRadiusSearch.size(); i++) {
570 int idx = pointIdxRadiusSearch[i];
571 points[i] = pts->points[idx];
572 points[i].getVector3fMap() = rotMat *
points[i].getVector3fMap();
573 Point refPoint2 = refPoint;
574 refPoint2.getVector3fMap() = rotMat * refPoint2.getVector3fMap();
587 cubes[x + y * n_cubes + z * n_cubes * n_cubes].push_back(i);
598 inline void generate_cubes_triplets(std::vector<Eigen::Vector3i> &triplets,
599 std::vector<int> cubes[],
600 std::vector<int> &cubes_idx,
601 std::vector<int> &vecInt) {
602 triplets.resize(n_planes);
604 std::vector<Eigen::Vector3i>::iterator ittrip = triplets.begin();
605 std::vector<int>::iterator itcube = cubes_idx.begin();
606 std::vector<int>::iterator itint = vecInt.begin();
609 while (ittrip != triplets.end() && itcube != cubes_idx.end()) {
610 if (cubes[*itcube].
size() != 0) {
611 int new_idx = cubes[*itcube][(*itint) % cubes[*itcube].size()];
612 bool is_valid =
true;
613 for (
int i = 0; i < idx; i++) {
614 if (new_idx == (*ittrip)[i]) {
619 (*ittrip)[idx] = new_idx;
631 while (ittrip != triplets.end()) {
632 int picked_points = 0;
633 while (picked_points < 3) {
634 int pos = rand() % (n_cubes * n_cubes * n_cubes);
635 if (cubes[pos].
size() == 0) {
638 int idx = rand() % cubes[pos].size();
639 bool is_valid =
true;
640 for (
int i = 0; i < picked_points; i++) {
641 if (cubes[pos][idx] == (*ittrip)[i]) {
646 (*ittrip)[picked_points] = cubes[pos][idx];
661 inline void find_a_triplet(pcl::KdTreeFLANN<Point> &tree,
666 int picked_points = 0;
668 while (picked_points < 3) {
675 x = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
676 y = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
677 z = ((rand() + 0.f) / RAND_MAX) * 2 - 1;
678 }
while (x * x + y * y + z * z > 1);
693 std::vector<int> pointIdxRadiusSearch;
694 std::vector<float> pointRadiusSquaredDistance;
695 tree.radiusSearch(pt, radius2, pointIdxRadiusSearch,
696 pointRadiusSquaredDistance);
698 if (pointIdxRadiusSearch.size() != 0) {
700 pointIdxRadiusSearch[rand() %
701 pointIdxRadiusSearch.size()];
702 bool is_valid =
true;
703 for (
int i = 0; i < picked_points; i++) {
704 if (new_index == triplet[i]) {
709 triplet[picked_points] = new_index;
727 inline void generate_list_of_triplets(
728 std::vector<Eigen::Vector3i> &triplets,
732 pcl::KdTreeFLANN<Point> &tree,
734 std::vector<Eigen::Vector3f> &
points,
735 std::vector<int> &vecInt) {
736 triplets.resize(plane_number);
738 std::vector<Eigen::Vector3i>::iterator ittrip = triplets.begin();
739 std::vector<Eigen::Vector3f>::iterator itpoints =
points.begin();
740 std::vector<int>::iterator itint = vecInt.begin();
743 while (ittrip != triplets.end() && itpoints !=
points.end()) {
746 x = (*itpoints)[0] * radius1 + pt.x;
747 y = (*itpoints)[1] * radius1 + pt.y;
748 z = (*itpoints)[2] * radius1 + pt.z;
755 std::vector<int> pointIdxRadiusSearch;
756 std::vector<float> pointRadiusSquaredDistance;
757 tree.radiusSearch(refPoint, radius2, pointIdxRadiusSearch,
758 pointRadiusSquaredDistance);
761 if (pointIdxRadiusSearch.size() != 0) {
763 pointIdxRadiusSearch[(*itint) %
764 pointIdxRadiusSearch.size()];
765 bool is_valid =
true;
766 for (
int i = 0; i < idx; i++) {
767 if (new_index == (*ittrip)[i]) {
772 (*ittrip)[idx] = new_index;
785 while (ittrip != triplets.end()) {
786 find_a_triplet(tree, radius1, radius2, *ittrip, pt);
801 float normal_at_point(
const int d1,
806 std::vector<Eigen::Vector3i> &triplets,
807 std::vector<float> &conf_interv) {
808 if (points_size < 3) {
809 nls->points[n].normal_x = 0;
810 nls->points[n].normal_y = 0;
811 nls->points[n].normal_z = 0;
816 float *votes =
new float[d1 * d2];
817 Eigen::Vector3f *votesV =
new Eigen::Vector3f[d1 * d2];
818 for (
int i = 0; i < d1; i++) {
819 for (
int j = 0; j < d2; j++) {
820 votes[i + j * d1] = 0;
821 votesV[i + j * d1] = Eigen::Vector3f(0, 0, 0);
825 float max1 = 0, max2 = 0;
834 for (
int n_try = 0; n_try < n_planes; n_try++) {
835 int p0 = triplets[n_try][0];
836 int p1 = triplets[n_try][1];
837 int p2 = triplets[n_try][2];
840 points[p1].getVector3fMap() -
points[p0].getVector3fMap();
842 points[p2].getVector3fMap() -
points[p0].getVector3fMap();
844 Eigen::Vector3f Pn = v1.cross(v2);
846 if (Pn.dot(
points[p0].getVector3fMap()) > 0) {
851 phi = acos((
float)Pn[2]);
852 float dphi =
PI / n_phi;
854 posp = int(
floor((phi + dphi / 2.) * n_phi / PI));
856 if (posp == 0 || posp == n_phi) {
859 float theta = acos((
float)Pn[0] /
860 sqrt(
float(Pn[0] * Pn[0] + Pn[1] * Pn[1])));
865 float dtheta =
PI / (n_phi * sin(posp * dphi));
866 post = (int)(
floor((theta + dtheta / 2) / dtheta)) %
873 votes[post + posp * d1] += 1.;
874 votesV[post + posp * d1] += Pn;
876 max1 = votes[i1 + j1 * d1] / (n_try + 1);
877 max2 = votes[i2 + j2 * d1] / (n_try + 1);
878 votes_val = votes[post + posp * d1] / (n_try + 1);
880 if (votes_val > max1) {
887 }
else if (votes_val > max2 && post != i1 && posp != j1) {
893 if (max1 - conf_interv[n_try] > max2) {
897 votesV[i1 + j1 * d1].normalize();
898 nls->points[n].getNormalVector3fMap() = votesV[i1 + j1 * d1];
913 inline Eigen::Vector3f normal_selection(
915 std::vector<Eigen::Vector3f> &normals_vec,
916 std::vector<float> &normals_conf) {
917 std::vector<bool> normals_use(rotations);
919 normals_use[0] =
true;
920 for (
int i = 1; i < rotations; i++) {
921 normals_use[i] =
true;
922 if (normals_vec[0].
dot(normals_vec[i]) < 0) {
923 normals_vec[i] *= -1;
927 Eigen::Vector3f normal_final;
928 switch (selection_type) {
931 float confidence_final = 0;
932 for (
int i = 0; i < rotations; i++) {
933 if (normals_conf[i] > confidence_final) {
934 confidence_final = normals_conf[i];
935 normal_final = normals_vec[i];
941 std::vector<std::pair<Eigen::Vector3f, float>> normals_fin;
942 int number_to_test = rotations;
943 while (number_to_test > 0) {
947 for (
int i = 0; i < rotations; i++) {
948 if (normals_use[i] && normals_conf[i] > max_conf) {
949 max_conf = normals_conf[i];
954 normals_fin.push_back(std::pair<Eigen::Vector3f, float>(
955 normals_vec[idx] * normals_conf[idx],
957 normals_use[idx] =
false;
960 for (
int i = 0; i < rotations; i++) {
961 if (normals_use[i] &&
962 acos(normals_vec[idx].
dot(normals_vec[i])) <
964 normals_use[i] =
false;
966 normals_fin.back().first +=
967 normals_vec[i] * normals_conf[i];
968 normals_fin.back().second += normals_conf[i];
973 normal_final = normals_fin[0].first;
974 float conf_fin = normals_fin[0].second;
975 for (
unsigned int i = 1; i < normals_fin.size(); i++) {
976 if (normals_fin[i].second > conf_fin) {
977 conf_fin = normals_fin[i].second;
978 normal_final = normals_fin[i].first;
984 normal_final = normals_conf[0] * normals_vec[0];
985 for (
int i = 1; i < rotations; i++) {
986 normal_final += normals_conf[i] * normals_vec[i];
991 normal_final.normalize();
1001 void points_knn(
int neighbor_number) {
1003 nls->resize(pts->size());
1006 srand((
unsigned int)time(
NULL));
1009 pcl::KdTreeFLANN<Point> tree;
1010 tree.setInputCloud(pts);
1013 const int d1 = 2 * n_phi;
1014 const int d2 = n_phi + 1;
1017 std::vector<Eigen::Matrix3f> rotMat;
1018 std::vector<Eigen::Matrix3f> rotMatInv;
1019 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1029 std::vector<Eigen::Vector3i> trip;
1030 std::vector<int> vecInt;
1031 generate_random_int_vector(vecInt, 1000000);
1032 if (rotations <= 1) {
1033 list_of_triplets(trip, neighbor_number, n_planes, vecInt);
1036 list_of_triplets(trip, neighbor_number, rotations * n_planes,
1041 std::vector<float> conf_interv(n_planes);
1042 for (
int i = 0; i < n_planes; i++) {
1043 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1047 std::vector<int> permutation(pts->size());
1048 for (
int i = 0; i < pts->size(); i++) {
1051 for (
int i = 0; i < pts->size(); i++) {
1052 int j = rand() % pts->size();
1053 int temp = permutation[i];
1054 permutation[i] = permutation[j];
1055 permutation[j] = temp;
1058 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1059 #pragma omp parallel for schedule(guided)
1061 for (
int per = 0; per < (int)pts->size(); per++) {
1062 int n = permutation[per];
1066 if (pts->points[n].getVector3fMap() == Eigen::Vector3f(0, 0, 0)) {
1071 std::vector<int> pointIdxSearch;
1072 std::vector<float> pointSquaredDistance;
1073 tree.nearestKSearch(pts->points[n], neighbor_number, pointIdxSearch,
1074 pointSquaredDistance);
1076 unsigned int points_size = (
unsigned int)pointIdxSearch.size();
1077 Point *
points =
new Point[points_size];
1078 for (
unsigned int pt = 0; pt < pointIdxSearch.size(); pt++) {
1079 points[pt] = pts->points[pointIdxSearch[pt]];
1082 std::vector<Eigen::Vector3f> normals_vec(rotations);
1083 std::vector<float> normals_conf(rotations);
1085 for (
int i = 0; i < rotations; i++) {
1086 std::vector<Eigen::Vector3i>::const_iterator first =
1087 trip.begin() + i * n_planes;
1088 std::vector<Eigen::Vector3i>::const_iterator last =
1089 trip.begin() + (i + 1) * n_planes;
1090 std::vector<Eigen::Vector3i> triplets(first, last);
1092 for (
unsigned int pt = 0; pt < points_size; pt++) {
1093 points[pt].getVector3fMap() =
1094 rotMat[(n + i) % rotMat.size()] *
1095 points[pt].getVector3fMap();
1097 normals_conf[i] = normal_at_point(d1, d2,
points, points_size,
1098 n, triplets, conf_interv);
1100 for (
unsigned int pt = 0; pt < points_size; pt++) {
1101 points[pt] = pts->points[pointIdxSearch[pt]];
1103 normals_vec[i] = rotMatInv[(n + i) % rotMat.size()] *
1104 nls->points[n].getNormalVector3fMap();
1107 nls->points[n].getNormalVector3fMap() =
1108 normal_selection(rotations, normals_vec, normals_conf);
1120 void points_radius(
float radius) {
1123 nls->resize(pts->size());
1127 srand((
unsigned int)time(
NULL));
1130 pcl::KdTreeFLANN<Point> tree;
1131 tree.setInputCloud(pts);
1134 const int d1 = 2 * n_phi;
1135 const int d2 = n_phi + 1;
1138 std::vector<Eigen::Matrix3f> rotMat;
1139 std::vector<Eigen::Matrix3f> rotMatInv;
1140 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1150 std::vector<float> conf_interv(n_planes);
1151 for (
int i = 0; i < n_planes; i++) {
1152 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1155 std::vector<int> vecInt;
1156 generate_random_int_vector(vecInt, 1000000);
1159 std::vector<int> permutation(pts->size());
1160 for (
int i = 0; i < pts->size(); i++) {
1163 for (
int i = 0; i < pts->size(); i++) {
1164 int j = rand() % pts->size();
1165 int temp = permutation[i];
1166 permutation[i] = permutation[j];
1167 permutation[j] = temp;
1170 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1171 #pragma omp parallel for schedule(guided)
1173 for (
int per = 0; per < (int)pts->size(); per++) {
1174 int n = permutation[per];
1177 if (pts->points[n].getVector3fMap() == Eigen::Vector3f(0, 0, 0)) {
1182 std::vector<int> pointIdxSearch;
1183 std::vector<float> pointSquaredDistance;
1184 tree.radiusSearch(pts->points[n], radius, pointIdxSearch,
1185 pointSquaredDistance);
1187 if (pointIdxSearch.size() < lower_neighbor_bound_neighbors) {
1188 tree.nearestKSearch(pts->points[n],
1189 lower_neighbor_bound_neighbors,
1190 pointIdxSearch, pointSquaredDistance);
1194 std::vector<Eigen::Vector3i> trip;
1195 if (rotations <= 1) {
1196 list_of_triplets(trip, (
int)pointIdxSearch.size(), n_planes,
1199 list_of_triplets(trip, (
int)pointIdxSearch.size(),
1200 rotations * n_planes, vecInt);
1203 unsigned int points_size = (
unsigned int)pointIdxSearch.size();
1204 Point *
points =
new Point[points_size];
1205 for (
unsigned int pt = 0; pt < pointIdxSearch.size(); pt++) {
1206 points[pt] = pts->points[pointIdxSearch[pt]];
1209 std::vector<Eigen::Vector3f> normals_vec(rotations);
1210 std::vector<float> normals_conf(rotations);
1212 for (
int i = 0; i < rotations; i++) {
1213 std::vector<Eigen::Vector3i>::const_iterator first =
1214 trip.begin() + i * n_planes;
1215 std::vector<Eigen::Vector3i>::const_iterator last =
1216 trip.begin() + (i + 1) * n_planes;
1217 std::vector<Eigen::Vector3i> triplets(first, last);
1219 for (
unsigned int pt = 0; pt < points_size; pt++) {
1220 points[pt].getVector3fMap() =
1221 rotMat[(n + i) % rotMat.size()] *
1222 points[pt].getVector3fMap();
1224 normals_conf[i] = normal_at_point(d1, d2,
points, points_size,
1225 n, triplets, conf_interv);
1227 for (
unsigned int pt = 0; pt < points_size; pt++) {
1228 points[pt] = pts->points[pointIdxSearch[pt]];
1230 normals_vec[i] = rotMatInv[(n + i) % rotMat.size()] *
1231 nls->points[n].getNormalVector3fMap();
1233 nls->points[n].getNormalVector3fMap() =
1234 normal_selection(rotations, normals_vec, normals_conf);
1246 void unif_knn(
int neighbor_number) {
1249 nls->resize(pts->size());
1253 srand((
unsigned int)time(
NULL));
1256 pcl::KdTreeFLANN<Point> tree;
1257 tree.setInputCloud(pts);
1260 const int d1 = 2 * n_phi;
1261 const int d2 = n_phi + 1;
1264 std::vector<float> conf_interv(n_planes);
1265 for (
int i = 0; i < n_planes; i++) {
1266 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1270 std::vector<Eigen::Matrix3f> rotMat;
1271 std::vector<Eigen::Matrix3f> rotMatInv;
1272 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1282 std::vector<Eigen::Vector3f> points_rand;
1283 std::vector<int> vecInt;
1284 generate_random_int_vector(vecInt, 1000000);
1285 generate_random_points_vector(points_rand, 1000000);
1288 std::vector<int> permutation(pts->size());
1289 for (
int i = 0; i < pts->size(); i++) {
1292 for (
int i = 0; i < pts->size(); i++) {
1293 int j = rand() % pts->size();
1294 int temp = permutation[i];
1295 permutation[i] = permutation[j];
1296 permutation[j] = temp;
1299 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1300 #pragma omp parallel for schedule(guided)
1302 for (
int per = 0; per < (int)pts->size(); per++) {
1303 int n = permutation[per];
1307 if (pts->points[n].getVector3fMap() == Eigen::Vector3f(0, 0, 0)) {
1312 std::vector<int> pointIdxRadiusSearch;
1313 std::vector<float> pointRadiusSquaredDistance;
1314 tree.nearestKSearch(pts->points[n], neighbor_number,
1315 pointIdxRadiusSearch,
1316 pointRadiusSquaredDistance);
1319 for (
unsigned int i = 0; i < pointRadiusSquaredDistance.size();
1321 if (pointRadiusSquaredDistance[i] > radius) {
1322 radius = pointRadiusSquaredDistance[i];
1325 radius = sqrt(radius);
1327 float s_radius = radius / small_radius_factor;
1330 typename pcl::PointCloud<Point>::Ptr cloud_neighbors(
1331 new pcl::PointCloud<Point>);
1332 cloud_neighbors->resize(pointIdxRadiusSearch.size());
1333 for (
unsigned int i = 0; i < pointIdxRadiusSearch.size(); i++) {
1334 cloud_neighbors->points[i] =
1335 pts->points[pointIdxRadiusSearch[i]];
1337 pcl::KdTreeFLANN<Point> tree_neighbors;
1338 tree_neighbors.setInputCloud(cloud_neighbors);
1340 Point *
points =
new Point[neighbor_number];
1343 std::vector<Eigen::Vector3i> trip;
1344 generate_list_of_triplets(trip, rotations * n_planes, radius,
1345 s_radius, tree_neighbors, pts->points[n],
1346 points_rand, vecInt);
1348 std::vector<Eigen::Vector3f> normals_vec(rotations);
1349 std::vector<float> normals_conf(rotations);
1351 for (
int i = 0; i < rotations; i++) {
1352 std::vector<Eigen::Vector3i>::const_iterator first =
1353 trip.begin() + i * n_planes;
1354 std::vector<Eigen::Vector3i>::const_iterator last =
1355 trip.begin() + (i + 1) * n_planes;
1356 std::vector<Eigen::Vector3i> triplets(first, last);
1358 for (
unsigned int pt = 0; pt < neighbor_number; pt++) {
1359 points[pt] = pts->points[pointIdxRadiusSearch[pt]];
1360 points[pt].getVector3fMap() =
1361 rotMat[(n + i) % rotMat.size()] *
1362 points[pt].getVector3fMap();
1366 normal_at_point(d1, d2,
points, neighbor_number, n,
1367 triplets, conf_interv);
1368 normals_vec[i] = rotMatInv[(n + i) % rotMat.size()] *
1369 nls->points[n].getNormalVector3fMap();
1372 nls->points[n].getNormalVector3fMap() =
1373 normal_selection(rotations, normals_vec, normals_conf);
1385 void unif_radius(
float radius) {
1388 nls->resize(pts->size());
1392 srand((
unsigned int)time(
NULL));
1395 pcl::KdTreeFLANN<Point> tree;
1396 tree.setInputCloud(pts);
1399 const int d1 = 2 * n_phi;
1400 const int d2 = n_phi + 1;
1403 std::vector<float> conf_interv(n_planes);
1404 for (
int i = 0; i < n_planes; i++) {
1405 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1409 std::vector<Eigen::Matrix3f> rotMat;
1410 std::vector<Eigen::Matrix3f> rotMatInv;
1411 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1421 std::vector<Eigen::Vector3f> points_rand;
1422 std::vector<int> vecInt;
1423 generate_random_points_vector(points_rand, 1000000);
1424 generate_random_int_vector(vecInt, 1000000);
1427 std::vector<int> permutation(pts->size());
1428 for (
int i = 0; i < pts->size(); i++) {
1431 for (
int i = 0; i < pts->size(); i++) {
1432 int j = rand() % pts->size();
1433 int temp = permutation[i];
1434 permutation[i] = permutation[j];
1435 permutation[j] = temp;
1438 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1439 #pragma omp parallel for schedule(guided)
1441 for (
int per = 0; per < (int)pts->size(); per++) {
1442 int n = permutation[per];
1446 if (pts->points[n].getVector3fMap() == Eigen::Vector3f(0, 0, 0)) {
1451 std::vector<int> pointIdxRadiusSearch;
1452 std::vector<float> pointRadiusSquaredDistance;
1453 tree.radiusSearch(pts->points[n], radius, pointIdxRadiusSearch,
1454 pointRadiusSquaredDistance);
1456 float radius2 = radius;
1457 if (pointIdxRadiusSearch.size() < lower_neighbor_bound_neighbors) {
1459 tree.nearestKSearch(
1460 pts->points[n], lower_neighbor_bound_neighbors,
1461 pointIdxRadiusSearch, pointRadiusSquaredDistance);
1462 for (
unsigned int i = 0; i < pointRadiusSquaredDistance.size();
1464 if (pointRadiusSquaredDistance[i] > radius2) {
1465 radius2 = pointRadiusSquaredDistance[i];
1469 float s_radius = radius2 / small_radius_factor;
1472 typename pcl::PointCloud<Point>::Ptr cloud_neighbors(
1473 new pcl::PointCloud<Point>);
1474 cloud_neighbors->resize(pointIdxRadiusSearch.size());
1475 for (
unsigned int i = 0; i < pointIdxRadiusSearch.size(); i++) {
1476 cloud_neighbors->points[i] =
1477 pts->points[pointIdxRadiusSearch[i]];
1479 pcl::KdTreeFLANN<Point> tree_neighbors;
1480 tree_neighbors.setInputCloud(cloud_neighbors);
1482 unsigned int points_size =
1483 (
unsigned int)pointIdxRadiusSearch.size();
1484 Point *
points =
new Point[points_size];
1487 std::vector<Eigen::Vector3i> trip;
1488 generate_list_of_triplets(trip, rotations * n_planes, radius2,
1489 s_radius, tree_neighbors, pts->points[n],
1490 points_rand, vecInt);
1492 std::vector<Eigen::Vector3f> normals_vec(rotations);
1493 std::vector<float> normals_conf(rotations);
1495 for (
int i = 0; i < rotations; i++) {
1496 std::vector<Eigen::Vector3i>::const_iterator first =
1497 trip.begin() + i * n_planes;
1498 std::vector<Eigen::Vector3i>::const_iterator last =
1499 trip.begin() + (i + 1) * n_planes;
1500 std::vector<Eigen::Vector3i> triplets(first, last);
1502 for (
unsigned int pt = 0; pt < points_size; pt++) {
1503 points[pt] = pts->points[pointIdxRadiusSearch[pt]];
1504 points[pt].getVector3fMap() =
1505 rotMat[(n + i) % rotMat.size()] *
1506 points[pt].getVector3fMap();
1509 normals_conf[i] = normal_at_point(d1, d2,
points, points_size,
1510 n, triplets, conf_interv);
1512 nls->points[n].getNormalVector3fMap() =
1513 rotMatInv[(n + i) % rotMat.size()] *
1514 nls->points[n].getNormalVector3fMap();
1516 normals_vec[i] = nls->points[n].getNormalVector3fMap();
1519 nls->points[n].getNormalVector3fMap() =
1520 normal_selection(rotations, normals_vec, normals_conf);
1532 void cubes_knn(
int neighbor_number) {
1535 nls->resize(pts->size());
1539 srand((
unsigned int)time(
NULL));
1542 pcl::KdTreeFLANN<Point> tree;
1543 tree.setInputCloud(pts);
1546 const int d1 = 2 * n_phi;
1547 const int d2 = n_phi + 1;
1550 std::vector<float> conf_interv(n_planes);
1551 for (
int i = 0; i < n_planes; i++) {
1552 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1556 std::vector<Eigen::Matrix3f> rotMat;
1557 std::vector<Eigen::Matrix3f> rotMatInv;
1558 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1568 std::vector<int> cubes_idx;
1569 std::vector<int> vecInt;
1570 generate_cube_vector(cubes_idx, 1000000);
1571 generate_random_int_vector(vecInt, 1000000);
1574 std::vector<int> permutation(pts->size());
1575 for (
int i = 0; i < pts->size(); i++) {
1578 for (
int i = 0; i < pts->size(); i++) {
1579 int j = rand() % pts->size();
1580 int temp = permutation[i];
1581 permutation[i] = permutation[j];
1582 permutation[j] = temp;
1585 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1586 #pragma omp parallel for schedule(guided)
1588 for (
int per = 0; per < (int)pts->size(); per++) {
1589 int n = permutation[per];
1593 if (pts->points[n].getVector3fMap() == Eigen::Vector3f(0, 0, 0)) {
1598 std::vector<int> pointIdxRadiusSearch;
1599 std::vector<float> pointRadiusSquaredDistance;
1600 tree.nearestKSearch(pts->points[n], neighbor_number,
1601 pointIdxRadiusSearch,
1602 pointRadiusSquaredDistance);
1605 for (
unsigned int i = 0; i < pointRadiusSquaredDistance.size();
1607 if (pointRadiusSquaredDistance[i] > radius) {
1608 radius = pointRadiusSquaredDistance[i];
1611 radius = sqrt(radius);
1613 std::vector<int> *cubes =
1614 new std::vector<int>[n_cubes * n_cubes * n_cubes];
1615 Point *
points =
new Point[neighbor_number];
1616 std::vector<Eigen::Vector3i> triplets;
1618 std::vector<Eigen::Vector3f> normals_vec(rotations);
1619 std::vector<float> normals_conf(rotations);
1621 for (
int i = 0; i < rotations; i++) {
1622 assign_points_to_cubes(pointIdxRadiusSearch, cubes, radius,
1624 rotMat[(n + i) % rotMat.size()]);
1626 generate_cubes_triplets(triplets, cubes, cubes_idx, vecInt);
1630 normal_at_point(d1, d2,
points, neighbor_number, n,
1631 triplets, conf_interv);
1634 for (
unsigned int pt = 0; pt < neighbor_number; pt++) {
1635 points[pt] = pts->points[pointIdxRadiusSearch[pt]];
1637 normals_vec[i] = rotMatInv[(n + i) % rotMat.size()] *
1638 nls->points[n].getNormalVector3fMap();
1641 nls->points[n].getNormalVector3fMap() =
1642 normal_selection(rotations, normals_vec, normals_conf);
1655 void cubes_radius(
float radius) {
1658 nls->resize(pts->size());
1662 srand((
unsigned int)time(
NULL));
1665 pcl::KdTreeFLANN<Point> tree;
1666 tree.setInputCloud(pts);
1669 const int d1 = 2 * n_phi;
1670 const int d2 = n_phi + 1;
1673 std::vector<float> conf_interv(n_planes);
1674 for (
int i = 0; i < n_planes; i++) {
1675 conf_interv[i] = 2.f / std::sqrt(i + 1.f);
1679 std::vector<Eigen::Matrix3f> rotMat;
1680 std::vector<Eigen::Matrix3f> rotMatInv;
1681 generate_rotation_matrix(rotMat, rotMatInv, n_rot * 200);
1691 std::vector<int> cubes_idx;
1692 std::vector<int> vecInt;
1693 generate_cube_vector(cubes_idx, 1000000);
1694 generate_random_int_vector(vecInt, 1000000);
1697 std::vector<int> permutation(pts->size());
1698 for (
int i = 0; i < pts->size(); i++) {
1701 for (
int i = 0; i < pts->size(); i++) {
1702 int j = rand() % pts->size();
1703 int temp = permutation[i];
1704 permutation[i] = permutation[j];
1705 permutation[j] = temp;
1708 #if defined(_OPENMP) && defined(USE_OPENMP_FOR_NORMEST)
1709 #pragma omp parallel for schedule(guided)
1711 for (
int per = 0; per < (int)pts->size(); per++) {
1712 int n = permutation[per];
1716 if (pts->points[n].getVector3fMap() == Eigen::Vector3f(0, 0, 0)) {
1720 float radius2 = radius;
1723 std::vector<int> pointIdxRadiusSearch;
1724 std::vector<float> pointRadiusSquaredDistance;
1725 tree.radiusSearch(pts->points[n], radius, pointIdxRadiusSearch,
1726 pointRadiusSquaredDistance);
1728 if (pointIdxRadiusSearch.size() < lower_neighbor_bound_neighbors) {
1730 tree.nearestKSearch(
1731 pts->points[n], lower_neighbor_bound_neighbors,
1732 pointIdxRadiusSearch, pointRadiusSquaredDistance);
1733 for (
unsigned int i = 0; i < pointRadiusSquaredDistance.size();
1735 if (pointRadiusSquaredDistance[i] > radius2) {
1736 radius2 = pointRadiusSquaredDistance[i];
1741 std::vector<int> *cubes =
1742 new std::vector<int>[n_cubes * n_cubes * n_cubes];
1743 unsigned int points_size =
1744 (
unsigned int)pointIdxRadiusSearch.size();
1745 Point *
points =
new Point[points_size];
1747 std::vector<Eigen::Vector3i> triplets;
1749 std::vector<Eigen::Vector3f> normals_vec(rotations);
1750 std::vector<float> normals_conf(rotations);
1752 for (
int i = 0; i < rotations; i++) {
1753 assign_points_to_cubes(pointIdxRadiusSearch, cubes, radius2,
1755 rotMat[(i + n) % rotMat.size()]);
1756 generate_cubes_triplets(triplets, cubes, cubes_idx, vecInt);
1758 normals_conf[i] = normal_at_point(d1, d2,
points, points_size,
1759 n, triplets, conf_interv);
1760 for (
unsigned int pt = 0; pt < points_size; pt++) {
1761 points[pt] = pts->points[pointIdxRadiusSearch[pt]];
1763 normals_vec[i] = rotMatInv[(i + n) % rotMat.size()] *
1764 nls->points[n].getNormalVector3fMap();
1767 nls->points[n].getNormalVector3fMap() =
1768 normal_selection(rotations, normals_vec, normals_conf);
Class grouping different variants of the algorithm Class using a dependency to Point Cloud Library.
int normal_selection_mode() const
pcl::PointCloud< Normal >::Ptr normal_cloud() const
int & normal_selection_mode()
pcl::PointCloud< Point >::Ptr point_cloud() const
int number_of_planes() const
float & cluster_angle_rad()
void estimate(int method=POINTS, int neighborhood_type=KNN, float neighborhood_size=200)
int & minimal_neighbor_number_for_range_search()
PCL_Normal_Estimator(typename pcl::PointCloud< Point >::Ptr points, typename pcl::PointCloud< Normal >::Ptr normals)
Constructor.
int rotation_number() const
float small_radius_fact() const
pcl::PointCloud< Point >::Ptr & point_cloud()
int minimal_neighbor_number_for_range_search() const
float cluster_angle_rad() const
int number_of_cubes() const
float & small_radius_fact()
pcl::PointCloud< Normal >::Ptr & normal_cloud()
__host__ __device__ float dot(float2 a, float2 b)
QTextStream & endl(QTextStream &stream)
MiniVec< float, N > floor(const MiniVec< float, N > &a)
Eigen::Matrix< Index, 3, 1 > Vector3i