@@ -84,80 +84,149 @@ void Registration::apply( int dx, int dy, float dz, float& cx, float &cy) const
84
84
cx = rx * color.fx + color.cx ;
85
85
}
86
86
87
- void Registration::apply (const Frame *rgb, const Frame *depth, Frame *undistorted, Frame *registered) const
87
+ void Registration::apply (const Frame *rgb, const Frame *depth, Frame *undistorted, Frame *registered, const bool enable_filter ) const
88
88
{
89
89
// Check if all frames are valid and have the correct size
90
90
if (!undistorted || !rgb || !registered ||
91
- rgb->width != 1920 || rgb->height != 1080 || rgb->bytes_per_pixel != 3 ||
91
+ rgb->width != 1920 || rgb->height != 1080 || rgb->bytes_per_pixel != 4 ||
92
92
depth->width != 512 || depth->height != 424 || depth->bytes_per_pixel != 4 ||
93
93
undistorted->width != 512 || undistorted->height != 424 || undistorted->bytes_per_pixel != 4 ||
94
- registered->width != 512 || registered->height != 424 || registered->bytes_per_pixel != 3 )
94
+ registered->width != 512 || registered->height != 424 || registered->bytes_per_pixel != 4 )
95
95
return ;
96
96
97
97
const float *depth_data = (float *)depth->data ;
98
+ const unsigned int *rgb_data = (unsigned int *)rgb->data ;
98
99
float *undistorted_data = (float *)undistorted->data ;
99
- unsigned char *registered_data = registered->data ;
100
+ unsigned int *registered_data = ( unsigned int *) registered->data ;
100
101
const int *map_dist = distort_map;
101
102
const float *map_x = depth_to_color_map_x;
102
103
const int *map_yi = depth_to_color_map_yi;
104
+
103
105
const int size_depth = 512 * 424 ;
104
- const int size_color = 1920 * 1080 * 3 ;
106
+ const int size_color = 1920 * 1080 ;
105
107
const float color_cx = color.cx + 0 .5f ; // 0.5f added for later rounding
106
108
109
+ // size of filter map with a border of filter_height_half on top and bottom so that no check for borders is needed.
110
+ // since the color image is wide angle no border to the sides is needed.
111
+ const int size_filter_map = size_color + 1920 * filter_height_half * 2 ;
112
+ // offset to the important data
113
+ const int offset_filter_map = 1920 * filter_height_half;
114
+
115
+ // map for storing the min z values used for each color pixel
116
+ float *filter_map = NULL ;
117
+ // pointer to the beginning of the important data
118
+ float *p_filter_map = NULL ;
119
+
120
+ // map for storing the color offest for each depth pixel
121
+ int *depth_to_c_off = new int [size_depth];
122
+ int *map_c_off = depth_to_c_off;
123
+
124
+ // initializing the depth_map with values outside of the Kinect2 range
125
+ if (enable_filter){
126
+ filter_map = new float [size_filter_map];
127
+ p_filter_map = filter_map + offset_filter_map;
128
+
129
+ for (float *it = filter_map, *end = filter_map + size_filter_map; it != end; ++it){
130
+ *it = 65536 .0f ;
131
+ }
132
+ }
133
+
107
134
// 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) {
135
+ // the four maps have the same structure as the images, so their pointers are increased each iteration as well
136
+ for (int i = 0 ; i < size_depth; ++i, ++undistorted_data, ++map_dist, ++map_x, ++map_yi, ++map_c_off) {
110
137
// getting index of distorted depth pixel
111
138
const int index = *map_dist;
112
139
113
140
// check if distorted depth pixel is outside of the depth image
114
141
if (index < 0 ){
142
+ *map_c_off = -1 ;
115
143
*undistorted_data = 0 ;
116
- *registered_data = 0 ;
117
- *++registered_data = 0 ;
118
- *++registered_data = 0 ;
119
144
continue ;
120
145
}
121
146
122
147
// getting depth value for current pixel
123
- const float z_raw = depth_data[index];
124
- *undistorted_data = z_raw ;
148
+ const float z = depth_data[index];
149
+ *undistorted_data = z ;
125
150
126
151
// checking for invalid depth value
127
- if (z_raw <= 0 .0f ) {
128
- *registered_data = 0 ;
129
- *++registered_data = 0 ;
130
- *++registered_data = 0 ;
152
+ if (z <= 0 .0f ){
153
+ *map_c_off = -1 ;
131
154
continue ;
132
155
}
133
156
134
157
// 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;
158
+ const float rx = (*map_x + (color.shift_m / z )) * color.fx + color_cx;
136
159
const int cx = rx; // same as round for positive numbers (0.5f was already added to color_cx)
137
160
// getting y offset for depth image
138
161
const int cy = *map_yi;
139
162
// combining offsets
140
- const int c_off = cx * 3 + cy;
163
+ const int c_off = cx + cy * 1920 ;
141
164
142
165
// check if c_off is outside of rgb image
143
166
// 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) {
145
- *registered_data = 0 ;
146
- *++registered_data = 0 ;
147
- *++registered_data = 0 ;
167
+ if (c_off < 0 || c_off >= size_color){
168
+ *map_c_off = -1 ;
148
169
continue ;
149
170
}
150
171
151
- // Setting RGB or registered image
152
- const unsigned char *rgb_data = rgb->data + c_off;
153
- *registered_data = *rgb_data;
154
- *++registered_data = *++rgb_data;
155
- *++registered_data = *++rgb_data;
172
+ // saving the offset for later
173
+ *map_c_off = c_off;
174
+
175
+ if (enable_filter){
176
+ // setting a window around the filter map pixel corresponding to the color pixel with the current z value
177
+ int yi = (cy - filter_height_half) * 1920 + cx - filter_width_half; // index of first pixel to set
178
+ for (int r = -filter_height_half; r <= filter_height_half; ++r, yi += 1920 ) // index increased by a full row each iteration
179
+ {
180
+ float *it = p_filter_map + yi;
181
+ for (int c = -filter_width_half; c <= filter_width_half; ++c, ++it)
182
+ {
183
+ // only set if the current z is smaller
184
+ if (z < *it)
185
+ *it = z;
186
+ }
187
+ }
188
+ }
189
+ }
190
+
191
+ // reseting the pointers to the beginning
192
+ map_c_off = depth_to_c_off;
193
+ undistorted_data = (float *)undistorted->data ;
194
+
195
+ if (enable_filter){
196
+ // run through all registered color pixels and set them based on filter results
197
+ for (int i = 0 ; i < size_depth; ++i, ++map_c_off, ++undistorted_data, ++registered_data){
198
+ const int c_off = *map_c_off;
199
+
200
+ // check if offset is out of image
201
+ if (c_off < 0 ){
202
+ *registered_data = 0 ;
203
+ continue ;
204
+ }
205
+
206
+ const float min_z = p_filter_map[c_off];
207
+ const float z = *undistorted_data;
208
+
209
+ // check for allowed depth noise
210
+ *registered_data = (z - min_z) / z > filter_tolerance ? 0 : *(rgb_data + c_off);
211
+ }
212
+
213
+ delete[] filter_map;
214
+ }
215
+ else
216
+ {
217
+ // run through all registered color pixels and set them based on c_off
218
+ for (int i = 0 ; i < size_depth; ++i, ++map_c_off, ++registered_data){
219
+ const int c_off = *map_c_off;
220
+
221
+ // check if offset is out of image
222
+ *registered_data = c_off < 0 ? 0 : *(rgb_data + c_off);
223
+ }
156
224
}
225
+ delete[] depth_to_c_off;
157
226
}
158
227
159
228
Registration::Registration (Freenect2Device::IrCameraParams depth_p, Freenect2Device::ColorCameraParams rgb_p):
160
- depth (depth_p), color(rgb_p)
229
+ depth (depth_p), color(rgb_p), filter_width_half( 2 ), filter_height_half( 1 ), filter_tolerance( 0 . 01f )
161
230
{
162
231
float mx, my;
163
232
int ix, iy, index;
@@ -186,7 +255,7 @@ Registration::Registration(Freenect2Device::IrCameraParams depth_p, Freenect2Dev
186
255
*map_x++ = rx;
187
256
*map_y++ = ry;
188
257
// compute the y offset to minimize later computations
189
- *map_yi++ = roundf (ry) * 1920 * 3 ;
258
+ *map_yi++ = roundf (ry);
190
259
}
191
260
}
192
261
}
0 commit comments