D435深度信息TCP传输–struct编解码
Preface
Intel Realsense D435深度相机获取的RGB数据是uint8,转化为字节后为1个字节;而深度信息是uint16,转化为字节后变成了2个字节。
在一般的RGB-D图像可视化中,都将uint16的深度图像转化为uint8,然后使用opencv将单通道的深度图转化为伪彩色图,与RGB拼接后进行可视化。
# 深度图转化为伪彩色图
depth_colormap=cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET) # (480,640,3)
# 将彩色图与深度图拼接在一起
images = np.hstack((color_image, depth_colormap)) #(480,1280,3)
在TCP传输中,需要将数据转化为字节流,然后在接收端进行解码,使用opencv的图像编解码可以实现远端深度相机的图像采集,但是需要先将16位的深度信息转化为8位,在编解码过程中,深度值都被压缩到255以内,造成信息丢失。
struct
python的内置模块struct可以实现将python数据转化为字节流,应用于网络传输中。同时能够按照指定格式将字节流转换为python指定的数据类型。
struct定义了pack、pack_into、unpack、unpack_from、iter_unpack和calcsize函数。
在C语言中,unsigned short表示16位无符号短整型,表示范围为0~65535,在struct的编解码中,需要指定数据编码格式,‘H’即代表C类型是unsigned short,编码后为2个字节大小。
struct还定义了Struct类,包括pack(v1, v2, …)、pack_into()和unpack(buffer)、format等方法和属性。
class struct.Struct(format):
def pack(v1, v2, ...):
pass
def unpack(buffer):
pass
...
示例:
import struct
format_ = 'H' # 格式字符串
s = struct.Struct(format_)
a = 1896
# 编码
a_byte = s.pack(a)
# 解码
b = s.unpack(a_byte)
注意传入的每一个数据都需要指定一个编码格式,比如编码一个整数,格式字符串为‘H’,编码两个整数,格式字符串应为‘HH’。
深度信息形状为(480, 640),总共包含30720个数据,因此对应的格式字符串需要指定30720个编码格式。用一个函数根据数据长度自适应的生成格式字符串:
def str_append(s, n):
out_str = ''
i = 0
while i < n:
out_str += s
i += 1
return out_str
编码RGB和深度信息
RGB图像为(480, 640, 3)(dtype=uint8),深度图为(480, 640)(dtype=16);转化前先分别将两个数据变成一维,再进行连接;最终对整合的一维数据进行编码。
import numpy as np
import struct
depth_image = np.asanyarray(depth_frame.get_data()) # (480, 640)
color_image = np.asanyarray(color_frame.get_data()) # (480, 640, 3)
depth_image = depth_image.reshape(-1) # 307200
color_image = color_image.reshape(-1) # 921600
rgbd_data = np.hstack(depth_image, color_image) # 1228800
# 编码
format_ = str_append() # 写数据格式及长度对应的编码格式
s = struct.Struct(format_)
bytedata = s.pack(*rgbd_data)
# 解码
data = s.unpack(bytedata)