RGBD(realsense, kinect等) 相机 储存深度图(depth_map)视频流(即uint16视频)

如果你使用的是realsense相机可以参见我封装好的代码: python RealSense相机 二次封装工具包_tycoer的博客-CSDN博客

问题: 最近在做 室内场景的三维重建, 需要同时储存深度图(depth_map)视频流和彩色图(color_img)的视频流, 即储存一系列连续的帧. realsense 提供了 .bag 文件格式用于记录视频流, 但该文件占用空间极大, 基本大概5~6秒的视频需要1G上下的硬盘空间(因为realsense在记录.bag文件时会同时记录多个视频流, 包含深度,彩色 , 左右emiter 的视频流, 当然也可以调api让其少记录几个视频流,但文件依旧很大), 故需要其他的一种文件格式来记录视频流以获得更小的储存空间:

方案如下(python 实现):

color_img.avi : 采用opencv 中的 cv2.VideoWriter直接以.avi格式录制, 以及cv2.VideoCapture(视频拆分) ;

depth_map.h5: 采用h5文件(由于depth_map采集出来的都是uint16的格式, 然而opencv不支持uint16的视频录制,仅支持uint8视频录制, 本人曾尝试多种编码例如'H265'的,但均不能正常录制, github上有一篇说是可以采取.oni格式, 但这个未尝试不置评): 很重要的一条是该depth_map需要使用cv2.imencode 进行编码, h5文件大小便会急剧下降, 代码:

#保存
import cv2
import h5py # 版本3.2.1

# 初始化 h5 文件 
h5=h5py.File('./depth_map.hdf5','w') #创建一个空的h5文件

# 初始化 avi文件
fourcc = cv2.VideoWriter_fourcc(*'XVID')
avi = cv2.VideoWriter('color_img.avi',fourcc, 30, (1280, 720),True)
# cv2.VideoWriter参数:
# 1-需保存视频的文件名
# 2-解码参数
# 3-fps帧率
# 4-分辨率
# 5-True为彩色视频, False为黑白视频

id = 0
while True:
    # 这里可能有一大段从相机api获取depth_map, color_img的代码
    # 例如:
    # depth_map, color_img = camera.get_frame() # camera.get_frame()是我瞎编的, 根据你自己        
    # 使用的相机api来写吧
    # depth_map, color_img 应为 numpy.ndarray
    # depth_map的典型shape为 (720, 1280) uint16, color_img的典型shape为 (720, 1280, 3) uint8
    # 把彩色图写入 avi
    avi.write(color_img)
    # 把深度图写入 h5
    res, depth_map_encode=cv2.imencode('.png',depth_map) # 编码depth_map 将depth_map 传入, res为bool, 用于判断是否编码成功
    # .png的原因: opencv 支持将16位图片写入.png, .jpg仅能写入8位图片
    h5[str(id)] = depth_map_encode # h5类似于字典, 即key 对应 data, 并且key不能重复
    id += 1
    
    '''
    一般会设置某个按键 让相机退出视频流并结束循环
    if 按键:
        break
    '''
h5.close() #关闭文件

将h5文件拆解成图片:

​
import os
import h5py # 版本3.2.1
import cv2
import numpy as np
def h52img(h5_path,save_dir='./'):
    # h5_path: h5文件路径
    # save_dir: 图片需要存入文件夹
    h5 = h5py.File(h5_path, 'r') 
    os.makedirs(save_dir,exist_ok=True)
    for key in h5.keys():
        img=cv2.imdecode(np.array(h5[key]),-1)  # 解码
        img_name = os.path.join(save_dir, key)  if key.endswith('.png') else os.path.join(save_dir, key +'.png' )# 判断文件名是否以 '.png' 结尾
        cv2.imwrite(img_name ,img)
    h5.close()

​

另外, 如果后续 使用opencv接口 cv2.imread读取 .png文件, 应设置flags = cv2.IMREAD_UNCHANGED 即 img = cv2.imread('xxx.png', flags = cv2.IMREAD_UNCHANGED), 才能正确的将 '.png' 文件读取为uint16格式单通道, 如果未设置flags = cv2.IMREAD_UNCHANGED 即 img=cv2.imread('xxx.png'), 将导致读取的'.png'文件为uint8三通道.

结果:

RGBD(realsense, kinect等) 相机 储存深度图(depth_map)视频流(即uint16视频)_第1张图片

可以看到大约7秒的视频(二者分辨率均为1280x720, 帧率30fps), color_img.avi 大约仅有7M, depth_map.h5 大约仅有13.5M 

你可能感兴趣的:(音视频,opencv,计算机视觉)