如何在没有 OpenCV 的情况下通过 ROS 发布 PIL 图像二进制文件?
How can I publish PIL image binary through ROS without OpenCV?
我目前正在尝试编写一个 ROS Publisher/Subscriber 设置来传递由 PIL 打开的图像二进制文件。由于操作限制,我不想使用 OpenCV,我想知道是否有办法这样做。这是我当前的代码:
#!/usr/bin/env python
import rospy
from PIL import Image
from sensor_msgs.msg import Image as sensorImage
from rospy.numpy_msg import numpy_msg
import numpy
def talker():
pub = rospy.Publisher('image_stream', numpy_msg(sensorImage), queue_size=10)
rospy.init_node('image_publisher', anonymous=False)
rate = rospy.Rate(0.5)
while not rospy.is_shutdown():
im = numpy.array(Image.open('test.jpg'))
pub.publish(im)
rate.sleep()
if __name__ == '__main__'
try:
talker()
except ROSInterruptException:
pass
pub.publish(im) 尝试抛出:
TypeError: Invalid number of arguments, args should be ['header', 'height', 'width', 'encoding', 'is_bigendian', 'step', 'data'] args are (array([[[***array data here***]]], dtype=uint8),)
我如何将图像转换为正确的形式,或者是否有一种转换 method/different 消息类型仅支持通过 ROS 连接发送原始二进制文件?
谢谢
我对ROS一无所知,但我经常使用PIL,所以如果有人知道更好,请ping我,我会删除这个“最佳猜测”答案。
因此,您似乎需要从 PIL Image
中创建类似 this 的内容。所以你需要:
- 'header',
- 'height',
- 'width',
- 'encoding',
- 'is_bigendian',
- 'step',
- 'data'
因此,假设您这样做:
im = Image.open('test.jpg')
你应该可以使用:
- 你需要解决的问题
im.height
来自 PIL Image
im.width
来自 PIL Image
- 可能
const std::string RGB8 = "rgb8"
- 可能不相关,因为数据是 8 位
- 可能
im.width * 3
因为它是每个像素 3 个字节 RGB
np.array(im).tobytes()
在有人标记此答案之前,没有人说答案必须是完整的 - 它们可以 “希望有帮助”!
请注意,如果您的输入图像是 PNG 格式,您应该检查 im.mode
,如果是 "P"
(即调色板模式),请立即检查 运行:
im = im.convert('RGB')
确定是3通道RGB。
请注意,如果您的输入图像是 PNG 格式且包含 alpha 通道,则应将 encoding
更改为 "rgba8"
并设置 step = im.width * 4
.
确实 完美运行(在本例中忽略 alpha 通道):
#!/usr/bin/env python
import rospy
import urllib2 # for downloading an example image
from PIL import Image
from sensor_msgs.msg import Image as SensorImage
import numpy as np
if __name__ == '__main__':
pub = rospy.Publisher('/image', SensorImage, queue_size=10)
rospy.init_node('image_publisher')
im = Image.open(urllib2.urlopen('https://cdn.sstatic.net/Sites/Whosebug/Img/apple-touch-icon.png'))
im = im.convert('RGB')
msg = SensorImage()
msg.header.stamp = rospy.Time.now()
msg.height = im.height
msg.width = im.width
msg.encoding = "rgb8"
msg.is_bigendian = False
msg.step = 3 * im.width
msg.data = np.array(im).tobytes()
pub.publish(msg)
我目前正在尝试编写一个 ROS Publisher/Subscriber 设置来传递由 PIL 打开的图像二进制文件。由于操作限制,我不想使用 OpenCV,我想知道是否有办法这样做。这是我当前的代码:
#!/usr/bin/env python
import rospy
from PIL import Image
from sensor_msgs.msg import Image as sensorImage
from rospy.numpy_msg import numpy_msg
import numpy
def talker():
pub = rospy.Publisher('image_stream', numpy_msg(sensorImage), queue_size=10)
rospy.init_node('image_publisher', anonymous=False)
rate = rospy.Rate(0.5)
while not rospy.is_shutdown():
im = numpy.array(Image.open('test.jpg'))
pub.publish(im)
rate.sleep()
if __name__ == '__main__'
try:
talker()
except ROSInterruptException:
pass
pub.publish(im) 尝试抛出:
TypeError: Invalid number of arguments, args should be ['header', 'height', 'width', 'encoding', 'is_bigendian', 'step', 'data'] args are (array([[[***array data here***]]], dtype=uint8),)
我如何将图像转换为正确的形式,或者是否有一种转换 method/different 消息类型仅支持通过 ROS 连接发送原始二进制文件?
谢谢
我对ROS一无所知,但我经常使用PIL,所以如果有人知道更好,请ping我,我会删除这个“最佳猜测”答案。
因此,您似乎需要从 PIL Image
中创建类似 this 的内容。所以你需要:
- 'header',
- 'height',
- 'width',
- 'encoding',
- 'is_bigendian',
- 'step',
- 'data'
因此,假设您这样做:
im = Image.open('test.jpg')
你应该可以使用:
- 你需要解决的问题
im.height
来自PIL Image
im.width
来自PIL Image
- 可能
const std::string RGB8 = "rgb8"
- 可能不相关,因为数据是 8 位
- 可能
im.width * 3
因为它是每个像素 3 个字节 RGB np.array(im).tobytes()
在有人标记此答案之前,没有人说答案必须是完整的 - 它们可以 “希望有帮助”!
请注意,如果您的输入图像是 PNG 格式,您应该检查 im.mode
,如果是 "P"
(即调色板模式),请立即检查 运行:
im = im.convert('RGB')
确定是3通道RGB。
请注意,如果您的输入图像是 PNG 格式且包含 alpha 通道,则应将 encoding
更改为 "rgba8"
并设置 step = im.width * 4
.
确实
#!/usr/bin/env python
import rospy
import urllib2 # for downloading an example image
from PIL import Image
from sensor_msgs.msg import Image as SensorImage
import numpy as np
if __name__ == '__main__':
pub = rospy.Publisher('/image', SensorImage, queue_size=10)
rospy.init_node('image_publisher')
im = Image.open(urllib2.urlopen('https://cdn.sstatic.net/Sites/Whosebug/Img/apple-touch-icon.png'))
im = im.convert('RGB')
msg = SensorImage()
msg.header.stamp = rospy.Time.now()
msg.height = im.height
msg.width = im.width
msg.encoding = "rgb8"
msg.is_bigendian = False
msg.step = 3 * im.width
msg.data = np.array(im).tobytes()
pub.publish(msg)