ROS Noetic下用rosbags-image写入未压缩灰度图至Bag报错求助
ROS Noetic下rosbags-image写入未压缩灰度图的问题解析
错误原因分析
1. imread数组赋值data报错
你用imread读取灰度图得到的是2D numpy数组(比如(224, 225)的形状),而ROS sensor_msgs/Image的data字段需要的是一维的原始像素字节流(mono8格式下,每个像素对应1字节,按行连续排列)。直接将2D数组赋值给data时,内存视图的结构不匹配(二维 vs 一维),所以触发ValueError: memoryview assignment: lvalue and rvalue have different structures错误。
2. numpy.fromfile读取的字节无法被RViz解析
numpy.fromfile读取的是PNG文件的原始压缩二进制数据(包含PNG文件头、压缩编码块等),但ROS未压缩图像话题要求的是未压缩的像素原始值。RViz会把这些PNG压缩数据当成mono8像素字节流去解析,自然无法识别,导致反序列化失败。
正确实现步骤及代码
要写入未压缩灰度图,需完成以下步骤:
- 读取灰度图并转成2D uint8数组
- 将数组扁平化为一维连续内存的字节流
- 正确设置Image消息的元数据(宽度、高度、编码、步长)
示例代码:
import numpy as np from PIL import Image from rosbags.image import Image from rosbags.highlevel import AnyWriter from rosbags.time import Time # 读取灰度图(用PIL确保得到标准mono8格式) img = Image.open("your_image.png").convert('L') # 'L'表示8位灰度图 img_array = np.array(img) # shape: (height, width) = (224, 225) # 构造ROS Image消息 ros_image = Image() ros_image.width = img_array.shape[1] ros_image.height = img_array.shape[0] ros_image.encoding = 'mono8' ros_image.step = ros_image.width # mono8格式下,每行字节数等于宽度 # 将2D数组转为一维连续字节流,赋值给data ros_image.data = np.ascontiguousarray(img_array).flatten().tobytes() # 写入ROS Bag with AnyWriter(path="output_gray.bag") as writer: # 注册话题 topic = "/camera/gray_image" msg_type = "sensor_msgs/Image" writer.add_topic(topic, msg_type, "rosbag2") # 写入消息(用当前时间作为时间戳) timestamp = Time.now() writer.write(topic, timestamp, ros_image.serialize())
关键注意事项
- 如果用
cv2.imread读取灰度图,要注意cv2.imread(path, cv2.IMREAD_GRAYSCALE)返回的是正确的uint8数组,无需额外转换。 np.ascontiguousarray确保数组内存连续,避免内存视图结构问题。step字段必须正确设置:mono8格式下step = width,若为RGB8则step = width * 3。
内容的提问来源于stack exchange,提问作者x y
相关产品推荐
相关产品推荐

