深度图与RGB彩色图的对准(内附Python代码)

文章讲述了如何处理已经采集到的未对准的RealSense深度相机和RGB相机图像,通过Python实现图像对齐,详细描述了算法思路并提供了代码示例,尽管最终效果不理想,可能因相机未准确对准导致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用RealSense深度相机前,必须把深度相机和RGB相机对准了使用。。。不然会导致采集到的图像不对齐(如下图所示):

        

 

 左边是RGB图像,右边是深度图像。

 关于RealSense相机的校准,网上已经有了许多教程,这里就不再赘述。本文主要内容是如何处理已采集好的未对准的图像,以避免之前采集的一堆实验数据作废。搜索了很多教程,但是没找到现成的代码,唯一现成的代码是用C++写的。。。由于我太废物只会最简单的Python,因此决定自己写一版Python的代码。

代码的撰写思路

先简单讲述一下过程。以下是从别的教程复制粘贴的:

1、获取Kinect的深度图像;

2、获取RGB摄像头的图像;

3、为深度图像中的每一个像素附上对应的RGB颜色,比如你要给坐标为(x, y)的深度图像素附上颜色,具体步骤如下;

1)构造一个三维向量p_ir = (x, y, z),其中x,y是该点的像素坐标,z是该像素的深度值;

2)用Kinect内参矩阵H_ir的逆,乘以p_ir得到对应的空间点坐标P_ir,具体公式见上文第四部分(配准);

3)由于P_ir是该点在Kinect坐标系下的坐标,我们需要将其转换到RGB摄像头的坐标系下,具体的,就是乘以一个旋转矩阵R,再加上一个平移向量T,得到P_rgb;

4)用RGB摄像头的内参矩阵H_rgb乘以P_rgb,得到p_rgb,p_rgb也是一个三维向量,其x和y坐标即为该点在RGB图像中的像素坐标,取出该像素的颜色,作为深度图像中对应像素的颜色;

5)对深度图像中的每一个像素都做上述操作,得到配准后的深度图。

深度图与RGB图对齐原理

其原理就是:

  1. 深度图上的2D点转换到世界坐标的3D点(这里设为点A)
  2. 将点A的世界坐标的3D点投影到彩色图像上,获取点A在RGB图像上的坐标(x,y)
  3. 提取A点的RGB三通道的值,将其赋予到原深度图上点A的坐标上。

最后的效果是深度图像不变,RGB图像对齐到深度图像

注意:这里只能让RGB图像去对齐到深度图像而不能反过来,因为在第1步将图像上的点转化为世界坐标的3D点这里,只有深度图像内含的深度信息才能实现。RGB图像不含深度信息因此无法做到RGB图像不变,深度图像去对齐到RGB。

代码实现

下面就是Python代码的实现。

import numpy as np
import cv2

# 获取RGB与深度图像信息。因为采集数据时是直接将RGB和深度信息一起存储到npy文件里,因此这里将RGB三通道和D深度通道的信息分开存储
arr = np.load('Data.npy')
b, g, r, d = cv2.split(arr)
depth_img = d  # 深度信息
rgb_img = cv2.merge([b, g, r])  # RGB信息

# 深度相机的外参矩阵(包括旋转矩阵与传递矩阵), 这里是通过RealSense2的函数 get_extrinsics_to(profile) 获得后直接赋值的,具体可网上搜索教程
R = np.array([(0.999993, 0.00372933, -0.000414306), (-0.00372927, 0.999993, 0.000135122), (0.000414807, -0.000133576, 1)])
T = np.array([-0.0148581, -8.0544e-05, 2.60393e-05])

# R1 = H_rgb@R@np.linalg.inv(H_depth)
result = np.zeros([480, 640, 3])

for row in range(480):
    for col in range(640):
        V_depth = depth_img[row][col]
        p_depth = np.array([col, row, 1])
        p_rgb = V_depth/1000*R@p_depth + T/1000

        X = p_rgb[0]//p_rgb[2]
        Y = p_rgb[1]//p_rgb[2]
        if (0 <= X < 640) and (0 <= Y < 480):
            result[row][col] = rgb_img[int(Y)][int(X)]
        else:
            result[row][col] = np.array([0, 0, 0])


