Skip to content

Commit 67762dd

Browse files
committed
factored out common code from depth_image_proc register convert
1 parent 776da13 commit 67762dd

File tree

1 file changed

+89
-61
lines changed

1 file changed

+89
-61
lines changed

depth_image_proc/src/nodelets/register.cpp

Lines changed: 89 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)