@@ -174,6 +174,8 @@ void RegisterNodelet::imageCb(const sensor_msgs::ImageConstPtr& depth_image_msg,
174174 registered_msg->width = resolution.width ;
175175 // step and data set in convert(), depend on depth data type
176176
177+ // TODO(lucasw) want a version of this where an rgb image that is lined up
178+ // with input depth_image pixel-for-pixel is converted
177179 if (depth_image_msg->encoding == enc::TYPE_16UC1)
178180 {
179181 convert<uint16_t >(depth_image_msg, registered_msg, depth_to_rgb);
@@ -195,6 +197,9 @@ void RegisterNodelet::imageCb(const sensor_msgs::ImageConstPtr& depth_image_msg,
195197 pub_registered_.publish (registered_msg, registered_info_msg);
196198}
197199
200+ // TODO(lucasw) need a unit test for this, simple low res image (e.g. 4x4 pixels) with
201+ // depth ranges of around 1.0
202+ // shift it to the right 1.0 units, view from 90 degrees
198203template <typename T>
199204void RegisterNodelet::convert (const sensor_msgs::ImageConstPtr& depth_msg,
200205 const sensor_msgs::ImagePtr& registered_msg,
@@ -207,32 +212,33 @@ void RegisterNodelet::convert(const sensor_msgs::ImageConstPtr& depth_msg,
207212 DepthTraits<T>::initializeBuffer (registered_msg->data );
208213
209214 // Extract all the parameters we need
210- double inv_depth_fx = 1.0 / depth_model_.fx ();
211- double inv_depth_fy = 1.0 / depth_model_.fy ();
212- double depth_cx = depth_model_.cx (), depth_cy = depth_model_.cy ();
213- double depth_Tx = depth_model_.Tx (), depth_Ty = depth_model_.Ty ();
214- double rgb_fx = rgb_model_.fx (), rgb_fy = rgb_model_.fy ();
215- double rgb_cx = rgb_model_.cx (), rgb_cy = rgb_model_.cy ();
216- double rgb_Tx = rgb_model_.Tx (), rgb_Ty = rgb_model_.Ty ();
215+ const double inv_depth_fx = 1.0 / depth_model_.fx ();
216+ const double inv_depth_fy = 1.0 / depth_model_.fy ();
217+ const double depth_cx = depth_model_.cx (), depth_cy = depth_model_.cy ();
218+ const double depth_Tx = depth_model_.Tx (), depth_Ty = depth_model_.Ty ();
219+ const double rgb_fx = rgb_model_.fx (), rgb_fy = rgb_model_.fy ();
220+ const double rgb_cx = rgb_model_.cx (), rgb_cy = rgb_model_.cy ();
221+ const double rgb_Tx = rgb_model_.Tx (), rgb_Ty = rgb_model_.Ty ();
217222
218223 // Transform the depth values into the RGB frame
219224 // / @todo When RGB is higher res, interpolate by rasterizing depth triangles onto the registered image
220225 const T* depth_row = reinterpret_cast <const T*>(&depth_msg->data [0 ]);
221- int row_step = depth_msg->step / sizeof (T);
226+ const int row_step = depth_msg->step / sizeof (T);
222227 T* registered_data = reinterpret_cast <T*>(®istered_msg->data [0 ]);
223228 int raw_index = 0 ;
224229 for (unsigned v = 0 ; v < depth_msg->height ; ++v, depth_row += row_step)
225230 {
226231 for (unsigned u = 0 ; u < depth_msg->width ; ++u, ++raw_index)
227232 {
228- T raw_depth = depth_row[u];
233+ const T raw_depth = depth_row[u];
229234 if (!DepthTraits<T>::valid (raw_depth))
230235 continue ;
231-
232- double depth = DepthTraits<T>::toMeters (raw_depth);
236+
237+ const double depth = DepthTraits<T>::toMeters (raw_depth);
233238
234239 if (fill_upsampling_holes_ == false )
235240 {
241+ // TODO(lucasw) factor out common code below
236242 // / @todo Combine all operations into one matrix multiply on (u,v,d)
237243 // Reproject (u,v,Z) to (X,Y,Z,1) in depth camera frame
238244 Eigen::Vector4d xyz_depth;
@@ -247,12 +253,13 @@ void RegisterNodelet::convert(const sensor_msgs::ImageConstPtr& depth_msg,
247253 // Project to (u,v) in RGB image
248254 double inv_Z = 1.0 / xyz_rgb.z ();
249255 int u_rgb = (rgb_fx*xyz_rgb.x () + rgb_Tx)*inv_Z + rgb_cx + 0.5 ;
256+ if (u_rgb < 0 || u_rgb >= (int )registered_msg->width )
257+ continue ;
258+
250259 int v_rgb = (rgb_fy*xyz_rgb.y () + rgb_Ty)*inv_Z + rgb_cy + 0.5 ;
251-
252- if (u_rgb < 0 || u_rgb >= (int )registered_msg->width ||
253- v_rgb < 0 || v_rgb >= (int )registered_msg->height )
260+ if (v_rgb < 0 || v_rgb >= (int )registered_msg->height )
254261 continue ;
255-
262+
256263 T& reg_depth = registered_data[v_rgb*registered_msg->width + u_rgb];
257264 T new_depth = DepthTraits<T>::fromMeters (xyz_rgb.z ());
258265 // Validity and Z-buffer checks
@@ -261,39 +268,47 @@ void RegisterNodelet::convert(const sensor_msgs::ImageConstPtr& depth_msg,
261268 }
262269 else
263270 {
271+ // TODO(lucasw) replace same code with for loop
264272 // Reproject (u,v,Z) to (X,Y,Z,1) in depth camera frame
265273 Eigen::Vector4d xyz_depth_1, xyz_depth_2;
266274 xyz_depth_1 << ((u-0 .5f - depth_cx)*depth - depth_Tx) * inv_depth_fx,
267275 ((v-0 .5f - depth_cy)*depth - depth_Ty) * inv_depth_fy,
268276 depth,
269277 1 ;
278+ // Transform to RGB camera frame
279+ Eigen::Vector4d xyz_rgb_1 = depth_to_rgb * xyz_depth_1;
280+ // Project to (u,v) in RGB image
281+ const double inv_Z_1 = 1.0 / xyz_rgb_1.z ();
282+ const int u_rgb_1 = (rgb_fx*xyz_rgb_1.x () + rgb_Tx)*inv_Z_1 + rgb_cx + 0.5 ;
283+ if (u_rgb_1 < 0 || u_rgb_1 >= (int )registered_msg->width )
284+ continue ;
285+ const int v_rgb_1 = (rgb_fy*xyz_rgb_1.y () + rgb_Ty)*inv_Z_1 + rgb_cy + 0.5 ;
286+ if (v_rgb_1 < 0 || v_rgb_1 >= (int )registered_msg->height )
287+ continue ;
288+
289+ // TODO(lucasw) this is identical to above except adding 0.5 instead of subtracting
270290 xyz_depth_2 << ((u+0 .5f - depth_cx)*depth - depth_Tx) * inv_depth_fx,
271291 ((v+0 .5f - depth_cy)*depth - depth_Ty) * inv_depth_fy,
272292 depth,
273293 1 ;
274-
275294 // Transform to RGB camera frame
276- Eigen::Vector4d xyz_rgb_1 = depth_to_rgb * xyz_depth_1;
277295 Eigen::Vector4d xyz_rgb_2 = depth_to_rgb * xyz_depth_2;
278-
279296 // Project to (u,v) in RGB image
280- double inv_Z = 1.0 / xyz_rgb_1.z ();
281- int u_rgb_1 = (rgb_fx*xyz_rgb_1.x () + rgb_Tx)*inv_Z + rgb_cx + 0.5 ;
282- int v_rgb_1 = (rgb_fy*xyz_rgb_1.y () + rgb_Ty)*inv_Z + rgb_cy + 0.5 ;
283- inv_Z = 1.0 / xyz_rgb_2.z ();
284- int u_rgb_2 = (rgb_fx*xyz_rgb_2.x () + rgb_Tx)*inv_Z + rgb_cx + 0.5 ;
285- int v_rgb_2 = (rgb_fy*xyz_rgb_2.y () + rgb_Ty)*inv_Z + rgb_cy + 0.5 ;
286-
287- if (u_rgb_1 < 0 || u_rgb_2 >= (int )registered_msg->width ||
288- v_rgb_1 < 0 || v_rgb_2 >= (int )registered_msg->height )
297+ const double inv_Z_2 = 1.0 / xyz_rgb_2.z ();
298+ const int u_rgb_2 = (rgb_fx*xyz_rgb_2.x () + rgb_Tx)*inv_Z_2 + rgb_cx + 0.5 ;
299+ if (u_rgb_2 < 0 || u_rgb_2 >= (int )registered_msg->width )
300+ continue ;
301+ const int v_rgb_2 = (rgb_fy*xyz_rgb_2.y () + rgb_Ty)*inv_Z_2 + rgb_cy + 0.5 ;
302+ if (v_rgb_2 < 0 || v_rgb_2 >= (int )registered_msg->height )
289303 continue ;
290304
305+ // fill in the square defined by uv range
306+ const T new_depth = DepthTraits<T>::fromMeters (0.5 *(xyz_rgb_1.z ()+xyz_rgb_2.z ()));
291307 for (int nv=v_rgb_1; nv<=v_rgb_2; ++nv)
292308 {
293309 for (int nu=u_rgb_1; nu<=u_rgb_2; ++nu)
294310 {
295311 T& reg_depth = registered_data[nv*registered_msg->width + nu];
296- T new_depth = DepthTraits<T>::fromMeters (0.5 *(xyz_rgb_1.z ()+xyz_rgb_2.z ()));
297312 // Validity and Z-buffer checks
298313 if (!DepthTraits<T>::valid (reg_depth) || reg_depth > new_depth)
299314 reg_depth = new_depth;
0 commit comments