好消息好消息,现在Matlab官方发布了激光雷达+相机的校准工具箱啦!! 如果想使用这个功能,请先升级到MATLAB2020b。然后按照一下教程运行。
使用这个功能需要准备的是
1.安装MATLAB2020b,拥有LiDAR工具箱 2.使用matlab标定好的相机内参矩阵 3.拥有雷达的点云文件PCD或PCL格式(实例所使用的是内置的PCD文件)2020b的Baidu云链接,提取码:zadk 下面这幅图展示了整个标定的过程,最终两个坐标系的转换使用了刚性变换。
从LiDAR中加载内置点云文件(HDL-64)
imagePath = fullfile(toolboxdir('lidar'), 'lidardata', 'lcc', 'HDL64', 'images'); ptCloudPath = fullfile(toolboxdir('lidar'), 'lidardata', 'lcc', 'HDL64', 'pointCloud'); cameraParamsPath = fullfile(imagePath, 'calibration.mat'); intrinsic = load(cameraParamsPath); % Load camera intrinsics imds = imageDatastore(imagePath); % Load images using imageDatastore pcds = fileDatastore(ptCloudPath, 'ReadFcn', @pcread); % Load point cloud files imageFileNames = imds.Files; ptCloudFileNames = pcds.Files; squareSize = 200; % Square size of the checkerboard % Set random seed to generate reproducible results. rng('default');执行棋盘角点检测
[imageCorners3d, checkerboardDimension, dataUsed] = ... estimateCheckerboardCorners3d(imageFileNames, intrinsic.cameraParams, squareSize); imageFileNames = imageFileNames(dataUsed); % Remove image files that are not used结果可以使用helperShowImageCorners函数进行可视化。
% Display Checkerboard corners helperShowImageCorners(imageCorners3d, imageFileNames, intrinsic.cameraParams);激光雷达中的棋盘检测
% Extract ROI from the detected image corners roi = helperComputeROI(imageCorners3d, 5); % Filter point cloud files corresponding to the detected images ptCloudFileNames = ptCloudFileNames(dataUsed); [lidarCheckerboardPlanes, framesUsed, indices] = ... detectRectangularPlanePoints(ptCloudFileNames, checkerboardDimension, 'ROI', roi); % Remove ptCloud files that are not used ptCloudFileNames = ptCloudFileNames(framesUsed); % Remove image files imageFileNames = imageFileNames(framesUsed); % Remove 3D corners from images imageCorners3d = imageCorners3d(:, :, framesUsed);可视化检测到的函数,使用helperShowLidarCorners函数
helperShowLidarCorners(ptCloudFileNames, indices);校准激光雷达和摄像机 使用estimateLidarCameraTransform函数去估计雷达和摄像机之间的刚性变换矩阵。
[tform, errors] = estimateLidarCameraTransform(lidarCheckerboardPlanes, ... imageCorners3d, 'CameraIntrinsic', intrinsic.cameraParams);校准完成后,可以通过两种方式使用校准矩阵:
使用图像中的色彩表示增强激光雷达点云,即生成彩色点云在图像上投影激光雷达点云。 使用helperFuseLidarCamerafunction函数可视化融合结果 helperFuseLidarCamera(imageFileNames, ptCloudFileNames, indices, ... intrinsic.cameraParams, tform);使用helperShowError函数绘制估计误差值
helperShowError(errors)结果 校准后检查具有较高误差值的数据,然后重新运行校准
outlierIdx = errors.RotationError < mean(errors.RotationError); [newTform, newErrors] = estimateLidarCameraTransform(lidarCheckerboardPlanes(outlierIdx), ... imageCorners3d(:, :, outlierIdx), 'CameraIntrinsic', intrinsic.cameraParams); helperShowError(newErrors);对真实数据进行测试 在实际 VLP-16 激光雷达数据上测试激光雷达相机校准。
clear; imagePath = fullfile(toolboxdir('lidar'), 'lidardata', 'lcc', 'vlp16', 'images'); ptCloudPath = fullfile(toolboxdir('lidar'), 'lidardata', 'lcc', 'vlp16', 'pointCloud'); cameraParamsPath = fullfile(imagePath, 'calibration.mat'); intrinsic = load(cameraParamsPath); % Load camera intrinscs imds = imageDatastore(imagePath); % Load images using imageDatastore pcds = fileDatastore(ptCloudPath, 'ReadFcn', @pcread); % Loadr point cloud files imageFileNames = imds.Files; ptCloudFileNames = pcds.Files; squareSize = 81; % Square size of the checkerboard % Set random seed to generate reproducible results. rng('default'); % Extract Checkerboard corners from the images [imageCorners3d, checkerboardDimension, dataUsed] = ... estimateCheckerboardCorners3d(imageFileNames, intrinsic.cameraParams, squareSize); imageFileNames = imageFileNames(dataUsed); % Remove image files that are not used % Filter point cloud files corresponding to the detected images ptCloudFileNames = ptCloudFileNames(dataUsed); % Extract ROI from the detected image corners roi = helperComputeROI(imageCorners3d, 5); %Extract Checkerboard in lidar data [lidarCheckerboardPlanes, framesUsed, indices] = detectRectangularPlanePoints(... ptCloudFileNames, checkerboardDimension, 'RemoveGround', true, 'ROI', roi); imageCorners3d = imageCorners3d(:, :, framesUsed); % Remove ptCloud files that are not used ptCloudFileNames = ptCloudFileNames(framesUsed); % Remove image files imageFileNames = imageFileNames(framesUsed); [tform, errors] = estimateLidarCameraTransform(lidarCheckerboardPlanes, ... imageCorners3d, 'CameraIntrinsic', intrinsic.cameraParams); helperFuseLidarCamera(imageFileNames, ptCloudFileNames, indices,... intrinsic.cameraParams, tform);如果运行中有报错,可直接在报错的函数中将参数代入运行一遍,然后将主函数开头的Clear删除,使用运行得到的结果接着在主函数中运行。