激光平面的标定流程
激光平面标定流程(含MATLAB代码)
激光平面标定(Laser Plane Calibration)用于确定激光发射器(如线激光)在相机坐标系下的平面方程((ax + by + cz + d = 0)),常用于结构光三维重建、激光三角测距等应用。
1. 标定原理
-
激光平面方程:
激光在相机坐标系下的平面方程表示为:
[
aX_c + bY_c + cZ_c + d = 0
]
其中 ( (X_c, Y_c, Z_c) ) 是相机坐标系下的3D点。 -
标定目标:
通过已知的标定板(如棋盘格)和激光线在图像上的投影,计算激光平面的参数 ( [a, b, c, d] )。
2. 标定流程
步骤1:采集数据
- 固定相机和激光器,激光线投射到标定板上。
- 移动标定板(或改变激光角度),采集多组数据:
- 标定板图像(用于计算标定板在相机坐标系下的位姿)。
- 激光线图像(用于提取激光线上的像素点)。
步骤2:相机标定
- 使用棋盘格标定相机,获取相机内参((K))和畸变系数((dist))。
- MATLAB代码:
% 相机标定(需提前拍摄棋盘格图像) [imagePoints, boardSize] = detectCheckerboardPoints('calibImages/*.jpg'); worldPoints = generateCheckerboardPoints(boardSize, squareSize); % squareSize为棋盘格方格实际尺寸(mm) params = estimateCameraParameters(imagePoints, worldPoints); K = params.IntrinsicMatrix'; % 内参矩阵 dist = params.RadialDistortion; % 畸变系数
步骤3:提取激光线
- 对激光线图像进行阈值分割、骨架化,提取激光线的像素坐标。
- MATLAB代码:
% 读取激光线图像并提取激光点 laserImg = imread('laser_line.jpg'); grayImg = rgb2gray(laserImg); binaryImg = imbinarize(grayImg, 'adaptive'); % 自适应二值化 skeletonImg = bwmorph(binaryImg, 'skel', Inf); % 骨架化 [v, u] = find(skeletonImg); % 获取激光线像素坐标 (u, v)
步骤4:计算激光线对应的3D点
- 对于每个激光点 ( (u, v) ),结合标定板位姿,计算其在相机坐标系下的3D坐标:
- 通过标定板位姿((R, t))将棋盘格角点转换到相机坐标系。
- 拟合标定板平面方程 ( Z = f(X, Y) )。
- 激光线与标定板平面相交,计算3D点:
- 反投影像素点 ( (u, v) ) 到相机坐标系(射线方程)。
- 求射线与标定板平面的交点。
- MATLAB代码:
% 假设已通过相机标定获取标定板位姿 [R|t] [R, t] = extrinsicsToCameraPose(params, imagePoints); % 标定板位姿 % 标定板平面方程(棋盘格在相机坐标系下的平面) boardPlane = [R(:,3); -dot(R(:,3), t)]; % 法向量 + 偏移量 [a,b,c,d] % 计算激光线3D点 laserPoints3D = zeros(length(u), 3); for i = 1:length(u) % 反投影像素点 (u,v) 到相机坐标系(射线) uv = [u(i), v(i)]; ray = inv(K) * [uv, 1]'; % 归一化坐标 % 计算射线与标定板平面的交点 lambda = -boardPlane(4) / (boardPlane(1:3)' * ray; point3D = lambda * ray; laserPoints3D(i,:) = point3D'; end
步骤5:拟合激光平面
- 使用最小二乘法拟合激光点云到平面方程 ( ax + by + cz + d = 0 )。
- MATLAB代码:
% 拟合激光平面 centroid = mean(laserPoints3D); [U, S, V] = svd(laserPoints3D - centroid); normal = V(:,3); % 平面法向量 [a,b,c] d = -normal' * centroid'; % 平面偏移量 d laserPlane = [normal; d]'; % 激光平面方程 [a,b,c,d] % 验证重投影误差 distances = laserPoints3D * laserPlane(1:3)' + laserPlane(4); rmse = sqrt(mean(distances.^2)); fprintf('激光平面拟合RMSE: %.4f mm\n', rmse);
3. 完整MATLAB代码示例
%% 激光平面标定(需提前完成相机标定)
clc; clear; close all;
% 1. 加载相机内参和畸变系数(假设已标定)
load('cameraParams.mat'); % 包含 K, dist
% 2. 提取激光线像素点
laserImg = imread('laser_line.jpg');
grayImg = rgb2gray(laserImg);
binaryImg = imbinarize(grayImg, 'adaptive');
skeletonImg = bwmorph(binaryImg, 'skel', Inf);
[v, u] = find(skeletonImg); % 注意MATLAB是 (row,col) = (v,u)
% 3. 计算标定板位姿(假设已检测到棋盘格角点)
imagePoints = detectCheckerboardPoints('calibBoard.jpg');
worldPoints = generateCheckerboardPoints([9,6], 25); % 假设棋盘格 9x6,方格25mm
[R, t] = extrinsicsToCameraPose(imagePoints, worldPoints, K, dist);
% 4. 计算激光线3D点
boardPlane = [R(:,3); -dot(R(:,3), t)]; % 标定板平面 [a,b,c,d]
laserPoints3D = zeros(length(u), 3);
for i = 1:length(u)
ray = inv(K) * [u(i); v(i); 1];
lambda = -boardPlane(4) / (boardPlane(1:3)' * ray);
laserPoints3D(i,:) = (lambda * ray)';
end
% 5. 拟合激光平面
centroid = mean(laserPoints3D);
[U, S, V] = svd(laserPoints3D - centroid);
laserPlane = [V(:,3); -dot(V(:,3), centroid')]';
fprintf('激光平面方程: %.4fX + %.4fY + %.4fZ + %.4f = 0\n', laserPlane);
% 6. 验证误差
distances = laserPoints3D * laserPlane(1:3)' + laserPlane(4);
rmse = sqrt(mean(distances.^2));
fprintf('拟合RMSE: %.4f mm\n', rmse);
% 可视化
figure; scatter3(laserPoints3D(:,1), laserPoints3D(:,2), laserPoints3D(:,3));
hold on; patch('Faces', [1,2,3,4], 'Vertices', [-1,-1,0; 1,-1,0; 1,1,0; -1,1,0], 'FaceAlpha', 0.5);
xlabel('X'); ylabel('Y'); zlabel('Z'); title('激光平面标定结果');
4. 注意事项
- 标定板要求:
- 棋盘格需平整,避免反光或弯曲。
- 激光线应清晰,避免过曝或断裂。
- 数据多样性:
- 采集多组不同位姿的数据以提高标定鲁棒性。
- 误差分析:
- 若RMSE较大,检查激光线提取或标定板位姿计算是否准确。
5. 应用场景
- 结构光三维扫描:将激光平面方程用于三角测量。
- 机器人导航:激光平面用于地面检测或障碍物识别。
通过此流程,可以高精度标定激光平面,为后续三维重建提供基础。

浙公网安备 33010602011771号