@@ -197,6 +197,54 @@ void RegisterNodelet::imageCb(const sensor_msgs::ImageConstPtr& depth_image_msg,
197197 pub_registered_.publish (registered_msg, registered_info_msg);
198198}
199199
200+ template <typename T>
201+ bool transform_depth (
202+ const Eigen::Affine3d& depth_to_rgb,
203+ const double u, const double v,
204+ const image_geometry::PinholeCameraModel& depth_model_,
205+ const image_geometry::PinholeCameraModel& rgb_model_,
206+ const double inv_depth_fx, const double inv_depth_fy,
207+ const int width, const int height,
208+ const double depth,
209+ int & u_rgb, int & v_rgb,
210+ T& new_depth)
211+ {
212+ // TODO(lucasw) pulling these out shouldn't cost anything
213+ const auto depth_cx = depth_model_.cx (), depth_cy = depth_model_.cy ();
214+ const auto depth_Tx = depth_model_.Tx (), depth_Ty = depth_model_.Ty ();
215+ const auto rgb_fx = rgb_model_.fx (), rgb_fy = rgb_model_.fy ();
216+ const auto rgb_cx = rgb_model_.cx (), rgb_cy = rgb_model_.cy ();
217+ const auto rgb_Tx = rgb_model_.Tx (), rgb_Ty = rgb_model_.Ty ();
218+
219+ // TODO(lucasw) factor out common code below
220+ // / @todo Combine all operations into one matrix multiply on (u,v,d)
221+ // Reproject (u,v,Z) to (X,Y,Z,1) in depth camera frame
222+ Eigen::Vector4d xyz_depth;
223+ xyz_depth << ((u - depth_cx)*depth - depth_Tx) * inv_depth_fx,
224+ ((v - depth_cy)*depth - depth_Ty) * inv_depth_fy,
225+ depth,
226+ 1 ;
227+
228+ // Transform to RGB camera frame
229+ Eigen::Vector4d xyz_rgb = depth_to_rgb * xyz_depth;
230+ // TODO(lucasw) return false if xyz_rgb.z() < 0.0 - or is that okay for some < 0 fx/fy?
231+
232+ // Project to (u,v) in RGB image
233+ const double inv_Z = 1.0 / xyz_rgb.z ();
234+
235+ u_rgb = (rgb_fx*xyz_rgb.x () + rgb_Tx)*inv_Z + rgb_cx + 0.5 ;
236+ if (u_rgb < 0 || u_rgb >= width)
237+ return false ;
238+
239+ v_rgb = (rgb_fy*xyz_rgb.y () + rgb_Ty)*inv_Z + rgb_cy + 0.5 ;
240+ if (v_rgb < 0 || v_rgb >= height)
241+ return false ;
242+
243+ new_depth = static_cast <T>(xyz_rgb.z ());
244+
245+ return true ;
246+ }
247+
200248// TODO(lucasw) need a unit test for this, simple low res image (e.g. 4x4 pixels) with
201249// depth ranges of around 1.0
202250// shift it to the right 1.0 units, view from 90 degrees
@@ -214,12 +262,10 @@ void RegisterNodelet::convert(const sensor_msgs::ImageConstPtr& depth_msg,
214262 // Extract all the parameters we need
215263 const double inv_depth_fx = 1.0 / depth_model_.fx ();
216264 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 ();
222-
265+
266+ const int dst_width = static_cast <int >(registered_msg->width );
267+ const int dst_height = static_cast <int >(registered_msg->height );
268+
223269 // Transform the depth values into the RGB frame
224270 // / @todo When RGB is higher res, interpolate by rasterizing depth triangles onto the registered image
225271 const T* depth_row = reinterpret_cast <const T*>(&depth_msg->data [0 ]);
@@ -238,75 +284,57 @@ void RegisterNodelet::convert(const sensor_msgs::ImageConstPtr& depth_msg,
238284
239285 if (fill_upsampling_holes_ == false )
240286 {
241- // TODO(lucasw) factor out common code below
242- // / @todo Combine all operations into one matrix multiply on (u,v,d)
243- // Reproject (u,v,Z) to (X,Y,Z,1) in depth camera frame
244- Eigen::Vector4d xyz_depth;
245- xyz_depth << ((u - depth_cx)*depth - depth_Tx) * inv_depth_fx,
246- ((v - depth_cy)*depth - depth_Ty) * inv_depth_fy,
247- depth,
248- 1 ;
249-
250- // Transform to RGB camera frame
251- Eigen::Vector4d xyz_rgb = depth_to_rgb * xyz_depth;
252-
253- // Project to (u,v) in RGB image
254- double inv_Z = 1.0 / xyz_rgb.z ();
255- 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-
259- int v_rgb = (rgb_fy*xyz_rgb.y () + rgb_Ty)*inv_Z + rgb_cy + 0.5 ;
260- if (v_rgb < 0 || v_rgb >= (int )registered_msg->height )
287+ int u_rgb;
288+ int v_rgb;
289+ T new_depth;
290+ if (!transform_depth (depth_to_rgb, u, v,
291+ depth_model_, rgb_model_,
292+ inv_depth_fx, inv_depth_fy,
293+ dst_width, dst_height,
294+ depth,
295+ u_rgb, v_rgb, new_depth)) {
261296 continue ;
297+ }
262298
263299 T& reg_depth = registered_data[v_rgb*registered_msg->width + u_rgb];
264- T new_depth = DepthTraits<T>::fromMeters (xyz_rgb.z ());
265300 // Validity and Z-buffer checks
266301 if (!DepthTraits<T>::valid (reg_depth) || reg_depth > new_depth)
267302 reg_depth = new_depth;
303+
268304 }
269305 else
270306 {
271- // TODO(lucasw) replace same code with for loop
272- // Reproject (u,v,Z) to (X,Y,Z,1) in depth camera frame
273- Eigen::Vector4d xyz_depth_1, xyz_depth_2;
274- xyz_depth_1 << ((u-0 .5f - depth_cx)*depth - depth_Tx) * inv_depth_fx,
275- ((v-0 .5f - depth_cy)*depth - depth_Ty) * inv_depth_fy,
276- depth,
277- 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 )
307+ // TODO(lucasw) loop on two -0.5, 0.5 vectors, keep track of u_min/max and v_min/max
308+ // as it goes
309+ int u_rgb_1;
310+ int v_rgb_1;
311+ T new_depth_1;
312+ if (!transform_depth (depth_to_rgb,
313+ u - 0.5 , v - 0.5 ,
314+ depth_model_, rgb_model_,
315+ inv_depth_fx, inv_depth_fy,
316+ dst_width, dst_height,
317+ depth,
318+ u_rgb_1, v_rgb_1, new_depth_1)) {
319+ // TODO(lucasw) need to be able to handle partiall out of bounds squares here
287320 continue ;
321+ }
288322
289- // TODO(lucasw) this is identical to above except adding 0.5 instead of subtracting
290- // TODO(lucasw) need a third and fourth position with u+0.5 and v-0.5 and u-0.5 and v+0.5
291- // (and then could do the triangle rastering mentioned above, or just take the min
292- // and max of all of them)
293- xyz_depth_2 << ((u+0 .5f - depth_cx)*depth - depth_Tx) * inv_depth_fx,
294- ((v+0 .5f - depth_cy)*depth - depth_Ty) * inv_depth_fy,
295- depth,
296- 1 ;
297- // Transform to RGB camera frame
298- Eigen::Vector4d xyz_rgb_2 = depth_to_rgb * xyz_depth_2;
299- // Project to (u,v) in RGB image
300- const double inv_Z_2 = 1.0 / xyz_rgb_2.z ();
301- const int u_rgb_2 = (rgb_fx*xyz_rgb_2.x () + rgb_Tx)*inv_Z_2 + rgb_cx + 0.5 ;
302- if (u_rgb_2 < 0 || u_rgb_2 >= (int )registered_msg->width )
303- continue ;
304- const int v_rgb_2 = (rgb_fy*xyz_rgb_2.y () + rgb_Ty)*inv_Z_2 + rgb_cy + 0.5 ;
305- if (v_rgb_2 < 0 || v_rgb_2 >= (int )registered_msg->height )
323+ int u_rgb_2;
324+ int v_rgb_2;
325+ T new_depth_2;
326+ if (!transform_depth (depth_to_rgb,
327+ u + 0.5 , v + 0.5 ,
328+ depth_model_, rgb_model_,
329+ inv_depth_fx, inv_depth_fy,
330+ dst_width, dst_height,
331+ depth,
332+ u_rgb_2, v_rgb_2, new_depth_2)) {
306333 continue ;
334+ }
307335
308336 // fill in the square defined by uv range
309- const T new_depth = DepthTraits<T>::fromMeters (0.5 *(xyz_rgb_1. z ()+xyz_rgb_2. z () ));
337+ const T new_depth = DepthTraits<T>::fromMeters (0.5 * (new_depth_1 + new_depth_2 ));
310338 for (int nv=std::min (v_rgb_1, v_rgb_2); nv<=std::max (v_rgb_1, v_rgb_2); ++nv)
311339 {
312340 for (int nu=std::min (u_rgb_1, u_rgb_2); nu<=std::max (u_rgb_2, u_rgb_2); ++nu)
0 commit comments