46 RangeImage::asinLookUp (
float value)
48 return (asin_lookup_table[
50 static_cast<float> (
pcl_lrintf ( (static_cast<float> (lookup_table_size) / 2.0f) * value)) +
51 static_cast<float> (lookup_table_size) / 2.0f)]);
56 RangeImage::atan2LookUp (
float y,
float x)
59 if (fabsf (x) < fabsf (y))
61 ret = atan_lookup_table[
63 static_cast<float> (
pcl_lrintf ( (static_cast<float> (lookup_table_size) / 2.0f) * (x / y))) +
64 static_cast<float> (lookup_table_size) / 2.0f)];
65 ret =
static_cast<float> (x*y > 0 ? M_PI/2-ret : -M_PI/2-ret);
68 ret = atan_lookup_table[
70 static_cast<float> (
pcl_lrintf ( (static_cast<float> (lookup_table_size) / 2.0f) * (y / x))) +
71 static_cast<float> (lookup_table_size)/2.0f)];
73 ret =
static_cast<float> (y < 0 ? ret-M_PI : ret+M_PI);
80 RangeImage::cosLookUp (
float value)
82 int cell_idx =
static_cast<int> (
pcl_lrintf ( (static_cast<float> (lookup_table_size)-1) * fabsf (value) / (2.0f * M_PI)));
83 return (cos_lookup_table[cell_idx]);
87 template <
typename Po
intCloudType>
void
89 float max_angle_width,
float max_angle_height,
91 float noise_level,
float min_range,
int border_size)
93 createFromPointCloud (point_cloud, angular_resolution, angular_resolution, max_angle_width, max_angle_height,
94 sensor_pose, coordinate_frame, noise_level, min_range, border_size);
98 template <
typename Po
intCloudType>
void
100 float angular_resolution_x,
float angular_resolution_y,
101 float max_angle_width,
float max_angle_height,
103 float noise_level,
float min_range,
int border_size)
107 width =
static_cast<uint32_t
> (
pcl_lrint (floor (max_angle_width*angular_resolution_x_reciprocal_)));
108 height =
static_cast<uint32_t
> (
pcl_lrint (floor (max_angle_height*angular_resolution_y_reciprocal_)));
110 int full_width =
static_cast<int> (
pcl_lrint (floor (
pcl::deg2rad (360.0f)*angular_resolution_x_reciprocal_))),
111 full_height = static_cast<int> (
pcl_lrint (floor (
pcl::deg2rad (180.0f)*angular_resolution_y_reciprocal_)));
112 image_offset_x_ = (full_width -
static_cast<int> (
width) )/2;
113 image_offset_y_ = (full_height-
static_cast<int> (
height))/2;
117 to_world_system_ = sensor_pose * to_world_system_;
119 to_range_image_system_ = to_world_system_.inverse (Eigen::Isometry);
124 points.resize (size, unobserved_point);
127 doZBuffer (point_cloud, noise_level, min_range, top, right, bottom, left);
129 cropImage (border_size, top, right, bottom, left);
135 template <
typename Po
intCloudType>
void
137 const Eigen::Vector3f& point_cloud_center,
float point_cloud_radius,
139 float noise_level,
float min_range,
int border_size)
142 sensor_pose, coordinate_frame, noise_level, min_range, border_size);
146 template <
typename Po
intCloudType>
void
148 float angular_resolution_x,
float angular_resolution_y,
149 const Eigen::Vector3f& point_cloud_center,
float point_cloud_radius,
151 float noise_level,
float min_range,
int border_size)
158 if ((point_cloud_center-sensor_pose.translation()).norm() <= point_cloud_radius) {
161 sensor_pose, coordinate_frame, noise_level, min_range, border_size);
168 to_world_system_ = sensor_pose * to_world_system_;
169 to_range_image_system_ = to_world_system_.inverse (Eigen::Isometry);
171 float max_angle_size =
getMaxAngleSize (sensor_pose, point_cloud_center, point_cloud_radius);
172 int pixel_radius_x =
pcl_lrint (ceil (0.5f*max_angle_size*angular_resolution_x_reciprocal_)),
173 pixel_radius_y =
pcl_lrint (ceil (0.5f*max_angle_size*angular_resolution_y_reciprocal_));
174 width = 2*pixel_radius_x;
175 height = 2*pixel_radius_y;
178 image_offset_x_ = image_offset_y_ = 0;
179 int center_pixel_x, center_pixel_y;
180 getImagePoint (point_cloud_center, center_pixel_x, center_pixel_y);
181 image_offset_x_ = (std::max) (0, center_pixel_x-pixel_radius_x);
182 image_offset_y_ = (std::max) (0, center_pixel_y-pixel_radius_y);
188 doZBuffer (point_cloud, noise_level, min_range, top, right, bottom, left);
190 cropImage (border_size, top, right, bottom, left);
196 template <
typename Po
intCloudTypeWithViewpo
ints>
void
198 float angular_resolution,
199 float max_angle_width,
float max_angle_height,
201 float noise_level,
float min_range,
int border_size)
204 max_angle_width, max_angle_height, coordinate_frame,
205 noise_level, min_range, border_size);
209 template <
typename Po
intCloudTypeWithViewpo
ints>
void
211 float angular_resolution_x,
float angular_resolution_y,
212 float max_angle_width,
float max_angle_height,
214 float noise_level,
float min_range,
int border_size)
217 Eigen::Affine3f sensor_pose =
static_cast<Eigen::Affine3f
> (Eigen::Translation3f (average_viewpoint));
218 createFromPointCloud (point_cloud, angular_resolution_x, angular_resolution_y, max_angle_width, max_angle_height,
219 sensor_pose, coordinate_frame, noise_level, min_range, border_size);
223 template <
typename Po
intCloudType>
void
224 RangeImage::doZBuffer (
const PointCloudType& point_cloud,
float noise_level,
float min_range,
int& top,
int& right,
int& bottom,
int& left)
226 typedef typename PointCloudType::PointType PointType2;
230 int* counters =
new int[
size];
235 float x_real, y_real, range_of_current_point;
243 this->
getImagePoint (current_point, x_real, y_real, range_of_current_point);
246 if (range_of_current_point < min_range|| !
isInImage (x, y))
254 int neighbor_x[4], neighbor_y[4];
255 neighbor_x[0]=floor_x; neighbor_y[0]=floor_y;
256 neighbor_x[1]=floor_x; neighbor_y[1]=ceil_y;
257 neighbor_x[2]=ceil_x; neighbor_y[2]=floor_y;
258 neighbor_x[3]=ceil_x; neighbor_y[3]=ceil_y;
261 for (
int i=0; i<4; ++i)
263 int n_x=neighbor_x[i], n_y=neighbor_y[i];
265 if (n_x==x && n_y==y)
269 int neighbor_array_pos = n_y*
width + n_x;
270 if (counters[neighbor_array_pos]==0)
272 float& neighbor_range =
points[neighbor_array_pos].range;
273 neighbor_range = (
pcl_isinf (neighbor_range) ? range_of_current_point : (std::min) (neighbor_range, range_of_current_point));
274 top= (std::min) (top, n_y); right= (std::max) (right, n_x); bottom= (std::max) (bottom, n_y); left= (std::min) (left, n_x);
281 int arrayPos = y*
width + x;
282 float& range_at_image_point =
points[arrayPos].range;
283 int& counter = counters[arrayPos];
284 bool addCurrentPoint=
false, replace_with_current_point=
false;
288 replace_with_current_point =
true;
292 if (range_of_current_point < range_at_image_point-noise_level)
294 replace_with_current_point =
true;
296 else if (fabs (range_of_current_point-range_at_image_point)<=noise_level)
298 addCurrentPoint =
true;
302 if (replace_with_current_point)
305 range_at_image_point = range_of_current_point;
306 top= (std::min) (top, y); right= (std::max) (right, x); bottom= (std::max) (bottom, y); left= (std::min) (left, x);
309 else if (addCurrentPoint)
312 range_at_image_point += (range_of_current_point-range_at_image_point)/counter;
323 Eigen::Vector3f point (x, y, z);
339 float image_x_float, image_y_float;
341 real2DToInt2D (image_x_float, image_y_float, image_x, image_y);
348 Eigen::Vector3f transformedPoint = to_range_image_system_ * point;
349 range = transformedPoint.norm ();
350 float angle_x = atan2LookUp (transformedPoint[0], transformedPoint[2]),
351 angle_y = asinLookUp (transformedPoint[1]/range);
361 float image_x_float, image_y_float;
363 real2DToInt2D (image_x_float, image_y_float, image_x, image_y);
378 float image_x_float, image_y_float;
380 real2DToInt2D (image_x_float, image_y_float, image_x, image_y);
387 int image_x, image_y;
391 point_in_image = unobserved_point;
393 point_in_image =
getPoint (image_x, image_y);
401 int image_x, image_y;
405 return -std::numeric_limits<float>::infinity ();
409 if (image_point_range > 0.0f)
410 return std::numeric_limits<float>::infinity ();
412 return -std::numeric_limits<float>::infinity ();
414 return image_point_range - range;
421 image_x = (angle_x*cosLookUp (angle_y) +
static_cast<float> (M_PI))*angular_resolution_x_reciprocal_ -
static_cast<float> (image_offset_x_);
422 image_y = (angle_y + 0.5f*
static_cast<float> (M_PI))*angular_resolution_y_reciprocal_ -
static_cast<float> (image_offset_y_);
437 return (x >= 0 && x < static_cast<int> (
width) && y >= 0 && y < static_cast<int> (
height));
476 return unobserved_point;
532 point =
getPoint (image_x, image_y).getVector3fMap ();
539 point =
getPoint (index).getVector3fMap ();
543 const Eigen::Map<const Eigen::Vector3f>
546 return getPoint (x, y).getVector3fMap ();
550 const Eigen::Map<const Eigen::Vector3f>
553 return getPoint (index).getVector3fMap ();
560 float angle_x, angle_y;
564 float cosY = cosf (angle_y);
565 point = Eigen::Vector3f (range * sinf (angle_x) * cosY, range * sinf (angle_y), range * cosf (angle_x)*cosY);
566 point = to_world_system_ * point;
581 Eigen::Vector3f tmp_point;
583 point.x=tmp_point[0]; point.y=tmp_point[1]; point.z=tmp_point[2];
598 angle_y = (image_y+
static_cast<float> (image_offset_y_))*angular_resolution_y_ - 0.5f*
static_cast<float> (M_PI);
599 float cos_angle_y = cosf (angle_y);
600 angle_x = (cos_angle_y==0.0f ? 0.0f : ( (image_x+
static_cast<float> (image_offset_x_))*angular_resolution_x_ -
static_cast<float> (M_PI))/cos_angle_y);
608 return -std::numeric_limits<float>::infinity ();
616 return -std::numeric_limits<float>::infinity ();
618 float r1 = (std::min) (point1.
range, point2.
range),
620 float impact_angle =
static_cast<float> (0.5f * M_PI);
633 float cos_impact_angle = (r2Sqr + dSqr - r1Sqr)/ (2.0f*r2*d);
634 cos_impact_angle = (std::max) (0.0f, (std::min) (1.0f, cos_impact_angle));
635 impact_angle = acosf (cos_impact_angle);
639 impact_angle = -impact_angle;
650 return -std::numeric_limits<float>::infinity ();
651 float ret = 1.0f - float (fabs (impact_angle)/ (0.5f*M_PI));
652 if (impact_angle < 0.0f)
664 return -std::numeric_limits<float>::infinity ();
669 const Eigen::Vector3f
672 return Eigen::Vector3f (to_world_system_ (0,3), to_world_system_ (1,3), to_world_system_ (2,3));
679 angle_change_x = angle_change_y = -std::numeric_limits<float>::infinity ();
682 Eigen::Vector3f point;
688 Eigen::Vector3f transformed_left;
690 transformed_left = Eigen::Vector3f (0.0f, 0.0f, -1.0f);
693 Eigen::Vector3f left;
695 transformed_left = - (transformation * left);
697 transformed_left[1] = 0.0f;
698 transformed_left.normalize ();
701 Eigen::Vector3f transformed_right;
703 transformed_right = Eigen::Vector3f (0.0f, 0.0f, 1.0f);
706 Eigen::Vector3f right;
708 transformed_right = transformation * right;
710 transformed_right[1] = 0.0f;
711 transformed_right.normalize ();
713 angle_change_x = transformed_left.dot (transformed_right);
714 angle_change_x = (std::max) (0.0f, (std::min) (1.0f, angle_change_x));
715 angle_change_x = acosf (angle_change_x);
720 Eigen::Vector3f transformed_top;
722 transformed_top = Eigen::Vector3f (0.0f, 0.0f, -1.0f);
727 transformed_top = - (transformation * top);
729 transformed_top[0] = 0.0f;
730 transformed_top.normalize ();
733 Eigen::Vector3f transformed_bottom;
735 transformed_bottom = Eigen::Vector3f (0.0f, 0.0f, 1.0f);
738 Eigen::Vector3f bottom;
740 transformed_bottom = transformation * bottom;
742 transformed_bottom[0] = 0.0f;
743 transformed_bottom.normalize ();
745 angle_change_y = transformed_top.dot (transformed_bottom);
746 angle_change_y = (std::max) (0.0f, (std::min) (1.0f, angle_change_y));
747 angle_change_y = acosf (angle_change_y);
784 return 2.0f * asinf (radius/ (viewer_pose.translation ()-center).norm ());
791 return Eigen::Vector3f (point.x, point.y, point.z);
800 float weight_sum = 1.0f;
804 if (average_point.
range>0.0f)
807 average_point.x = average_point.y = average_point.z = average_point.
range = 0.0f;
811 Vector4fMap average_point_eigen = average_point.getVector4fMap ();
813 for (
int step=1; step<no_of_points; ++step)
816 x2+=delta_x; y2+=delta_y;
820 average_point_eigen+=p.getVector4fMap (); average_point.
range+=p.
range;
823 if (weight_sum<= 0.0f)
825 average_point = unobserved_point;
828 float normalization_factor = 1.0f/weight_sum;
829 average_point_eigen *= normalization_factor;
830 average_point.
range *= normalization_factor;
839 return -std::numeric_limits<float>::infinity ();
845 return std::numeric_limits<float>::infinity ();
853 float average_pixel_distance = 0.0f;
855 for (
int i=0; i<max_steps; ++i)
857 int x1=x+i*offset_x, y1=y+i*offset_y;
858 int x2=x+ (i+1)*offset_x, y2=y+ (i+1)*offset_y;
864 return pixel_distance;
870 average_pixel_distance += sqrtf (pixel_distance);
872 average_pixel_distance /= weight;
874 return average_pixel_distance;
882 return -std::numeric_limits<float>::infinity ();
884 int no_of_nearest_neighbors =
static_cast<int> (pow (static_cast<double> ( (radius + 1.0)), 2.0));
885 Eigen::Vector3f normal;
887 return -std::numeric_limits<float>::infinity ();
897 for (
int y2=y-radius; y2<=y+radius; y2+=step_size)
899 for (
int x2=x-radius; x2<=x+radius; x2+=step_size)
906 vector_average.
add (Eigen::Vector3f (point.x, point.y, point.z));
911 Eigen::Vector3f eigen_values, eigen_vector2, eigen_vector3;
912 vector_average.
doPCA (eigen_values, normal, eigen_vector2, eigen_vector3);
924 return -std::numeric_limits<float>::infinity ();
925 float ret = 1.0f -
static_cast<float> ( (impact_angle / (0.5f * M_PI)));
933 int no_of_nearest_neighbors, Eigen::Vector3f& normal,
int step_size)
const
935 return getNormalForClosestNeighbors (x, y, radius, Eigen::Vector3f (point.x, point.y, point.z), no_of_nearest_neighbors, normal, NULL, step_size);
944 int no_of_nearest_neighbors =
static_cast<int> (pow (static_cast<double> (radius + 1.0), 2.0));
950 struct NeighborWithDistance
954 bool operator < (
const NeighborWithDistance& other)
const {
return distance<other.distance;}
961 float& max_closest_neighbor_distance_squared,
962 Eigen::Vector3f& normal, Eigen::Vector3f& mean, Eigen::Vector3f& eigen_values,
963 Eigen::Vector3f* normal_all_neighbors, Eigen::Vector3f* mean_all_neighbors,
964 Eigen::Vector3f* eigen_values_all_neighbors)
const
966 max_closest_neighbor_distance_squared=0.0f;
967 normal.setZero (); mean.setZero (); eigen_values.setZero ();
968 if (normal_all_neighbors!=NULL)
969 normal_all_neighbors->setZero ();
970 if (mean_all_neighbors!=NULL)
971 mean_all_neighbors->setZero ();
972 if (eigen_values_all_neighbors!=NULL)
973 eigen_values_all_neighbors->setZero ();
975 int blocksize =
static_cast<int> (pow (static_cast<double> ( (2.0 * radius + 1.0)), 2.0));
978 given_point.x=point[0]; given_point.y=point[1]; given_point.z=point[2];
980 std::vector<NeighborWithDistance> ordered_neighbors (blocksize);
981 int neighbor_counter = 0;
982 for (
int y2=y-radius; y2<=y+radius; y2+=step_size)
984 for (
int x2=x-radius; x2<=x+radius; x2+=step_size)
988 NeighborWithDistance& neighbor_with_distance = ordered_neighbors[neighbor_counter];
989 neighbor_with_distance.neighbor = &
getPoint (x2, y2);
994 no_of_closest_neighbors = (std::min) (neighbor_counter, no_of_closest_neighbors);
996 std::sort (ordered_neighbors.begin (), ordered_neighbors.begin () + neighbor_counter);
1000 max_closest_neighbor_distance_squared = ordered_neighbors[no_of_closest_neighbors-1].distance;
1002 float max_distance_squared = max_closest_neighbor_distance_squared*4.0f;
1008 for (neighbor_idx=0; neighbor_idx<neighbor_counter; ++neighbor_idx)
1010 if (ordered_neighbors[neighbor_idx].
distance > max_distance_squared)
1013 vector_average.
add (ordered_neighbors[neighbor_idx].
neighbor->getVector3fMap ());
1019 Eigen::Vector3f eigen_vector2, eigen_vector3;
1020 vector_average.
doPCA (eigen_values, normal, eigen_vector2, eigen_vector3);
1021 Eigen::Vector3f viewing_direction = (
getSensorPos ()-point).normalized ();
1022 if (normal.dot (viewing_direction) < 0.0f)
1024 mean = vector_average.
getMean ();
1026 if (normal_all_neighbors==NULL)
1030 for (
int neighbor_idx2=neighbor_idx; neighbor_idx2<neighbor_counter; ++neighbor_idx2)
1031 vector_average.
add (ordered_neighbors[neighbor_idx2].neighbor->getVector3fMap ());
1033 vector_average.
doPCA (*eigen_values_all_neighbors, *normal_all_neighbors, eigen_vector2, eigen_vector3);
1035 if (normal_all_neighbors->dot (viewing_direction) < 0.0f)
1036 *normal_all_neighbors *= -1.0f;
1037 *mean_all_neighbors = vector_average.
getMean ();
1050 return -std::numeric_limits<float>::infinity ();
1052 int blocksize =
static_cast<int> (pow (static_cast<double> (2.0 * radius + 1.0), 2.0));
1053 std::vector<float> neighbor_distances (blocksize);
1054 int neighbor_counter = 0;
1055 for (
int y2=y-radius; y2<=y+radius; y2+=step_size)
1057 for (
int x2=x-radius; x2<=x+radius; x2+=step_size)
1059 if (!
isValid (x2, y2) || (x2==x&&y2==y))
1062 float& neighbor_distance = neighbor_distances[neighbor_counter++];
1066 std::sort (neighbor_distances.begin (), neighbor_distances.begin () + neighbor_counter);
1068 n = (std::min) (neighbor_counter, n);
1069 return neighbor_distances[n-1];
1076 Eigen::Vector3f& normal, Eigen::Vector3f* point_on_plane,
int step_size)
const
1078 Eigen::Vector3f mean, eigen_values;
1079 float used_squared_max_distance;
1080 bool ret =
getSurfaceInformation (x, y, radius, point, no_of_nearest_neighbors, step_size, used_squared_max_distance,
1081 normal, mean, eigen_values);
1085 if (point_on_plane != NULL)
1086 *point_on_plane = (normal.dot (mean) - normal.dot (point))*normal + point;
1097 for (
int y2=y-radius; y2<=y+radius; y2+=step_size)
1099 for (
int x2=x-radius; x2<=x+radius; x2+=step_size)
1106 vector_average.
add (Eigen::Vector3f (point.x, point.y, point.z));
1111 Eigen::Vector3f eigen_values;
1112 vector_average.
doPCA (eigen_values);
1113 return eigen_values[0]/eigen_values.sum ();
1118 template <
typename Po
intCloudTypeWithViewpo
ints> Eigen::Vector3f
1121 Eigen::Vector3f average_viewpoint (0,0,0);
1122 int point_counter = 0;
1123 for (
unsigned int point_idx=0; point_idx<point_cloud.points.size (); ++point_idx)
1125 const typename PointCloudTypeWithViewpoints::PointType& point = point_cloud.points[point_idx];
1128 average_viewpoint[0] += point.vp_x;
1129 average_viewpoint[1] += point.vp_y;
1130 average_viewpoint[2] += point.vp_z;
1133 average_viewpoint /= point_counter;
1135 return average_viewpoint;
1152 viewing_direction = (point-
getSensorPos ()).normalized ();
1159 Eigen::Affine3f transformation;
1161 return transformation;
1168 Eigen::Vector3f viewing_direction = (point-
getSensorPos ()).normalized ();
1176 Eigen::Vector3f viewing_direction = (point-
getSensorPos ()).normalized ();
1184 angular_resolution_x_ = angular_resolution_y_ = angular_resolution;
1185 angular_resolution_x_reciprocal_ = angular_resolution_y_reciprocal_ = 1.0f / angular_resolution;
1192 angular_resolution_x_ = angular_resolution_x;
1193 angular_resolution_x_reciprocal_ = 1.0f / angular_resolution_x_;
1194 angular_resolution_y_ = angular_resolution_y;
1195 angular_resolution_y_reciprocal_ = 1.0f / angular_resolution_y_;
1201 to_range_image_system_ = to_range_image_system;
1202 to_world_system_ = to_range_image_system_.inverse ();
1208 angular_resolution_x = angular_resolution_x_;
1209 angular_resolution_y = angular_resolution_y_;