文章可以转载,但是必须表明出处!
本文使用Intel Realsense D435深度相机,拍摄RGB颜色图及16位深度图。
同时实现了以深度图和RGB颜色图为图像帧的视频显示、录制与保存。
以下为总体程序:
'''
使用realsense相机录制视频
'''
#!/usr/bin/env python
# coding=utf-8
import time
import h5py # 深度图格式所在库
import pyrealsense2 as rs
import numpy as np
import cv2
import os
class Camera(object):
'''
realsense相机处理类
'''
def __init__(self, width=1280, height=720, fps=30): # 图片格式可根据程序需要进行更改
self.width = width
self.height = height
self.pipeline = rs.pipeline()
self.config = rs.config()
self.config.enable_stream(rs.stream.color, self.width, self.height, rs.format.bgr8, fps)
self.config.enable_stream(rs.stream.depth, self.width, self.height, rs.format.z16, fps)
# self.config.enable_stream(rs.stream.infrared, 1, self.width, self.height, rs.format.y8, fps)
# self.config.enable_stream(rs.stream.infrared, 2, self.width, self.height, rs.format.y8, fps)
self.pipeline.start(self.config) # 获取图像视频流
def get_frame(self):
frames = self.pipeline.wait_for_frames() # 获得frame (包括彩色,深度图)
colorizer = rs.colorizer() # 创建伪彩色图对象
depth_to_disparity = rs.disparity_transform(True)
disparity_to_depth = rs.disparity_transform(False)
# 创建对齐对象
align_to = rs.stream.color # rs.align允许我们执行深度帧与其他帧的对齐
align = rs.align(align_to) # “align_to”是我们计划对齐深度帧的流类型。
aligned_frames = align.process(frames)
# 获取对齐的帧
aligned_depth_frame = aligned_frames.get_depth_frame() # aligned_depth_frame是对齐的深度图
color_frame = aligned_frames.get_color_frame()
# left_frame = frames.get_infrared_frame(1)
# right_frame = frames.get_infrared_frame(2)
color_image = np.asanyarray(color_frame.get_data())
colorizer_depth = np.asanyarray(colorizer.colorize(aligned_depth_frame).get_data())
depthx_image = np.asanyarray(aligned_depth_frame.get_data()) # 原始深度图
# left_frame = np.asanyarray(left_frame.get_data())
# right_frame = np.asanyarray(right_frame.get_data())
return color_image, depthx_image, colorizer_depth
# left_frame, right_frame
def release(self):
self.pipeline.stop()
if __name__ == '__main__':
# 视频保存路径
os.mkdir(f'D://Realsense//Video//{int(time.time())}')
video_path = f'D://Realsense//Video//{int(time.time())}//targetvideo_rgb.mp4'
video_depthc_path = f'D://Realsense//Video//{int(time.time())}//targetvideo_depthcolor.mp4'
video_depth16_path = f'D://Realsense//Video//{int(time.time())}//targetvideo_depth.h5'
# video_left_path = f'D://Realsense//Video//Stereo_left//{int(time.time())}_left.mp4'
# video_right_path = f'D://Realsense//Video//Stereo_right//{int(time.time())}_right.mp4'
# 初始化参数
fps, w, h = 30, 1280, 720
# fps, w, h = 30, 640, 480
mp4 = cv2.VideoWriter_fourcc(*'mp4v') # 视频格式
# 视频保存而建立对象
# wr_left = cv2.VideoWriter(video_left_path, mp4, fps, (w, h), isColor=False)
# wr_right = cv2.VideoWriter(video_right_path, mp4, fps, (w, h), isColor=False)
# 完成相机初始化
cam = Camera(w, h, fps)
flag_V = 0
idx = 0
id = 0
print('录制视频请按: s, 保存视频或退出请按:q')
while True:
# 读取图像帧,包括RGB图和深度图
color_image, depthxy_image, colorizer_depth = cam.get_frame()
cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
cv2.imshow('RealSense', color_image)
key = cv2.waitKey(1)
if key & 0xFF == ord('s') :
flag_V = 1
# 创建视频文件
wr = cv2.VideoWriter(video_path, mp4, fps, (w, h), isColor=True)
wr_colordepth = cv2.VideoWriter(video_depthc_path, mp4, fps, (w, h), isColor=True)
wr_depth = h5py.File(video_depth16_path, 'w')
print('...录制视频中...')
if flag_V == 1:
# 保存图像帧
wr.write(color_image) # 保存RGB图像帧
wr_colordepth.write(colorizer_depth) # 保存相机自身着色深度图
# wr_left.write(left_image) # 保存左帧深度图
# wr_right.write(right_image) # 保存右帧深度图
# res, depth16_image = cv2.imencode('.png', depthxy_image) # 深度图解码方式一:点云小,但是出错
depth16_image = cv2.imencode('.png', depthxy_image)[1] # 深度图解码方式二:文件较大,测试稳定
depth_map_name = str(id).zfill(5) + '_depth.png'
# wr_depth[str(idx).zfill(5)] = depth16_image # 储存方法:1 前3帧和没11帧出现高质量点云,其他错误
wr_depth[depth_map_name] = depth16_image # 储存方法:2 所有点云准确,但是点云质量不高
idx += 1
id = id + 1
if key & 0xFF == ord('q') or key == 27:
cv2.destroyAllWindows()
print('...录制结束/直接退出...')
break
# 录制完毕,释放对象
wr.release()
wr_colordepth.release()
# wr_left.release()
# wr_right.release()
wr_depth.close()
cam.release()
print(f'若保存视频,则视频保存在:{video_path}')
程序阅读如下:
1.库引用
import time # 获取时间信息,用于创建不同文件名称的文件夹
import h5py # 深度图格式所在库
import pyrealsense2 as rs # 相机集成库,用于相机初始化与相机视频流获取
import numpy as np # 将图像帧转换为数据信息以进行图像保存
import cv2 # 视觉图像库,用于保存图像帧与视频
import os # 系统操作库,用于系统路径寻觅与文件夹创建
2.相机初始化函数
class Camera(object):
'''
realsense相机处理类
'''
def __init__(self, width=1280, height=720, fps=30): # 图片格式可根据程序需要进行更改
self.width = width #获取图像帧设置
self.height = height
self.pipeline = rs.pipeline() #开放图像帧管道
self.config = rs.config() #配置初始化
self.config.enable_stream(rs.stream.color, self.width, self.height, rs.format.bgr8, fps)
self.config.enable_stream(rs.stream.depth, self.width, self.height, rs.format.z16, fps)
# self.config.enable_stream(rs.stream.infrared, 1, self.width, self.height, rs.format.y8, fps)
# self.config.enable_stream(rs.stream.infrared, 2, self.width, self.height, rs.format.y8, fps)
self.pipeline.start(self.config) # 获取图像视频流
3.图像流获取函数
def get_frame(self):
frames = self.pipeline.wait_for_frames() # 获得frame (包括彩色,深度图)
colorizer = rs.colorizer() # 创建伪彩色图对象
depth_to_disparity = rs.disparity_transform(True)
disparity_to_depth = rs.disparity_transform(False)
# 创建对齐对象
align_to = rs.stream.color # rs.align允许我们执行深度帧与其他帧的对齐
align = rs.align(align_to) # “align_to”是我们计划对齐深度帧的流类型。
aligned_frames = align.process(frames)
# 获取对齐的帧
aligned_depth_frame = aligned_frames.get_depth_frame() # aligned_depth_frame是对齐的深度图
color_frame = aligned_frames.get_color_frame()
# left_frame = frames.get_infrared_frame(1)
# right_frame = frames.get_infrared_frame(2)
color_image = np.asanyarray(color_frame.get_data()) # 将图像帧转换为矩阵格式
colorizer_depth = np.asanyarray(colorizer.colorize(aligned_depth_frame).get_data())
depthx_image = np.asanyarray(aligned_depth_frame.get_data())
# left_frame = np.asanyarray(left_frame.get_data())
# right_frame = np.asanyarray(right_frame.get_data())
return color_image, depthx_image, colorizer_depth # 返回图像数据值
# left_frame, right_frame
4.相机功能释放函数
def release(self):
self.pipeline.stop() # 停止相机拍摄
5.主程序:文件路径需要根据本地情况进行修改,图片格式根据需求进行修改
if __name__ == '__main__':
# 视频保存路径 路径需要根据本地情况进行修改
os.mkdir(f'D://Realsense//Video//{int(time.time())}')
video_path = f'D://Realsense//Video//{int(time.time())}//targetvideo_rgb.mp4'
video_depthc_path = f'D://Realsense//Video//{int(time.time())}//targetvideo_depthcolor.mp4'
video_depth16_path = f'D://Realsense//Video//{int(time.time())}//targetvideo_depth.h5'
# video_left_path = f'D://Realsense//Video//Stereo_left//{int(time.time())}_left.mp4'
# video_right_path = f'D://Realsense//Video//Stereo_right//{int(time.time())}_right.mp4'
# 初始化参数
fps, w, h = 30, 1280, 720
# fps, w, h = 30, 640, 480
mp4 = cv2.VideoWriter_fourcc(*'mp4v') # 视频格式
# 视频保存对象
# wr_left = cv2.VideoWriter(video_left_path, mp4, fps, (w, h), isColor=False)
# wr_right = cv2.VideoWriter(video_right_path, mp4, fps, (w, h), isColor=False)
# 相机初始化
cam = Camera(w, h, fps)
flag_V = 0
idx = 0
id = 0
print('录制视频请按: s, 保存视频或退出请按:q')
# 循环保存图像帧以建立视频
while True:
# 读取图像帧,包括RGB图和深度图
color_image, depthxy_image, colorizer_depth = cam.get_frame()
cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
cv2.imshow('RealSense', color_image)
key = cv2.waitKey(1)
if key & 0xFF == ord('s') :
flag_V = 1
# 创建视频文件
wr = cv2.VideoWriter(video_path, mp4, fps, (w, h), isColor=True)
wr_colordepth = cv2.VideoWriter(video_depthc_path, mp4, fps, (w, h), isColor=True)
wr_depth = h5py.File(video_depth16_path, 'w')
print('...录制视频中...')
if flag_V == 1:
# 保存图像帧
wr.write(color_image) # 保存RGB图像帧
wr_colordepth.write(colorizer_depth) # 保存相机自身着色深度图
# wr_left.write(left_image) # 保存左帧深度图
# wr_right.write(right_image) # 保存右帧深度图
depth16_image = cv2.imencode('.png', depthxy_image)[1] # 深度图解码
depth_map_name = str(id).zfill(5) + '_depth.png'
wr_depth[depth_map_name] = depth16_image # 所有点云准确
id = id + 1
if key & 0xFF == ord('q') or key == 27:
cv2.destroyAllWindows()
print('...录制结束/直接退出...')
break
# 录制完毕,释放视频对象
wr.release()
wr_colordepth.release()
# wr_left.release()
# wr_right.release()
wr_depth.close()
cam.release()
print(f'若保存视频,则视频保存在:{video_path}')
图片拍摄结果:
RGB图
16位深度图
伪彩色图
总结:
对比上一篇文章,该程序完整的保存了16位深度图,而非将其转换为8位深度图;
16位深度图保存采用的h5py格式,在后续进行图片抽帧时需要对应的图片抽取程序。
具体代码可查看我后续的博客