You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 07:37:26