python使用深度摄像机绘制三维曲面图

采用深度摄像机获取深度数据

今天和大家分享之前一个项目中用于获取物体的深度数据来求体积的一些操作。
我使用的深度摄像机的型号是 Intel RealSense Depth Camera D435,关于该深度摄像机的使用大家可以 参考该博客

连接深度相机获取RGB图和深度图

首先调用我们后面会用到的一些库

import pyrealsense2 as rs
import numpy as np
import cv2
import pandas as pd
import os
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

调用完相关的库后设置深度相机获取数据的相关参数。
其中深度数据可获取的分辨率可达1280 x 720,其他先关参数可点击此处查看。

#configure depth and color streams
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.depth,640,480,rs.format.z16,30)#分辨率可更改为(1280 x 720)
config.enable_stream(rs.stream.color,640,480,rs.format.bgr8,30)
pipeline.start(config)

在设置完相关参数后调用深度相机获取彩色图数据和深度数据。

frames = pipeline.wait_for_frames()
depth_frames = frames.get_depth_frame()
color_frames = frames.get_color_frame()

为了使所获得的深度数据和彩色数据在位置上能够匹配,我们使用rs.align函数进行对其处理

#获取图像和深度信息
def get_imgData():
    # rs.align允许执行深度帧与其他帧的对齐
    # “align_to”是计划对齐深度帧的流类型
    align_to = rs.stream.color
    align = rs.align(align_to)
    frames = pipeline.wait_for_frames()
    align_frames = align.process(frames)
    depth_frames = align_frames.get_depth_frame()
    color_frames = align_frames.get_color_frame()
    depth_image = np.asanyarray(depth_frames.get_data())
    color_image = np.asanyarray(color_frames.get_data())
    return depth_image,color_image

之后调用之前写的函数,将获取的彩色数据和深度数据进行呈现

if __name__ == '__main__':
    while True:
        depth_image, color_image = get_imgData()
        depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
        cv2.imshow("color_image", color_image)
        cv2.imshow("depth_colormap", depth_colormap)
        key = cv2.waitKey(1)
        if key & 0xFF == ord('q') or key == 27:
            break
    cv2.destroyAllWindows()

获得图像结果如下
在这里插入图片描述

深度数据转三维曲面图

在获得相关的深度数据(depth_image)后,我们该如何来使用呢,就以上图为例,我们将所获取到的深度数据转换为三维曲面图,来查看被测物体的到摄像机之间的距离。
1、搭建绘制曲面图的相关函数

def draw_3D(depth_data):
    fig = plt.figure()
    ax = Axes3D(fig)
    x = np.arange(0,depth_data.shape[1],1)
    y = np.arange(0,depth_data.shape[0],1)
    ax.set_ylim(-10, depth_data.shape[0] + 10)
    ax.set_xlim(-10, depth_data.shape[1] + 10)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z/(mm)')
    X,Y = np.meshgrid(x,y)
    ax.plot_surface(X, Y, depth_data,cmap=plt.get_cmap('rainbow'))
    #ax.contour(X,Y,depth_data,zdir="y",offset=depth_data.shape[0],cmap=plt.get_cmap("rainbow"))
    #ax.contour(X,Y,depth_data,zdir="x", offset=0, cmap=plt.get_cmap("rainbow"))
    #plt.savefig(os.path.join(paths, 'Figure_3DX' + str(i)))#保存三维曲面图
    plt.show()

2、在主函数中调用该部分函数,当按下“s”键时便可获得相关的深度曲面图。

if __name__ == '__main__':
    while True:
        depth_image, color_image = get_imgData()
        depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
        cv2.imshow("color_image", color_image)
        cv2.imshow("depth_colormap", depth_colormap)

        key = cv2.waitKey(1)
        if key & 0xFF == ord('q') or key == 27:
            break
        if key & 0xFF == ord('s'):
            draw_3D(depth_image)
    cv2.destroyAllWindows()

在这里插入图片描述

目标区域选择

为了更直观的看到某个区域的深度数据,我们可以对彩色图进行区域选择,提取我们所需要的深度数据。

def select_img_data(select_data,color_frame,depth_frame):
    select_color = color_frame[select_data[1]:select_data[1] + select_data[3], select_data[0]:select_data[0] + select_data[2]]
    select_depth = depth_frame[select_data[1]:select_data[1] + select_data[3], select_data[0]:select_data[0] + select_data[2]]
    select_colormap = cv2.applyColorMap(cv2.convertScaleAbs(select_depth, alpha=0.03), cv2.COLORMAP_JET)
    #select_colormap = cv2.cvtColor(select_colormap, cv2.COLOR_BGR2GRAY)
    selects = np.hstack((select_color,select_colormap))
    cv2.namedWindow("choose_video",cv2.WINDOW_AUTOSIZE)
    cv2.imshow("choose_video", selects)
    return select_color,select_depth

我们在主函数中加入

if key & 0xFF == ord('s'):
    select_data = cv2.selectROI('color_image', color_image)
    color_image, depth_image = select_img_data(select_data, color_image, depth_image)
    choose_img = True

