关于rospy中图像的实时处理

引子

        前一段时间做项目时遇到了一个图像处理的问题,当时的任务是要在ROS中实时地获取图像并作为网络的输入进行前向计算。如果是使用C++的话将没有什么问题,直接获取图像处理就是了,但是如果使用Python的话,就会遇到数据格式的问题。下面我们对此进行简要介绍。

rosmsg中的数据格式

        在使用ROS时,常常会自定义消息类型,即.msg文件,我们需要遵守一定的规则来对此进行定义,比如:

geometry_msgs/Vector3.msg
float64 x
float64 y
float64 z

        其中会用到一些原子类型,比如float64。那这些类型在C++或者是Python中分别对应什么类型的数据呢?对照关系列表如下:


关于rospy中图像的实时处理_第1张图片

        上表中小括号里的数字代表下列注释:


关于rospy中图像的实时处理_第2张图片

        从上面的列表中可以看出,rosmsg中的uint8虽然对应Python中的int,但是却与一般的int稍有不同。rosmsg中的uint8[]表示的并不是int[],而是被作为Python bytes对待,这一点尤其需要注意。具体请参考rosmsg。

Python bytes

        通常,在计算机中,为了对不同类型的数据进行表示,我们需要对数据进行编码。常见的编码方式有ASCII码,UTF-8编码等。这些编码将不同类型的数据如“a、b、c”、“1、2、3”、“&、*、^”等编码为二进制数,以便于在计算机中进行存储和表示。Python bytes就是这样一种编码之后的数据类型,也即二进制数据类型,一般以16进制进行表示:

>>> '€20'.encode('utf-8')
b'\xe2\x82\xac20'
>>> b'\xe2\x82\xac20'.decode('utf-8')
'€20'

        结合前面对rosmsg的介绍,我们可以发现rosmsg中的uint8[]是将uint数组直接以二进制方式表示了,从而实现更快地存取操作。

图像处理中的问题

        在rospy中,我们的sensor_msgs/Image消息类型定义如下:

std_msgs/Header header
uint32 height
uint32 width
string encoding
uint8 is_bigendian
uint32 step
uint8[] data

        用于存储图像数据的是uint8,而刚刚我们谈到uint8[]在Python中将被当做bytes处理。如果我们想要使用NumPy对图像数据进行处理,则需要先转换为10进制数据。最开始我是这样做的:

start_time = time.time()
bytes_list = list(img_data)
temp = []
for i in range(len(img_data)):
    temp.append(ord(bytes_list[i]))
img_array = np.array(temp, dtype=np.uint8) 
array_reshaped = img_array.reshape([480, 640, 3])
end_time = time.time() 
print "Elapsed time: ", end_time - start_time

        这段代码测试耗时约为0.12s,也即最多能够达到8Hz的频率,这样的话实时性就得不到保证了。
        幸好NumPy提供了frombuffer函数用于对这类bytes数据进行处理:

>>> np.frombuffer(b'\x01\x02', dtype=np.uint8)
array([1, 2], dtype=uint8)
>>> np.frombuffer(b'\x01\x02\x03\x04\x05', dtype=np.uint8, count=3)
array([1, 2, 3], dtype=uint8)

        我们可以将这一函数用于处理上面的图像数据:

start_time = time.time()
img_array = np.frombuffer(img_data, dtype=np.uint8)
array_reshaped = img_array.reshape([480, 640, 3])
end_time = time.time() 
print "Elapsed time: ", end_time - start_time

        处理时间为 105 10 − 5 s数量级,这样一来,上面的问题就解决了。

推荐阅读

  • NumPy Data Types
  • Understanding Data Types in Python
  • Buffer Protocol

 
 
 
 
 

你可能感兴趣的:(Python学习笔记,ROS学习)