最近放暑假,想再回顾一下激光三角法,整理内容如下所示:
1 原理
激光器发射出的是一个激光平面,也叫光刀面,激光平面照射到物体上就形成了一道线激光。整个仪器一边是相机,另一边是线激光器,线激光器将线结构光打在物体上,相机拍摄到线激光的画面,(Figure1-右)然后计算出激光线上的像素点的深度值,就能够恢复出物体的三维结构了。
2 步骤
相机标定 -> 激光平面的标定 -> 激光线的提取 -> 三维重建
相机标定的详细步骤可见前文:link
2.1 相机标定
采用张定友标定法,得到相机的内参和外参并保存。
2.2 激光平面的标定
目的:获得激光平面在相机坐标系下的平面方程,从而可以获得图像线激光上像素点的深度。
注意:平面方程是在相机坐标系下定义的,所以一旦激光平面标定完成之后,激光器和相机的相对位置就必须固定不动了。
Figure2-左图就是从图像中提取激光线得到的光条中心线,每一张图片都能提取出一条激光线;一条激光线代表一张图片,最终通过最小二乘法拟合得到一个平面,就是所要求的激光平面。
步骤:
1、求激光平面与棋盘格标定板的交点(即激光线上点)在相机坐标系下的坐标
如 Figure3 所示,交点 P 是射线 OcP 和棋盘格的交点,所以可以先求出棋盘格标定板和射线 OcP 在相机坐标系下的方程,然后联立得到 P 点在相机坐标系下的方程。
取多张带激光线的棋盘格照片,在每张图的激光线段上取两个点,得到这些点在像素坐标系下的坐标 (u, v, 1)。
相机标定时所定义的世界坐标系是以标定板所在平面为 Zw = 0 的平面 (xoy 平面),可以通过世界坐标系下 Zw = 0 标定板平面倒推相机世界坐标系下标定板平面的方程。
由上式最后一行可知,由于 Zw = 0, 所以 r31Xc + r32Yc + r33Zc + t3 = 0 为棋盘格标定板在相机坐标系下的方程。
2. 求激光平面在相机坐标系下的方程
2.3 激光线的提取:使用极值法
首先将图像转成灰度图,设定一个亮度阈值,用于准确的判断激光线,然后在图像上进行按行寻找,寻找每一行亮度的最大值,得到的就是激光线上的点在像素坐标系下的坐标。
2.4 三维重建
根据标定得到的激光平面方程,可以求得激光线上的点在相机坐标系下的三维坐标(方法如上面求 P 点在相机坐标系下的坐标,只不过这里联立的方程是射线 OcP 和激光平面)。三维重建重建的是一个物体,每一帧图像都可以得到一条激光线上的三维点坐标,但都是相机坐标系下的坐标,需要转化到世界坐标系下。所以需要进行多帧拼接,也就是把所有相机坐标系下求得的三维点转化到一个世界坐标系下。这里只有一帧。由相机坐标系下坐标-> 世界坐标系下坐标的原理:
3 代码及实验结果
all代码:激光三角法matlab代码
代码例子 - 激光线的提取:
% 激光线的提取,关键代码,全部代码请参考上述gitee仓库链接
% 寻找每行的最大值
for i = crop_h(1) : crop_h(2)
%保存每一行亮度最大值max0,并且记录该值的坐标max_ij
max0 = img(i, crop_w(1));
max_ij = [i, crop_w(1)];
for j = crop_w(1):crop_w(2)
if img(i, j) > max0 && img(i, j) > T
max0 = img(i, j);
max_ij = [i, j];
end
end
%max比初始值大时,说明成功找到大于阈值t的激光点,记录该点
%to do对于uv的操作,每循环一次,就向uv=[]中加入一个点
uv = [uv;[max_ij(2),max_ij(1)]];
%uv = [uv;max_ij];i:列,j:行
maxImg(max_ij(1),max_ij(2))=255;
end