Astra 3D相机 - OpenNI2 SDK

1. Astra S 3D相机

Astra S 是目前性价比很高的消费级单目结构光3D相机,适合入门3D点云处理使用。大家可以在我们的淘宝店铺 阿凯爱玩机器人 购买。

Astra S 淘宝购买链接 奥比中光深度相机3D机器视觉结构光立体摄像头三维点云体感摄影头

如果需要精度更高的工业3D相机,可以选购店铺中的 RVC X Mini 双目结构光3D相机

本课程的配套源码,可以联系阿凯老师获取。

2. 概要

本篇文章为 OpenNI2 Python SDK 使用示例,如无特殊需求,则不需要学习OpenNI2的SDK使用。因为在阿凯老师开发的 Astra Open3D Python SDK 已经对其做了二次封装。

配套实验代码路径: 03.Astra-3D相机OpenNI2测试样例

共提供了三个OpenNI2的SDK使用示例。实验代码是基于 Jupyter Notebook 的,请使用 Jupyter Notebook Web IDE 打开。

image-20220720173438423

3. 修改OpenNI2路径

导入依赖

import numpy as np
import cv2
from openni import openni2
from openni import _openni2 as c_api
from matplotlib import pyplot as plt

将 dll_directories 的路径改成自己的实际安装路径

需要注意的是在Windows下,路径中文件夹与文件夹之间,需要使用两个反斜杠 \\

# 在Windows下必须配置OpenNI2动态链接库的路径
# OpenNI2初始化
openni2.initialize(dll_directories="D:\\KyleSoftware\\OpenNI2\\libs")
# Linux下, 无序填写dll_directories
# openni2.initialize()
# 查看设备ID列表
list_devices = openni2.Device.enumerate_uris()
print(list_devices)

# 打开一个设备
dev = openni2.Device.open_any()

# 打印设备信息
dev.get_device_info()

4. OpenNI2 - 读取2D图像

4.1 导入依赖

import numpy as np
import cv2
from openni import openni2
from openni import _openni2 as c_api
from matplotlib import pyplot as plt

4.2 设备查找

# OpenNI2初始化
openni2.initialize()

# 查看设备ID列表
list_devices = openni2.Device.enumerate_uris()
print(list_devices)

# 打开一个设备
dev = openni2.Device.open_any()

# 打印设备信息
dev.get_device_info()

输出日志:

[b'2bc5/[email protected]/4']
OniDeviceInfo(uri = b'2bc5/[email protected]/4', vendor = b'Orbbec', name = b'Astra', usbVendorId = 11205, usbProductId = 1026)

4.3 创建彩图数据流

# 彩图数据流
color_stream = dev.create_color_stream()

# 查看视频流里面支持的模式
video_modes_list = color_stream.get_sensor_info().videoModes
print(video_modes_list)

输出日志:

[OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_RGB888, resolutionX = 320, resolutionY = 240, fps = 15), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_YUV422, resolutionX = 320, resolutionY = 240, fps = 15), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_RGB888, resolutionX = 320, resolutionY = 240, fps = 30), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_YUV422, resolutionX = 320, resolutionY = 240, fps = 30), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_RGB888, resolutionX = 320, resolutionY = 240, fps = 60), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_YUV422, resolutionX = 320, resolutionY = 240, fps = 60), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_RGB888, resolutionX = 640, resolutionY = 480, fps = 30), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_YUV422, resolutionX = 640, resolutionY = 480, fps = 30), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_RGB888, resolutionX = 1280, resolutionY = 960, fps = 30), OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_YUV422, resolutionX = 1280, resolutionY = 960, fps = 30)]

# 注1: 分辨率跟帧率不能乱写,要在上述的列表内的才可以。 
# 注2: Astra S是支持1280 x 960分辨率的
# 但是这个配置,得到的图像都是噪点,不是有效图像
# IMG_WIDTH = 1280
# IMG_HEIGHT = 960
# FPS = 30

IMG_WIDTH = 640
IMG_HEIGHT = 480
FPS = 30

# 设置视频流属性
# - 像素格式, 分辨率, 帧率
video_mode = c_api.OniVideoMode(pixelFormat = c_api.OniPixelFormat.ONI_PIXEL_FORMAT_RGB888, \
                resolutionX=IMG_WIDTH, resolutionY=IMG_HEIGHT,fps=FPS)
print(video_mode)
color_stream.set_video_mode(video_mode)

输出日志:

OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_RGB888, resolutionX = 640, resolutionY = 480, fps = 30)

# 开启数据流
color_stream.start()

4.4 读取图像

# 获取RGB彩图数据
color_frame = color_stream.read_frame()
# 转换为Numpy的数组
img_rgb = np.uint8(color_frame.get_buffer_as_uint8()).reshape([IMG_HEIGHT, IMG_WIDTH, 3])
plt.imshow(img_rgb)

# 转换为bgr格式
img_bgr = img_rgb[:, :, ::-1]

4.5 关闭设备

openni2.unload()
dev.close()

5. OpenNI2 - 读取深度图

5.1 导入依赖

import numpy as np
import cv2
from openni import openni2
from openni import _openni2 as c_api
from matplotlib import pyplot as plt

5.2 设备查找

# OpenNI2初始化
openni2.initialize()
# 打开一个设备
dev = openni2.Device.open_any()