并对主函数做适当的调整

if __name__ == '__main__':
    choose_img = False
    while True:
        depth_image, color_image = get_imgData()
        depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
        cv2.imshow("color_image", color_image)
        cv2.imshow("depth_colormap", depth_colormap)
        key = cv2.waitKey(1)
        if key & 0xFF == ord('s'):
            select_data = cv2.selectROI('color_image', color_image)
            color_image, depth_image = select_img(select_data, color_image, depth_image)
            choose_img = True
        if key & 0xFF == ord('q') or key == 27:
            break
        if choose_img == True:
            draw_3D(depth_image)
            choose_img = False
    cv2.destroyAllWindows()

按下“s”后便可以框选我们所需要的相关区域的数据
在这里插入图片描述
选框区域内的彩色图和深度图
在这里插入图片描述
选框区域的深度曲面图。
在这里插入图片描述
由于深度相机(D435)在使用时,获得的深度数据中存在一些失效点,因此我们需要对失效部分的数据进行拟合处理和复原,如下图红色部分就是由于失效点造成。
在这里插入图片描述

失效点数据处理

所以我们需要对失效点的数据进行拟合处理和复原,经过拟合处理后的图像如下

在这里插入图片描述
相关的数据拟合及恢复处理操作将在下一篇博客中进行介绍。

  • 1
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
双目摄像机标定矫正是一个用于将两个摄像机像对准以进行三维重建的过程。Python中常用的双目摄像机标定矫正代码库是OpenCV,以下是一个简单的双目摄像机标定和矫正的Python代码示例: ```python import cv2 # 设置左右摄像机ID left_cam_id = 0 right_cam_id = 1 # 设置棋盘格尺寸 board_size = (9, 6) # 设置棋盘格物理尺寸(单位:mm) square_size = 30 # 设置像路径 left_path = 'left.jpg' right_path = 'right.jpg' # 初始化左右摄像机 left_cam = cv2.VideoCapture(left_cam_id) right_cam = cv2.VideoCapture(right_cam_id) # 设置棋盘格角点的三维坐标 obj_points = [] for i in range(board_size * board_size): obj_points.append((i // board_size * square_size, i % board_size * square_size, 0)) # 初始化像点和对象点数组 obj_points_list = [] img_points_left_list = [] img_points_right_list = [] while True: # 捕获像 ret_l, img_left = left_cam.read() ret_r, img_right = right_cam.read() # 检测棋盘格角点 ret_l, corners_left = cv2.findChessboardCorners(img_left, board_size) ret_r, corners_right = cv2.findChessboardCorners(img_right, board_size) if ret_l and ret_r: # 绘制角点 cv2.drawChessboardCorners(img_left, board_size, corners_left, ret_l) cv2.drawChessboardCorners(img_right, board_size, corners_right, ret_r) # 添加对象点和像点到数组中 obj_points_list.append(obj_points) img_points_left_list.append(corners_left) img_points_right_list.append(corners_right) # 显示像 cv2.imshow('Left', img_left) cv2.imshow('Right', img_right) # 按下 ESC 键退出循环 if cv2.waitKey(1) == 27: break # 关闭摄像机 left_cam.release() right_cam.release() # 计算标定参数 ret_l, mtx_l, dist_l, rvecs_l, tvecs_l = cv2.calibrateCamera(obj_points_list, img_points_left_list, img_left.shape[::-1][1:], None, None) ret_r, mtx_r, dist_r, rvecs_r, tvecs_r = cv2.calibrateCamera(obj_points_list, img_points_right_list, img_right.shape[::-1][1:], None, None) ret_s, mtx_l, dist_l, mtx_r, dist_r, R, T, E, F = cv2.stereoCalibrate(obj_points_list, img_points_left_list, img_points_right_list, mtx_l, dist_l, mtx_r, dist_r, img_left.shape[::-1][1:], criteria=criteria) # 计算矫正参数 R1, R2, P1, P2, Q, valid_roi_left, valid_roi_right = cv2.stereoRectify(mtx_l, dist_l, mtx_r, dist_r, img_left.shape[::-1][1:], R, T, alpha=0) # 生成映射表 mapx_l, mapy_l = cv2.initUndistortRectifyMap(mtx_l, dist_l, R1, P1, img_left.shape[::-1][1:], cv2.CV_32FC1) mapx_r, mapy_r = cv2.initUndistortRectifyMap(mtx_r, dist_r, R2, P2, img_right.shape[::-1][1:], cv2.CV_32FC1) # 加载像 img_left = cv2.imread(left_path) img_right = cv2.imread(right_path) # 根据映射表矫正像 img_rectified_left = cv2.remap(img_left, mapx_l, mapy_l, cv2.INTER_LINEAR) img_rectified_right = cv2.remap(img_right, mapx_r, mapy_r, cv2.INTER_LINEAR) # 显示矫正后的像 cv2.imshow('Left Rectified', img_rectified_left) cv2.imshow('Right Rectified', img_rectified_right) cv2.waitKey(0) cv2.destroyAllWindows() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuLaDe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值