提示:上一篇博客(基础篇1)链接:Realsense深度相机+pyqt5+应用案例(基础篇1)
本篇将在上一篇博客的基础上继续介绍D435i深度相机的相关操作,主要包括深度图的后处理和相机姿态的绘制。
由于受限于所使用的场景,相机获取的深度图往往存在一些黑洞,尤其是在物体边缘、光滑的物体表面等,官方API提供了四种后处理的算法可以对深度图进行优化,包括:孔填充、抽取滤波、空间滤波、时间滤波。
这里我们以最常用的孔填充为例进行介绍,首先在窗体类的__init__函数中加入以下代码:
# 为每个操作设置tag
self.tag_hole_filling = 0
# 定义孔填充过滤器
self.hole_filling = rs.hole_filling_filter()
接下来,在setupUi中新增一个button控件用于开启和关闭孔填充:
# 开启孔填充的按钮
self.button_hole_filling = QtWidgets.QPushButton(self.centralwidget)
self.button_hole_filling.setGeometry(QtCore.QRect(260, 560, 200, 50))
self.button_hole_filling.setStyleSheet("color: rgb(255, 255, 255);\n"
"border-color: rgb(0, 0, 0);\n"
"background-color: rgb(50,50,237);")
self.button_hole_filling.setFlat(False)
self.button_hole_filling.setObjectName("button_hole_filling")
self.button_hole_filling.setFont(QFont("宋体", 12, QFont.Bold))
并在retranslateUi中设置控件文本
self.button_hole_filling.setText(_translate("MainWindow", "Hole filling"))
在slot_init中建立与self.button_hole_filling_click函数的通信:
self.button_hole_filling.clicked.connect(self.button_hole_filling_click)
然后编写self.button_hole_filling_click函数,用于控制变量self.tag_hole_filling的取值,并更改控件显示的文本,变量置1时开启孔填充,置0时关闭孔填充:
def button_hole_filling_click(self):
if self.tag_hole_filling == 0:
self.tag_hole_filling = 1
self.button_hole_filling.setText(u'Close Hole filling')
else:
self.tag_hole_filling = 0
self.button_hole_filling.setText(u'Hole filling')
最后,在get_photo函数中,调用先前定义的孔填充对深度图进行处理:
# 对深度图像进行后处理
if self.tag_hole_filling == 1:
depth_frame = self.hole_filling.process(depth_frame)
对比图如下图所示,可以发现填充后黑洞不再出现了。
关于其余的滤波器的使用,可以参考文末资源包链接。
如图所示,在Intel官方提供的Intel RealSense Viewer的界面中可以实时的看到相机当前的姿态,其中红轴代表X轴、绿轴代表Y轴、蓝轴代表Z轴,白色线段代表相机,其朝向代表相机姿态。
有时候在我们自己设计UI界面的时候也希望能够看到类似的姿态图,首先需要说明的是,上图的坐标系是RealsenseD435i内定的,其Z轴指向相机后方,Y轴铅锤向下,我们希望Z轴是指向前方的,因此以Y轴为基准旋转上述坐标系180°,得到如下的相机坐标系:
其中俯仰角为相机Zc轴与世界坐标系XOZ之间的夹角,以相机抬头为正;滚转角为相机Yc轴与包含相机Zc轴的铅垂面之间的夹角,以相机向右倾斜为正;偏航角始终为0,是因为此处世界坐标系定义的Z轴与相机轴Zc处于同一铅垂面中 。
根据重力加速度在三个方向上的分量gx,gy,gz,可以计算出相机的当前姿态:
# 将相机当前姿态绘制到界面上
def IMU_visdom(self, gx, gy, gz):
# 定义画布
canvas_size = 512
canvas = np.zeros((canvas_size, canvas_size, 3), dtype="uint8")
# 绘制坐标轴,坐标原点位于(256,256)
# Y轴向下
cv2.line(canvas, (256, 256), (256, 450), (0, 255, 0), 2)
cv2.line(canvas, (256, 450), (256 - 5, 450 - 10), (0, 255, 0), 2)
cv2.line(canvas, (256, 450), (256 + 5, 450 - 10), (0, 255, 0), 2)
cv2.putText(canvas, 'Y', (266, 450), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
# Z轴左下
cv2.line(canvas, (256, 256), (88, 353), (0, 0, 255), 2)
cv2.line(canvas, (88, 353), (88 + 10, 353), (0, 0, 255), 2)
cv2.line(canvas, (88, 353), (88 + 5, 353 - 10), (0, 0, 255), 2)
cv2.putText(canvas, 'Z', (76, 359), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
# X轴左上
cv2.line(canvas, (256, 256), (88, 159), (255, 0, 0), 2)
cv2.line(canvas, (88, 159), (88 + 10, 159), (255, 0, 0), 2)
cv2.line(canvas, (88, 159), (88 + 5, 159 + 10), (255, 0, 0), 2)
cv2.putText(canvas, 'X', (83, 154), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
# 我们认为194个像素点为坐标轴长度,对应重力加速度大小,这里取10, 首先计算各个分量在对应坐标轴上的距离
dis_y = (256, int(gy / 10 * 194))
dis_x = (int(gx / 10 * 194 / 2 * 1.732), int(gx / 10 * 194 / 2))
dis_z = (int(gz / 10 * 194 / 2 * 1.732), int(gz / 10 * 194 / 2))
cv2.circle(canvas, (256, 256 - dis_y[1]), 3, color=(255, 255, 255))
cv2.circle(canvas, (256 - dis_x[0], 256 - dis_x[1]), 3, color=(255, 255, 255))
cv2.circle(canvas, (256 - dis_z[0], 256 + dis_z[1]), 3, color=(255, 255, 255))
# 计算出相机末端位置
point_xyz = (256 + dis_x[0] + dis_z[0], 256 + dis_x[1] - dis_z[1] + dis_y[1])
# 绘制代表相机姿态的线段
cv2.line(canvas, (256, 256), point_xyz, (255, 255, 255), 2)
showImage2 = QtGui.QImage(canvas.data, canvas.shape[1], canvas.shape[0], QtGui.QImage.Format_RGB888)
self.label_show_camera2.setPixmap(QtGui.QPixmap.fromImage(showImage2))
上述代码在 get_photo函数中调用即可:
gx, gy, gz = accel_info.x, accel_info.y, accel_info.z
# 将相机姿态绘制到界面上
self.IMU_visdom(gx, gy, gz)
效果如下图所示,可以看到我们绘制的相机姿态Z轴是朝前的。
本篇主要介绍了RealsenseD435i深度相机的深度图后处理操作和相机姿态的绘制,该部分内容需要在,Realsense深度相机+pyqt5+应用案例(基础篇1)的基础上进行操作,完整项目资源包将在近期上传于CSDN并附上链接,敬请期待!