5.3 创建深度图数据流

# 深度图数据流
depth_stream = dev.create_depth_stream()

# 查看视频流里面支持的模式
video_modes_list = depth_stream.get_sensor_info().videoModes
for video_mode in video_modes_list:
    print(video_mode)

输出日志:

OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_1_MM, resolutionX = 160, resolutionY = 120, fps = 30)
OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_100_UM, resolutionX = 160, resolutionY = 120, fps = 30)
OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_1_MM, resolutionX = 320, resolutionY = 240, fps = 30)
OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_100_UM, resolutionX = 320, resolutionY = 240, fps = 30)
OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_1_MM, resolutionX = 640, resolutionY = 480, fps = 30)
OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_100_UM, resolutionX = 640, resolutionY = 480, fps = 30)
OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_1_MM, resolutionX = 1280, resolutionY = 1024, fps = 7)
OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_100_UM, resolutionX = 1280, resolutionY = 1024, fps = 7)

IMG_WIDTH = 640
IMG_HEIGHT = 480
FPS = 30

# 设置视频流属性
# - 像素格式, 分辨率, 帧率
# ONI_PIXEL_FORMAT_DEPTH_1_MM 的含义,是深度图的单位是1mm
video_mode = c_api.OniVideoMode(pixelFormat = c_api.OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_1_MM, \
                resolutionX=IMG_WIDTH, resolutionY=IMG_HEIGHT,fps=FPS)
print(video_mode)
depth_stream.set_video_mode(video_mode)

输出日志:

OniVideoMode(pixelFormat = OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_1_MM, resolutionX = 640, resolutionY = 480, fps = 30)

# 开启数据流
depth_stream.start()

5.4 读取图像

# 获取深度图
depth_frame = depth_stream.read_frame()
depth_frame_data = depth_frame.get_buffer_as_uint16()
depth_img = np.ndarray((depth_frame.height, depth_frame.width), dtype=np.uint16, buffer=depth_frame_data)
plt.imshow(depth_img, cmap="gray")

5.5 关闭设备

openni2.unload()
dev.close()

6. OpenNI2 - 获取对齐后的RGB图与深度图

6.1 导入依赖

import numpy as np
import cv2
from openni import openni2
from openni import _openni2 as c_api
from matplotlib import pyplot as plt

6.2 配置参数

# 图像宽度
IMG_WIDTH = 640
# 图像高度
IMG_HEIGHT = 480
# 帧率
FPS = 30
# 彩图的像素格式, 颜色空间为RGB
COLOR_PIXEL_FORMAT = c_api.OniPixelFormat.ONI_PIXEL_FORMAT_RGB888
# 深度图的像素格式, Uint16格式,单位是1mm
DEPTH_PIXEL_FORMAT = c_api.OniPixelFormat.ONI_PIXEL_FORMAT_DEPTH_1_MM

6.3 设备查找

# OpenNI2初始化
openni2.initialize()
# 打开一个设备
dev = openni2.Device.open_any()

输出日志:

[b'2bc5/[email protected]/4']

6.4 创建数据流

# 彩图数据流
color_stream = dev.create_color_stream()
# 深度图数据流
depth_stream = dev.create_depth_stream()

6.5 配置数据流

# 配置参图数据流格式
color_video_mode = c_api.OniVideoMode(pixelFormat = COLOR_PIXEL_FORMAT, \
                resolutionX= IMG_WIDTH, resolutionY = IMG_HEIGHT, fps = FPS)
color_stream.set_video_mode(color_video_mode)
# 配置深度图数据流格式
depth_video_mode = c_api.OniVideoMode(pixelFormat = DEPTH_PIXEL_FORMAT, \
                resolutionX=IMG_WIDTH, resolutionY = IMG_HEIGHT, fps=FPS)
depth_stream.set_video_mode(depth_video_mode)
# 开启数据流
color_stream.start()
depth_stream.start()
# RGB图与深度图对齐
dev.set_image_registration_mode(True)
# 另深度图对齐RGB图
dev.set_image_registration_mode(openni2.IMAGE_REGISTRATION_DEPTH_TO_COLOR)
# 设置深度图与RGB图同步
dev.set_depth_color_sync_enabled(True)

6.6 获取彩图与深度图

def color_frame2rgb_img(color_frame):
    '''彩图帧转换为彩图-RGB色彩空间'''
    # 转换为Numpy的数组
    img_rgb = np.uint8(color_frame.get_buffer_as_uint8()).reshape([IMG_HEIGHT, IMG_WIDTH, 3])
    return img_rgb

def depth_frame2depth_img(depth_frame):
    '''深度图帧转换为深度图-np.float32'''
    depth_frame_data = depth_frame.get_buffer_as_uint16()
    depth_img = np.ndarray((depth_frame.height, depth_frame.width), dtype=np.uint16, buffer=depth_frame_data)
    return np.float32(depth_img)
plt.figure(figsize=(10, 20))
color_frame = color_stream.read_frame()
color_img = color_frame2rgb_img(color_frame)

depth_frame = depth_stream.read_frame()
depth_img = depth_frame2depth_img(depth_frame)

plt.subplot(1, 2, 1)
plt.imshow(color_img)
plt.subplot(1, 2, 2)
plt.imshow(depth_img, cmap="gray")

6.7 关闭设备

openni2.unload()
dev.close()