How to convert the ROS Image obtained from the L525 Lidar camera to real world units
Hello Team,
I have connected the L515 Lidar camera with my computer over the ROS network. I am getting an image from the ROS topic "/camera/depth/image_rect_raw" which is of the type "sensor_msgs/Image".
If I look at one of the topics in MATLAB it looks like this:
MessageType: 'sensor_msgs/Image'
Header: [1×1 Header]
Height: 480
Width: 640
Encoding: '16UC1'
IsBigendian: 0
Step: 1280
Data: [614400×1 uint8]
Now I take this msg and convert it into two pictures in the following manner:
imgData = msg.Data;
imgH = msg.Height;
imgW = msg.Width;
%Create blank image output with required size
img = zeros(msg.Width,msg.Height,2);
imgD = reshape(imgData(1:2:end),imgW,imgH)';
imgC = reshape(imgData(2:2:end),imgW,imgH)';
This is how my depth image imgD looks:
This is how imgC looks:
Now my question is why am I getting 8 bit depth image? Shouldn't it be 16 bit? Why am I getting 480x640 pixels? Secondly, how do I convert the value of the pixels from the 0-255 to meters.
Please let me know if I am doing something wrong.
Thanks for the help in advance.!!
Regards,
Kashish Dhal
-
Hi Kashish Dhal,
Why am I getting 8 bit depth image? Shouldn't it be 16 bit?
You are splitting the 16 bit to two matrix.
I would suggest you look at the typecast and swapbytes functions.
Try to checking out this discussion about merging two 8 bit to 16 bit.Why am I getting 480x640 pixels?
You are getting that resolution because it is the resolution you recorded (it is the default resolution for depth camera)Secondly, how do I convert the value of the pixels from the 0-255 to meters.
You would need to multiply the 16bit value with the the depth camera and add the offset.The topic should be similar to:
- /device_0/sensor_0/option/Depth_Units/value for conversion (it is in meters)
- /device_0/sensor_0/option/Depth_Offset/value for offset (it is in milimeters)
Note: Check your topics. In my case, the depth camera was sensor_0.
You could try something similar to the following:
X = swapbytes( [Dxy Cxy] );
Depth(x,y) = double( typecast(X,'uint16') * depth_units ) + (offset / 1000) ;Regards,
Rizal -
Hello Rizal,
Thank you very much for the reply!
So, I am not splitting the depth image into 2 matrix, but actually from ROS side, I am getting the data as a vector of size 614400. Now this fits into two matrices of 640x480. So I was forced to do so.
Just before getting your reply, I figured that they should be combined to make one matrix. So this is what I did:
imgD = reshape(imgData(1:2:end),imgW,imgH)';
imgC = reshape(imgData(2:2:end),imgW,imgH)';imgCombined = imgCx2^8 + imgD;
This operation is equivalent of what you suggested, typecasting the uint8_t to uint16_t and then swapping the two bytes. But can you suggest something that takes a vector of length 614400 as input and outputs a 640x480 matrix. I am doing this in 3 lines of code as above, if you can suggest something that can be done in one line it will be great!
If I am getting the default resolution then it is fine!
The following you are referring to are ROS topics?
- /device_0/sensor_0/option/Depth_Units/value for conversion (it is in meters)
- /device_0/sensor_0/option/Depth_Offset/value for offset (it is in milimeters)
Currently, I have calibrated the camera myself by taking the distance measurements at different position from camera:
Regards,
Kashish Dhal
-
Hello Rizal,
Thanks for the reply!
Unfortunately, I can't see the topics that you have mentioned, see below:
gnclab@system76-pc:~$ rostopic list /camera/depth/camera_info /camera/depth/image_rect_raw /camera/depth/image_rect_raw/compressed /camera/depth/image_rect_raw/compressed/parameter_descriptions /camera/depth/image_rect_raw/compressed/parameter_updates /camera/depth/image_rect_raw/compressedDepth /camera/depth/image_rect_raw/compressedDepth/parameter_descriptions /camera/depth/image_rect_raw/compressedDepth/parameter_updates /camera/depth/image_rect_raw/theora /camera/depth/image_rect_raw/theora/parameter_descriptions /camera/depth/image_rect_raw/theora/parameter_updates /camera/infra/camera_info /camera/infra/image_raw /camera/infra/image_raw/compressed /camera/infra/image_raw/compressed/parameter_descriptions /camera/infra/image_raw/compressed/parameter_updates /camera/infra/image_raw/compressedDepth /camera/infra/image_raw/compressedDepth/parameter_descriptions /camera/infra/image_raw/compressedDepth/parameter_updates /camera/infra/image_raw/theora /camera/infra/image_raw/theora/parameter_descriptions /camera/infra/image_raw/theora/parameter_updates /camera/l500_depth_sensor/parameter_descriptions /camera/l500_depth_sensor/parameter_updates /camera/motion_module/parameter_descriptions /camera/motion_module/parameter_updates /camera/realsense2_camera_manager/bond /camera/rgb_camera/parameter_descriptions /camera/rgb_camera/parameter_updates /diagnostics /rosout /rosout_agg /tf /tf_static
Also, I wanted to convert the long vector of size 614400 into the 640x480 vector in C++. Would you suggest some efficient way of doing that? Should I use two nested for loops or something else?
-
Hello Rizal,
I am getting the following message:
gnclab@system76-pc:~$ rostopic echo -n1 /camera/depth/camera_info header: seq: 519 stamp: secs: 1605317106 nsecs: 955127954 frame_id: "camera_depth_optical_frame" height: 480 width: 640 distortion_model: "plumb_bob" D: [0.0, 0.0, 0.0, 0.0, 0.0] K: [459.37890625, 0.0, 334.30078125, 0.0, 460.34375, 248.58984375, 0.0, 0.0, 1.0] R: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0] P: [459.37890625, 0.0, 334.30078125, 0.0, 0.0, 460.34375, 248.58984375, 0.0, 0.0, 0.0, 1.0, 0.0] binning_x: 0 binning_y: 0 roi: x_offset: 0 y_offset: 0 height: 0 width: 0 do_rectify: False ---
Please sign in to leave a comment.
Comments
9 comments