[英]How can I publish PIL image binary through ROS without OpenCV?
I'm currently trying to write a ROS Publisher/Subscriber setup that passes image binary opened by PIL.我目前正在尝试编写一个 ROS 发布者/订阅者设置,通过 PIL 打开的图像二进制文件。 I'd like to not have to use OpenCV due to operating restrictions, and I was wondering if there was a way to do so.
由于操作限制,我不想使用 OpenCV,我想知道是否有办法这样做。 This is my current code:
这是我当前的代码:
#!/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
which on pub.publish(im) attempt throws:在 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),)
How would I transform the image into the right form, or is there a conversion method/different message type that supports just sending raw binary over the ROS connection?我将如何将图像转换为正确的形式,或者是否有一种转换方法/不同的消息类型支持仅通过 ROS 连接发送原始二进制文件?
Thanks谢谢
Indeed Mark Setchell's answer works perfectly (ignoring the alpha channel in this example):事实上, Mark Setchell 的回答非常有效(在这个例子中忽略了 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/stackoverflow/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)
I don't know anything about ROS, but I use PIL a lot, so if someone else knows better, please ping me and I will delete this "best guess" answer.我对 ROS 一无所知,但我经常使用PIL ,所以如果其他人更了解,请 ping 我,我将删除这个“最佳猜测”答案。
So, it seems you need to make something like this from a PIL Image
.因此,看来你需要的东西像这样从
PIL Image
。 So you need:所以你需要:
So, assuming you do this:所以,假设你这样做:
im = Image.open('test.jpg')
you should be able to use:你应该能够使用:
im.height
from PIL Image
PIL Image
im.height
im.width
from PIL Image
PIL Image
im.width
const std::string RGB8 = "rgb8"
const std::string RGB8 = "rgb8"
im.width * 3
as it's 3 bytes per pixel RGBim.width * 3
因为它是每像素 RGB 3 个字节np.array(im).tobytes()
Before anyone marks this answer down, nobody said answers have to be complete - they can just be "hopefully helpful" !在任何人标记这个答案之前,没有人说答案必须是完整的——他们只是“希望有帮助” !
Note that if your input image is PNG format, you should check im.mode
and if it is "P"
(ie palette mode) immediately run:请注意,如果您的输入图像是 PNG 格式,您应该检查
im.mode
,如果它是"P"
(即调色板模式),请立即运行:
im = im.convert('RGB')
to make sure it is 3-channel RGB.以确保它是 3 通道 RGB。
Note that if your input image is PNG format and contains an alpha channel, you should change the encoding
to "rgba8"
and set step = im.width * 4
.请注意,如果您的输入图像是 PNG 格式并包含 alpha 通道,则应将
encoding
更改为"rgba8"
并设置step = im.width * 4
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.