激光雷达-相机外参联合标定通过手动选取3D-2D点利用PnP求解

0、写在前面

差不多快半年没有更新博客了,这里先感慨一下找工作的不容易。
这个激光雷达-相机联合标定的需求是因为我前段时间所做的项目中有一个需求,需要给点云添加对应的温度。没错,给点云加温度,从红外相机中获取到温度。


1、激光雷达->相机的坐标变换

在这里插入图片描述
什么是激光雷达到相机坐标系的变换?
激光雷达坐标系下的一个3D点(x, y, z)通过外参矩阵(R, t)转换到相机坐标系,在通过相机内参转到像素平面得到2D点(u,v)

2、怎么解这个外参矩阵

为了解这个(R, t)矩阵,我们至少需要三对匹配点,利用三对匹配点的就变成了PnP中的P3P问题。具体的原理可以参考高翔slambook中第七章中相关内容

3、怎么获取匹配点对

之前用过Autoware的Calibration ToolKit ,它可以自动识别到图像和点云中的标定板,这在小范围场景下是可行的。

如果相机和激光雷达安装的位置很高,导致标定板在视野中很小,那么此时标定板就捕获不到了。那么有没有别的方法呢?
答案是可以的,我们可以在图像和点云中自己选取匹配的点对,通过鼠标的监听方式。但这种方式带来的困难也显而易见的,我们能确定这是同一块区域,但是对区域里的具体的点的选择确实困难的,概括来说就是:

  • 确定这是匹配点
  • 鼠标点的准

4、PnP求解3D-2D问题

可以调用opencv中的PnP方法完成求解


                
激光雷达与摄像头之间的标定是自动驾驶机器人领域中的关键技术之一,旨在确定两者之间的相对位置姿态(即旋转平移数)。以下是几种常见的标定方法: ### 1. 基于标定板的方法 文中提出了一种全新的标定板设计,用于联合标定任务[^1]。该方法通过使用特定的标定板(如棋盘格),在多个视角下采集数据,并利用这些数据来估计相机、畸变因子以及LiDAR-Camera。具体步骤包括: - **数据采集**:在不同角度距离下,使用激光雷达摄像头同时采集标定板的数据。 - **特征提取**:从图像中提取角等特征,并从云数据中找到对应的- **优化计算**:基于提取的特征,通过优化算法(如PnP或ICP)求解。 对于标定板的设计使用,需注意以下数: - `chessboard_size`:表示标定板的物理尺寸,单位为米。 - `chessboard_width` `chessboard_height`:分别表示棋盘格宽方向高方向的角数量。 - `chessboard_grap`:每个角之间的间距,单位为米[^3]。 ### 2. 在线标定方法 针对自动驾驶车辆的应用场景,文中介绍了一种基于在线标定的算法[^2]。这种方法不需要预先固定的标定板,而是通过实时采集的数据进行动态标定。其原理基于激光雷达以雷达坐标系(X, Y, Z)表示目标云数据,而摄像头以图像坐标系(u, v)表示目标像素位。通过匹配图像中的特征,可以实时更新。 ### 3. 无标定板方法 文中还提到了一种无需标定板的标定方法[^4]。该方法依赖于相机的已知性,并通过配置文件(如`camera_config.json`)设置初始数,包括: - `camera_matrix`:相机矩阵。 - `distortion_coefficients`:镜头畸变系数。 - `tvec`:初始平移向量。 - `rvec`:初始旋转向量。 通过分析自然场景中的共同特征,结合优化算法,可以在没有标定板的情况下实现标定。 ### 示例代码 以下是一个简单的Python示例,展示如何使用OpenCV库进行基于标定板的标定: ```python import cv2 import numpy as np # 定义棋盘格的尺寸间距 chessboard_size = (11, 8) square_size = 0.06 # 单位:米 # 准备对象,如 (0,0,0), (1,0,0), ..., (10,7,0) objp = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32) objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2) * square_size # 存储对象图像的数组 objpoints = [] # 3d在世界坐标系中 imgpoints = [] # 2d在图像平面中 # 加载图像并检测角 cap = cv2.VideoCapture('calibration_video.mp4') while cap.isOpened(): ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None) if ret: objpoints.append(objp) imgpoints.append(corners) # 相机标定 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None) # 计算LiDAR到相机 lidar_to_camera_rotation = ... # 根据实际应用计算旋转矩阵 lidar_to_camera_translation = ... # 根据实际应用计算平移向量 ``` ###
评论 13
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值