激光雷达-相机标定建立了三维激光雷达点和二维相机数据之间的对应关系,从而将激光雷达和相机输出融合在一起。
激光雷达传感器和相机被广泛用于自动驾驶、机器人和导航等应用中的三维场景重建。激光雷达传感器捕捉环境的三维结构信息,而相机则捕捉色彩、纹理和外观信息。激光雷达传感器和相机各自根据自己的坐标系捕捉数据。
激光雷达-相机标定包括将激光雷达传感器和相机的数据转换为同一坐标系。这样就可以融合两个传感器的数据,准确识别场景中的物体。该图显示了融合后的数据。
激光雷达-相机标定包括内参标定和外参标定。
激光雷达传感器和相机的外参标定估算它们之间的刚性变换,以建立它们坐标系之间的几何关系。这一过程使用标准标定对象,如带有棋盘图案的平面板。
该图显示了使用棋盘格对激光雷达传感器和相机进行外参标定的过程。
外参标定的程序化工作流程包括这些步骤。另外,您也可以使用激光雷达相机标定器应用程序交互式地执行激光雷达-相机标定。
您可以使用转换矩阵来
本例向您展示如何估计三维激光雷达传感器和相机之间的刚性变换,然后使用刚性变换矩阵融合激光雷达和相机数据。
激光雷达传感器和相机通常在自动驾驶应用中结合使用,因为激光雷达传感器收集三维空间信息,而相机则以二维图像捕捉空间的外观和纹理。您可以融合来自这些传感器的数据来改进物体检测和分类。激光雷达-相机标定可以估算出一个变换矩阵,给出两个传感器之间的相对旋转和平移。在进行激光雷达-相机数据融合时,您可以使用该矩阵。
本图说明了激光雷达和相机标定(LCC)过程的工作流程,我们使用棋盘格作为标定对象。我们从激光雷达和相机数据中提取棋盘角和平面,然后在它们的坐标系之间建立几何关系,进行标定。有关激光雷达-相机标定过程的更多信息,请参阅什么是激光雷达-相机标定?
本示例使用了两个不同激光雷达传感器的数据,一个是VelodyneLiDARHDL-64传感器,另一个是VelodyneLiDARVLP-16传感器。对于HDL-64传感器,使用从Gazebo环境中采集的数据。
HDL-64传感器捕获的数据是一组PNG图像和相应的PCD点云。本示例假定您已经知道相机的固有参数。有关提取相机内参标定参数的详细信息,请参阅评估单相机标定的准确性。
从Gazebo加载VelodyneHDL-64传感器数据。
imagePath=fullfile(toolboxdir('lidar'),'lidardata','lcc','HDL64','images');ptCloudPath=fullfile(toolboxdir('lidar'),'lidardata','lcc','HDL64','pointCloud');cameraParamsPath=fullfile(imagePath,'calibration.mat');%Loadcameraintrinsics.intrinsic=load(cameraParamsPath);%LoadimagesusingimageDatastore.imds=imageDatastore(imagePath);imageFileNames=imds.Files;%Loadpointcloudfiles.pcds=fileDatastore(ptCloudPath,'ReadFcn',@pcread);ptCloudFileNames=pcds.Files;%Squaresizeofthecheckerboard.squareSize=200;%Setrandomseedtogeneratereproducibleresults.rng('default')2.3检测棋盘角本例使用棋盘格图案进行标定。首先,根据相机数据估算棋盘边缘。使用estimateCheckerboardCorners3d函数计算棋盘角的坐标和实际棋盘的尺寸(以毫米为单位)。该函数以世界坐标系中的三维坐标来估算边角。
[imageCorners3d,checkerboardDimension,dataUsed]=...estimateCheckerboardCorners3d(imageFileNames,intrinsic.cameraParams,squareSize);%Removeimagefilesthatarenotused.imageFileNames=imageFileNames(dataUsed);使用helperShowImageCorners辅助函数将结果可视化。
接下来,使用detectRectangularPlanePoints函数检测激光雷达数据中的棋盘平面。该函数使用estimateCheckerboardCorners3d函数计算出的棋盘尺寸来检测棋盘平面。
%ExtractthecheckerboardROIfromthedetectedcheckerboardimagecorners.roi=helperComputeROI(imageCorners3d,5);%Filterthepointcloudfilesthatarenotusedfordetection.ptCloudFileNames=ptCloudFileNames(dataUsed);[lidarCheckerboardPlanes,framesUsed,indices]=...detectRectangularPlanePoints(ptCloudFileNames,checkerboardDimension,ROI=roi);%RemoveptCloudfilesthatarenotused.ptCloudFileNames=ptCloudFileNames(framesUsed);%Removeimagefiles.imageFileNames=imageFileNames(framesUsed);%Remove3-Dcornersfromimages.imageCorners3d=imageCorners3d(:,:,framesUsed);使用helperShowCheckerboardPlanes函数将检测到的棋盘可视化。
使用estimateLidarCameraTransform函数估算激光雷达传感器和相机之间的刚性变换矩阵。
[tform,errors]=estimateLidarCameraTransform(lidarCheckerboardPlanes,...imageCorners3d,intrinsic.cameraParams);标定后,您可以使用此变换矩阵来
使用helperFuseLidarCamera函数将激光雷达和图像数据融合在一起,实现可视化。
您可以使用这些类型的误差来估算标定精度。
使用helperShowError函数绘制估计误差值。
在实际VLP-16激光雷达数据上测试LCC工作流程,以评估其性能。
本示例概述了激光雷达-相机标定工作流程,并向您展示了如何使用刚性变换矩阵来融合激光雷达和相机数据。
激光雷达相机标定程序可让您通过估算激光雷达传感器和相机之间的刚性变换,以交互方式在两者之间执行标定。
本专题将向您展示LidarCameraCalibrator应用程序的工作流程,以及您可以用来分析和改进结果的功能。标定过程的第一个也是最重要的部分是获取准确有用的数据。有关获取数据的指南和技巧,请参阅标定指南。
要打开LidarCameraCalibrator应用程序,请在MATLAB命令提示符下输入此命令。
lidarCameraCalibrator或者,也可以从"应用程序"选项卡的"图像处理和计算机视觉"下打开该应用程序。
应用程序打开时是一个空会话。该程序可读取PLY和点云数据(PCD)格式的点云数据,以及imformats支持的任何格式的图像。如果您的数据存储在rosbag文件中,请参阅"从Rosbag文件读取激光雷达和相机数据"教程进行相应转换。
将标定数据加载到应用程序中。
输入的图像和点云文件必须具有相同的名称。应用程序会使用文件名将图像和点云数据配对。它会将图像与具有相同文件名的相应点云进行比较。
提示
要在会话中的任意位置向会话添加更多图像和点云,请选择导入>向会话添加数据。
加载图像和点云数据后,应用程序会对其执行自动特征检测。应用程序会使用指定的棋盘格参数,从图像数据中检测棋盘格角,从点云数据中检测棋盘格面。
当应用程序在图像和点云中都检测到棋盘格特征时,会将其显示在"接受数据"窗格中,并接受图像和点云数据对进行标定。
如果应用程序在图像、点云或两者中均未检测到特征,则会将其显示在"拒绝数据"窗格中。您可以使用"选择感兴趣区域"或"选择棋盘格区域"工具来检测剔除数据中的特征。
从数据浏览器的"接受数据"或"剔除数据"窗格中选择数据对,将其显示在可视化窗格中。
您可以在应用程序工具条的"操作"部分使用这些工具来处理接受和剔除的数据对。
有关在数据浏览器中使用的键盘快捷键列表,请参阅数据浏览器。
默认情况下,应用程序会在内部计算输入图像数据中的相机固有参数,以执行特征检测。您也可以在应用程序工具条的"相机固有参数"部分选择"使用固定固有参数",将相机固有参数加载到应用程序中。在打开的对话框中,指定相机固有参数的位置并将其加载到应用程序中。您可以从文件或MATLAB工作区加载固有参数。然后,在"检测特征"部分,选择"检测"以使用新的固有参数重新检测输入数据中的特征。
要将相机固有参数重置为应用程序计算的默认值,请选择计算固有参数。要加载不同的固有参数值,请选择使用固定固有参数,然后选择加载固有参数。
指定感兴趣区域来检测特征可以改善特征检测结果,尤其是在剔除数据中。要指定感兴趣区域,首先要从应用工具条中选择编辑ROI。这将打开"编辑ROI"选项卡。
在"编辑ROI"选项卡中,应用程序会显示带有ROI立方体的点云数据。调整ROI立方体,使其与包含棋盘格的区域更加匹配。这样可以将特征检测限制在特定区域内,从而减少数据剔除并提高性能。
使用以下步骤,使用"编辑ROI"微调点云数据中的棋盘格检测。
更新点云帧的ROI后,在应用程序工具条的"标定"选项卡上的"检测特征"部分,选择"检测"以重新检测所选ROI内输入数据中的特征。
使用键盘快捷键可以更加交互式地执行这些任务。有关"编辑ROI"键盘快捷键,请参阅"编辑ROI"。
要进一步调整特征检测,请单击应用程序工具条上的"选择棋盘区域"。应用程序会打开"选择棋盘"选项卡,您可以在其中手动选择任意点云坐标系中的棋盘点。
在"选择棋盘"选项卡中
棋盘格选择只适用于所选点云。更新棋盘格点后,选择"检测"可使用更新后的棋盘格点重新检测输入数据中的地物。
应用程序提供了这些特征检测设置,您可以利用它们调整检测参数。
更新新的检测参数后,选择"检测"以重新检测输入数据中的特征。
对检测结果满意后,选择标定按钮对传感器进行标定。如果您有估计的变换矩阵,请选择初始变换从文件或工作区加载变换矩阵。本应用程序假定激光雷达传感器和相机之间的旋转角度在[-4545]范围内,单位为度,沿每个轴。如果旋转角度超出此范围,请使用初始变换指定初始变换以提高标定精度。
标定完成后,应用程序界面会显示图像,并将点云中的棋盘格点投射到图像上。应用程序使用projectLidarPointsOnImage函数将激光雷达点投射到图像上。使用fuseCameraToLidar函数将图像的颜色信息与点云数据融合。
该程序还利用误差图提供转换矩阵的不准确度指标。图中说明了每个数据对中的这些误差:
在数据浏览器中选择一个数据对时,误差图中的相应条形图将以深蓝色突出显示。您可以通过删除异常值来调整标定结果。垂直拖动每个图上的红线可设置误差限值。应用程序会选择误差值大于误差限值的所有数据对作为异常值,并在数据浏览器中以蓝色高亮显示误差条及其对应的数据对。右键单击数据浏览器中任何选定的数据对,然后选择删除和重新校准,即可删除异常值并重新校准传感器。删除异常值可以提高标定精度。有关误差图的键盘快捷键列表,请参阅误差图。
您可以将转换矩阵和误差指标作为变量导出到工作区或MAT文件中。您可以生成完整应用工作流程的MATLAB脚本,以便在项目中使用。
激光雷达相机标定程序有以下限制:
本例演示了如何从rosbag文件中读取并保存图像和点云数据。本例还展示了如何为激光雷达相机标定准备数据。
使用本示例末尾定义的helperDownloadRosbag辅助函数下载rosbag文件。
path=helperDownloadRosbag;从bag文件中读取信息。
imageBag=select(bag,'Topic','/camera/image/compressed');pcBag=select(bag,'Topic','/points');阅读所有消息。
k=1;ifsize(t2,1)>size(t1,1)fori=1:size(t1,1)[val,indx]=min(abs(t1(i)-t2));ifval<=0.1idx(k,:)=[iindx];k=k+1;endendelsefori=1:size(t2,1)[val,indx]=min(abs(t2(i)-t1));ifval<=0.1idx(k,:)=[indxi];k=k+1;endendend创建保存有效图像和点云的目录。
pcFilesPath=fullfile(tempdir,'PointClouds');imageFilesPath=fullfile(tempdir,'Images');if~exist(imageFilesPath,'dir')mkdir(imageFilesPath);endif~exist(pcFilesPath,'dir')mkdir(pcFilesPath);end提取图像和点云。将文件命名并保存在各自的文件夹中。将相应的图像和点云保存在同一编号下。
fori=1:length(idx)I=readImage(imageMsgs{idx(i,1)});pc=pointCloud(readXYZ(pcMsgs{idx(i,2)}));n_strPadded=sprintf('%04d',i);pcFileName=strcat(pcFilesPath,'/',n_strPadded,'.pcd');imageFileName=strcat(imageFilesPath,'/',n_strPadded,'.png');imwrite(I,imageFileName);pcwrite(pc,pcFileName);end启动激光雷达相机标定器应用程序,使用界面将数据加载到应用程序中。您也可以从MATLAB命令行加载数据并启动应用程序。
checkerSize=81;%毫米padding=[0000];lidarCameraCalibrator(imageFilesPath,pcFilesPath,checkerSize,padding)
functionrosbagFile=helperDownloadRosbag()%DownloadthedatasetfromthegivenURL.rosbagZipFile=matlab.internal.examples.downloadSupportFile(...'lidar','data/lccSample.zip');[outputFolder,~,~]=fileparts(rosbagZipFile);rosbagFile=fullfile(outputFolder,'lccSample.bag');if~exist(rosbagFile,'file')unzip(rosbagZipFile,outputFolder);endend