0

I'm new to ROS and running ROS noetic with the need to create a ROS bag containing uncompressed greyscale images.
Therefore, I use rosbags-image==0.9.1 and according to their
compressed example here
I have prepared an example to save 2 uncompressed mono8 images, stored on disk as png.
Image size is 225x224 which results in data size of 50400 bytes.

# Test to store 225x224 mono8 images uncompressed in ros bag for noetic
import numpy
from rosbags.rosbag1 import Writer
from rosbags.serde import serialize_ros1, serialize_cdr
from rosbags.typesys.types import builtin_interfaces__msg__Time as Time
# from rosbags.typesys.types import sensor_msgs__msg__CompressedImage as CompressedImage
from rosbags.typesys.types import sensor_msgs__msg__Image as Image
from rosbags.typesys.types import std_msgs__msg__Header as Header
from cv2 import imread

TOPIC = '/camera'
FRAMEID = 'map'

# Contains filenames and their timestamps
IMAGES = [
    ('homer.png', 42),  # w x h = 225 x 224, 8bit
    ('marge.png', 43),  # w x h = 225 x 224, 8bit
]


def save_images() -> None:
    """Iterate over IMAGES and save to output bag."""
    with Writer('output.bag') as writer:
        conn = writer.add_connection(TOPIC, Image.__msgtype__)

        for path, timestamp in IMAGES:
            ii = imread(path, 0)  # test version 1: <type 'numpy.ndarray'>
            dd = numpy.fromfile(path, dtype=numpy.uint8)  # version 2: <type 'numpy.ndarray'>
            print(ii.size, dd.size)  
            # ii.size=50400 = correct uncompressed img data size 
            # vs dd.size=44157 = correct png filesize

            message = Image(
                Header(
                    stamp=Time(
                        sec=int(timestamp // 10**9),
                        nanosec=int(timestamp % 10**9),
                    ),
                    frame_id=FRAMEID,
                ),
                height=ii.shape[0], # 224
                width=ii.shape[1],  # 225
                encoding='mono8',  # 8bit
                is_bigendian=0,  # False
                step=ii.shape[1],  # 225
                # data=ii,  # ii.size = 50400=hxw, ERROR!!!
                # ValueError: memoryview assignment: lvalue and rvalue have different structures
                data=dd,  # dd.size = 44157=png-file size, # Runs, but bag fails to deserialize image in rviz
            )

            writer.write(
                conn,
                timestamp,
                serialize_ros1(message, Image.__msgtype__),
            )
save_images()

Can someone please explain, what's wrong with the code, why setting the (imho) correct ii data results in an error ValueError: memoryview assignment: lvalue and rvalue have different structures, while setting the smaller dd data can be written,
but seems to be wrong as well...

x y
  • 911
  • 9
  • 27

1 Answers1

0

Unless you have very specific needs, I recommend you use cv_bridge to construct sensor_msgs/Image using its cv2_to_imgmsg method instead of doing this yourself.

Refer to: http://wiki.ros.org/cv_bridge/Tutorials/ConvertingBetweenROSImagesAndOpenCVImagesPython