# cv2.imwrite('OMG/RGB.jpg', rgb_img)
cv2.imwrite('OMG/RGB2.jpg', result)

这里的Python代码是照着这篇教程里的C++代码修改的:

kinect 2.0 SDK学习笔记(四)--深度图与彩色图对齐_深度相机rgb图和深度图对齐原理_jiaojialulu的博客-CSDN博客

最后得到的效果并不是很理想。但是由于时间有限,懒得进行进一步优化。猜测原因如果不是代码问题的话,就是之前深度相机没和RGB相机对准,两个相机范围相差过大导致的。欢迎大神找出原因并指导一下我(˚ ˃̣̣̥᷄⌓˂̣̣̥᷅ )

 

参考文章:​​​​​​​Kinect深度图与RGB摄像头的标定与配准_aipiano的博客-CSDN博客

可以使用OpenCV库来实现彩色图像和深度图像的配准。 以下是一个简单的代码示例: ```python import cv2 import numpy as np # 读取彩色图像和深度图像 color_img = cv2.imread('color_image.png') depth_img = cv2.imread('depth_image.png', cv2.IMREAD_ANYDEPTH) # 将深度图像转换为浮点型 depth_img = depth_img.astype(np.float32) # 缩小深度图像以提高配准速度 depth_img = cv2.resize(depth_img, (color_img.shape[1], color_img.shape[0])) # 提取深度图像中非零像素的坐标 non_zeros = np.where(depth_img > 0) # 将非零像素坐标转换为相机坐标系下的三维坐标 fx = 525.0 fy = 525.0 cx = 319.5 cy = 239.5 x = (non_zeros[1] - cx) * depth_img[non_zeros] / fx y = (non_zeros[0] - cy) * depth_img[non_zeros] / fy z = depth_img[non_zeros] camera_coords = np.vstack((x, y, z)).T # 将相机坐标系下的三维坐标转换为世界坐标系下的三维坐标 world_coords = np.dot(camera_coords, np.linalg.inv(np.array([[1, 0, 0], [0, -1, 0], [0, 0, -1]]))) # 将世界坐标系下的三维坐标转换为彩色图像坐标系下的二维坐标 fx_rgb = 1066.778 fy_rgb = 1067.487 cx_rgb = 312.9869 cy_rgb = 241.3109 x_rgb = world_coords[:, 0] * fx_rgb / world_coords[:, 2] + cx_rgb y_rgb = world_coords[:, 1] * fy_rgb / world_coords[:, 2] + cy_rgb # 将二维坐标转换为整数 x_rgb = x_rgb.astype(np.int) y_rgb = y_rgb.astype(np.int) # 创建一个空白的彩色图像 registered_img = np.zeros_like(color_img) # 将深度图像中的非零像素对应到彩色图像中 registered_img[y_rgb, x_rgb] = color_img[non_zeros] # 显示配准后的图像 cv2.imshow('Registered Image', registered_img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 代码中涉及到的变量说明: - `color_img`: 彩色图像,类型为`numpy.ndarray`,大小为`(height, width, 3)`。 - `depth_img`: 深度图像,类型为`numpy.ndarray`,大小为`(height, width)`。 - `fx`, `fy`, `cx`, `cy`: 相机内参。 - `fx_rgb`, `fy_rgb`, `cx_rgb`, `cy_rgb`: 彩色相机内参。 - `camera_coords`: 相机坐标系下的三维坐标,类型为`numpy.ndarray`,大小为`(n, 3)`,其中`n`为非零像素的数量。 - `world_coords`: 世界坐标系下的三维坐标,类型为`numpy.ndarray`,大小为`(n, 3)`。 - `x_rgb`, `y_rgb`: 彩色图像中的像素坐标,类型为`numpy.ndarray`,大小为`(n,)`。 - `registered_img`: 配准后的彩色图像,类型为`numpy.ndarray`,大小和`color_img`相同。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值