0
$\begingroup$

Rosanswers logo

I want to get the depth data from kinect by receiving sensor_msgs/Image from topic /camera/depth_registrered/image_raw(reference), I use cv_bridge to store the data to a gray scale image.

I use this snippet of code to receive sensor_msgs/Image from topic /camera/depth_registrered/image_raw, change it to gray scale image by cvBridge, and then store the image to a jpeg file.

#!/usr/bin/env python
import roslib
roslib.load_manifest('store_stereo_image')
import sys 
import rospy
import cv
from std_msgs.msg import String
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError

class image_converter:

  def __init__(self):
    self.bridge = CvBridge()
    self.image_sub = rospy.Subscriber("/camera/depth_registered/image_raw",Image,self.callback)

  def callback(self,data):
    try:
        cv_image = self.bridge.imgmsg_to_cv(data, "mono8")
        cv.SaveImage("depth_camera_msg.jpg", cv_image)
        print "image saved!"
    except CvBridgeError, e:
      print e

def main(args):
  ic = image_converter()
  rospy.init_node('image_converter', anonymous=True)
  try:
    rospy.spin()
  except KeyboardInterrupt:
    print "Shutting down"

if __name__ == '__main__':
    main(sys.argv)

This is the jpeg file I stored, I suppose the value in this picture should vary from 0 to 255. However, I found the values in this picture are either 0 or 255(only black and white).

image description

I use rostopic echo /camera/depth_registered/image_raw to check, I found that the data it published vary from 0~255, but I don't know why the image is only black and white~

Did I miss something? Thanks in advance.

---EDIT---

Thanks to DamienJadeDuff's comment, I learned that the raw data from msg sensor_msgs/Image is uint8, and the data contained in /camera/depth_registered/image_raw is uint16 depths in mm. Does this means depth data is retrieved from combining two uint8 data?


Originally posted by Po-Jen Lai on ROS Answers with karma: 1371 on 2013-03-21

Post score: 0


Original comments

Comment by DamienJadeDuff on 2013-03-22:
From memory, the depth image is a 32 bit float. Perhaps the rostopic echo is only showing the byte level data?

Comment by DamienJadeDuff on 2013-03-31:
To respond to your edit, Ricky; sorry I got the encoding wrong for your message (depth_registered/image_raw), but why don't you use depth_registered/image instead? See http://www.ros.org/wiki/depth_image_proc --- then you can use jelfring's code for image type 32FC1.

Comment by DamienJadeDuff on 2013-03-31:
Also, yes, check the encoding field in the message; that gives a cue as to how the data should be interpreted. But you should be able to use the cv_bridge library to interpret the message. See http://www.ros.org/wiki/cv_bridge

$\endgroup$

2 Answers 2

0
$\begingroup$

Rosanswers logo

Hi,

We have made a tool to store camera data from a bag file, e.g., depth images, as a video sequence. Part of the procedure can help you I guess. The relevant file can be found here:

ros.org/doc/electric/api/rosbag_video/html/bag__to__video_8cpp_source.html (lines 95-125).

Jos


Originally posted by jelfring with karma: 36 on 2013-03-21

This answer was ACCEPTED on the original site

Post score: 2


Original comments

Comment by Albert K on 2013-04-13:
@jelfring: I've met the same problem with Ricky. Thanks for the code you provided, it solves the problem. But why is that we need to do the data conversion by ourselves? The function toCvCopy() should be able to convert the encoding internally. What's wrong when using toCvCopy(msg, mono8)

Comment by Albert K on 2013-04-13:
By the way, I use toCvCopy(msg, mono8) and try to convert float32 to int8 and fialed. That's a similar condition to Ricky's.

$\endgroup$
0
$\begingroup$

Rosanswers logo

I now is an old thread. But just for the others that need to store a depth image (from camera or from rosbag) to a png file. This is what you should do on the depth image subscription callback or in any place you want to perform this operation with python:

def callback(self, data):
    try:
        # The depth image is a single-channel float32 image
        # the values is the distance in mm in z axis
        depth_image = self.bridge.imgmsg_to_cv(data, '32FC1')
        # Convert the depth image to a Numpy array since most cv2 functions
        # require Numpy arrays.
        depth_array = np.array(depth_image, dtype=np.float32)
        # Normalize the depth image to fall between 0 (black) and 1 (white)
        cv2.normalize(depth_array, depth_array, 0, 1, cv2.NORM_MINMAX)
        # At this point you can display the result properly:
        # cv2.imshow('Depth Image', depth_display_image)
        # If you write it as it si, the result will be a image with only 0 to 1 values.
        # To actually store in a this a image like the one we are showing its needed
        # to reescale the otuput to 255 gray scale.
        cv2.imwrite('capture_depth.png',frame*255)
    except CvBridgeError, e:
        print e

I'm using at the moment ubuntu 12.04 and Ros Hydro


Originally posted by E1000ii with karma: 178 on 2014-05-13

This answer was NOT ACCEPTED on the original site

Post score: 5


Original comments

Comment by Pototo on 2016-12-08:
What would be the case if I had a compressedDepth image instead?

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.