@@ -100,64 +100,127 @@ void Registration::apply(const Frame *rgb, const Frame *depth, Frame *undistorte
100100 const int *map_dist = distort_map;
101101 const float *map_x = depth_to_color_map_x;
102102 const int *map_yi = depth_to_color_map_yi;
103+
103104 const int size_depth = 512 * 424 ;
104- const int size_color = 1920 * 1080 * 3 ;
105+ const int size_color = 1920 * 1080 ;
105106 const float color_cx = color.cx + 0 .5f ; // 0.5f added for later rounding
106107
108+ // size of filter map with a border of filter_height_half on top and bottom so that no check for borders is needed.
109+ // since the color image is wide angle no border to the sides is needed.
110+ const int size_filter_map = size_color + 1920 * filter_height_half * 2 ;
111+ // offset to the important data
112+ const int offset_filter_map = 1920 * filter_height_half;
113+
114+ // map for storing the min z values used for each color pixel
115+ float *filter_map = new float [size_filter_map];
116+ // pointer to the beginning of the important data
117+ float *p_filter_map = filter_map + offset_filter_map;
118+
119+ // map for storing the color offest for each depth pixel
120+ int *depth_to_c_off = new int [size_depth];
121+ int *map_c_off = depth_to_c_off;
122+
123+ // initializing the depth_map with values outside of the Kinect2 range
124+ for (float *it = filter_map, *end = filter_map + size_filter_map; it != end; ++it){
125+ *it = 65536 .0f ;
126+ }
127+
107128 // iterating over all pixels from undistorted depth and registered color image
108- // the three maps have the same structure as the images, so their pointers are increased each iteration as well
109- for (int i = 0 ; i < size_depth; ++i, ++registered_data, ++ undistorted_data, ++map_dist, ++map_x, ++map_yi) {
129+ // the four maps have the same structure as the images, so their pointers are increased each iteration as well
130+ for (int i = 0 ; i < size_depth; ++i, ++undistorted_data, ++map_dist, ++map_x, ++map_yi, ++map_c_off) {
110131 // getting index of distorted depth pixel
111132 const int index = *map_dist;
112133
113134 // check if distorted depth pixel is outside of the depth image
114135 if (index < 0 ){
136+ *map_c_off = -1 ;
115137 *undistorted_data = 0 ;
116- *registered_data = 0 ;
117- *++registered_data = 0 ;
118- *++registered_data = 0 ;
119138 continue ;
120139 }
121140
122141 // getting depth value for current pixel
123- const float z_raw = depth_data[index];
124- *undistorted_data = z_raw ;
142+ const float z = depth_data[index];
143+ *undistorted_data = z ;
125144
126145 // checking for invalid depth value
127- if (z_raw <= 0 .0f ) {
128- *registered_data = 0 ;
129- *++registered_data = 0 ;
130- *++registered_data = 0 ;
146+ if (z <= 0 .0f ){
147+ *map_c_off = -1 ;
131148 continue ;
132149 }
133150
134151 // calculating x offset for rgb image based on depth value
135- const float rx = (*map_x + (color.shift_m / z_raw )) * color.fx + color_cx;
152+ const float rx = (*map_x + (color.shift_m / z )) * color.fx + color_cx;
136153 const int cx = rx; // same as round for positive numbers (0.5f was already added to color_cx)
137154 // getting y offset for depth image
138155 const int cy = *map_yi;
139156 // combining offsets
140- const int c_off = cx * 3 + cy;
157+ const int c_off = cx + cy * 1920 ;
141158
142159 // check if c_off is outside of rgb image
143160 // checking rx/cx is not needed because the color image is much wider then the depth image
144- if (c_off < 0 || c_off >= size_color) {
161+ if (c_off < 0 || c_off >= size_color){
162+ *map_c_off = -1 ;
163+ continue ;
164+ }
165+
166+ // setting a window around the filter map pixel corresponding to the color pixel with the current z value
167+ int yi = (cy - filter_height_half) * 1920 + cx - filter_width_half; // index of first pixel to set
168+ for (int r = -filter_height_half; r <= filter_height_half; ++r, yi += 1920 ) // index increased by a full row each iteration
169+ {
170+ float *it = p_filter_map + yi;
171+ for (int c = -filter_width_half; c <= filter_width_half; ++c, ++it)
172+ {
173+ // only set if the current z is smaller
174+ if (z < *it)
175+ *it = z;
176+ }
177+ }
178+
179+ // saving the offset for later
180+ *map_c_off = c_off;
181+ }
182+
183+ // reseting the pointers to the beginning
184+ undistorted_data = (float *)undistorted->data ;
185+ map_c_off = depth_to_c_off;
186+
187+ // run through all registered color pixels and set them based on filter results
188+ for (int i = 0 ; i < size_depth; ++i, ++registered_data, ++map_c_off, ++undistorted_data){
189+ const int c_off = *map_c_off;
190+
191+ // check if offset is out of image
192+ if (c_off < 0 ){
193+ *registered_data = 0 ;
194+ *++registered_data = 0 ;
195+ *++registered_data = 0 ;
196+ continue ;
197+ }
198+
199+ const float min_z = p_filter_map[c_off];
200+ const float z = *undistorted_data;
201+
202+ // check for allowed depth noise
203+ if ((z - min_z) / z > filter_tolerance) {
145204 *registered_data = 0 ;
146205 *++registered_data = 0 ;
147206 *++registered_data = 0 ;
148207 continue ;
149208 }
150209
151210 // Setting RGB or registered image
152- const unsigned char *rgb_data = rgb->data + c_off;
211+ const unsigned char *rgb_data = rgb->data + c_off * 3 ;
153212 *registered_data = *rgb_data;
154213 *++registered_data = *++rgb_data;
155214 *++registered_data = *++rgb_data;
156215 }
216+
217+ // delete the temporary maps
218+ delete[] filter_map;
219+ delete[] depth_to_c_off;
157220}
158221
159222Registration::Registration (Freenect2Device::IrCameraParams depth_p, Freenect2Device::ColorCameraParams rgb_p):
160- depth (depth_p), color(rgb_p)
223+ depth (depth_p), color(rgb_p), filter_width_half( 2 ), filter_height_half( 1 ), filter_tolerance( 0 . 01f )
161224{
162225 float mx, my;
163226 int ix, iy, index;
@@ -186,7 +249,7 @@ Registration::Registration(Freenect2Device::IrCameraParams depth_p, Freenect2Dev
186249 *map_x++ = rx;
187250 *map_y++ = ry;
188251 // compute the y offset to minimize later computations
189- *map_yi++ = roundf (ry) * 1920 * 3 ;
252+ *map_yi++ = roundf (ry);
190253 }
191254 }
192255}
0 commit comments