作者 | yunswj
编辑 | 3D视觉开发者社区
✨如果觉得文章内容不错,别忘了三连支持下哦~
奥比中光的相机是通过Type-C连接的,目前直接获得码流的SDK是OpenNi2,但是哇,这个SDK是13年就不维护了。年久失修吗?不,宝刀未老!各家的RGBD相机都适配了这个SDK,上层的接口给开发人员使用,下层的驱动层给厂家适配。
但是哇,我就是怕C++,我不是不会,就是讨厌样板代码,那我肯定想办法搞个Python的接口~
时间紧,任务重,从头写来不及,我只能改装啦!
首先安装:
pip install primesense
我们就使用这个库的openni2的的接口。
里面包装了很多的C++方法
我们就看一个方法就好,大概就知道实现方法啦!
接下来就是更换我们的驱动了,方法有了,接口也有了,缺最终的引擎。
建立一个这样的文件夹
把我们OrbbecViewer的dll文件放成我上面的样子
import numpy as np
import cv2
from primesense import openni2
from primesense import _openni2 as c_api
openni2.initialize("./Redist")
if (openni2.is_initialized()):
print("openNI2 initialized")
else:
print("openNI2 not initialized")
写个初始化的代码。
![图片alt](https://developer-orbbec-oss.oss-cn-shenzhen.aliyuncs.com/forum/20220308112944.png ''图片title'')
成功
from primesense import openni2
from primesense import _openni2 as c_api
import numpy as np
import cv2
openni2.initialize("./Redist")
dev = openni2.Device.open_any()
print(dev.get_device_info())
depth_stream = dev.create_depth_stream()
depth_stream.start()
while True:
# 显示深度图
frame = depth_stream.read_frame()
dframe_data = np.array(frame.get_buffer_as_triplet()
).reshape([480, 640, 2])
dpt1 = np.asarray(dframe_data[:, :, 0], dtype='float32')
dpt2 = np.asarray(dframe_data[:, :, 1], dtype='float32')
dpt2 *= 255
dpt = dpt1 + dpt2
cv2.imshow('dpt', dpt)
# 按下q键退出循环
key = cv2.waitKey(10)
if int(key) == 113:
break
# 人走带门,关闭设备
depth_stream.stop()
dev.close()
输出深度流
OniDeviceInfo(uri = b’\?\usb#
vid_2bc5
&
pid_0614#6&5dea7dd&0&2#
{c3b5f022-5a42-1980-1909-ea72095601b1}’,
vendor = b’Orbbec’,
name = b’Astra’,
usbVendorId = 11205,
usbProductId = 1556)
输出的信息,可以看到输得正确
输出了
接下来的是,来自于3D视觉开发者社区论坛的硬货:悟空分享的OpenNI协议小结
1.OpenNI协议命令是基于USB控制传输,使用默认的控制端点0;而图像数据传输是基于USB实现的批量传输,而后者根据取决于数据类型。图像传输端点:
2.OpenNI协议命令
使用默认的控制端点HOST使用USB默认端点0发送请求,协议包含一个头部信息,结构如下:
typedef struct{
uint16_t nMagic;
uint16_t nSize;
uint16_t nOpcode;
uint16_t nId;
}ProtocolHeader;
其中,Request: nMagic=0x4252, Response: nMagic=0x4d47, nSize表示数据长度,nOpcode表示命令类型,如获取版本号、设置参数等,nId表示包号,设备应答时就使用接收到Request中的nId;
数据部分限制最大长度为512字节。具体实现在protocol.c中,命令类型定义在protocol.h中。
3.OpenNI图像传输
OpenNI支持IR/DEPTH/RGB传输,协议与UVC类似,OpenNI 12字节头部信息定义:
根据USB工作模式,在USB3.0下,每帧最大长度为1024字节,USB2.0则为512字节。
这里需要注意的是:
大小端,package_id 是小端,而package_size和TimeStamp是大端;
帧包与包号:package_id表示包号,每个传输完一个包加1;TimeStamp表示帧号,每传输完一帧加1,但每帧的第一个包,TimeStamp=0;
包长度,SOF和Normal均为0xC00,而最后一包取决于实际所剩长度last_size,则pakage_size=last_size+12.
后面通过融合,可以获取到点云图。
我下面发一段demo,感兴趣可以直接运行一下:
import open3d as o3d
import matplotlib.pyplot as plt
if __name__ == "__main__":
print("Read Redwood dataset")
color_raw = o3d.io.read_image("color.jpg")
depth_raw = o3d.io.read_image("depth.png")
rgbd_image = o3d.geometry.create_rgbd_image_from_color_and_depth(
color_raw, depth_raw)
print(rgbd_image)
plt.subplot(1, 2, 1)
plt.title('grayscale image')
plt.imshow(rgbd_image.color)
plt.subplot(1, 2, 2)
plt.title('depth image')
plt.imshow(rgbd_image.depth)
plt.show()
pcd = o3d.geometry.create_point_cloud_from_rgbd_image(
rgbd_image,
o3d.camera.PinholeCameraIntrinsic(
o3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault))
pcd.transform([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
o3d.io.write_point_cloud("test.pcd", pcd)
o3d.visualization.draw_geometries([pcd])
另外,在ubuntu上也可以这样操作,上层的API是一样的,使用在Linux平台下的二进制驱动文件的路径。
版权声明:本文为奥比中光3D视觉开发者社区特约作者授权原创发布,未经授权不得转载,本文仅做学术分享,版权归原作者所有,若涉及侵权内容请联系删文
3D视觉开发者社区是由奥比中光给所有开发者打造的分享与交流平台,旨在将3D视觉技术开放给开发者。平台为开发者提供3D视觉领域免费课程、奥比中光独家资源与专业技术支持。点击加入3D视觉开发者社区,和开发者们一起讨论分享吧~
也可移步微信关注官方公众号3D视觉开发者社区 ,获取更多干货知识哦~