第三章 激光三角法原理

做三维测量这些年,我接触过不少光学方案。结构光、双目视觉、共聚焦……各有各的看家本领。但要说工业现场用得最多、最皮实的,还得是激光三角法。

说白了,这玩意儿就是用一个激光器打出一条线,再用相机从侧面拍。激光照到物体表面,线就变形了。变形量里藏着高度信息。嗯,就这么简单。

但简单归简单,真要把它做稳定、做精准,里面门道不少。今天我就把激光三角法的核心原理、光条提取算法和标定板设计,掰开了跟你聊聊。

核心要点:激光三角法的本质是利用几何相似三角形,将图像中的光条偏移量换算成实际高度值。精度取决于光条提取的亚像素精度和系统标定的准确性。

3.1 激光发射器与相机的几何关系

先看最基础的配置。激光器垂直向下打光,相机从侧面斜着拍。激光照到基准面上是一条直线,照到凸起的物体上,光条就会偏移。

为什么会这样?你想想看,物体表面比基准面高,激光打上去的位置自然就变了。相机从侧面看过去,这个位置变化在图像上就是一个像素位移。

我习惯把这种配置叫「直射式三角法」。它的几何关系很清晰:

  • 激光光轴与相机光轴之间的夹角,我一般取30°到45°之间
  • 夹角太小,灵敏度不够;夹角太大,遮挡严重
  • 相机镜头的光轴要尽量与激光平面共面

这里有个公式你得记住:

ΔZ = Δx / (M × sinθ)

其中:

  • ΔZ 是实际高度变化
  • Δx 是图像上的光条偏移量(像素)
  • M 是光学放大倍率
  • θ 是激光与相机光轴的夹角

我在项目中遇到过一个问题:夹角选大了,灵敏度确实高,但物体侧面陡峭的地方,激光直接打不到相机视野里。后来我学乖了,一般先做个仿真,看看最大测量范围下会不会出现遮挡。

我的经验:实际安装时,激光器和相机都要用精密调节架。别指望手拧螺丝就能对准。我曾经为了省一个调节架,结果调试花了三天——得不偿失。

3.2 光条中心提取算法

激光打在物体上,图像里是一条亮带。但这条亮带是有宽度的,可能几个像素到十几个像素不等。我们需要找到它的「中心」位置——这才是激光真正打到的地方。

提取光条中心的方法很多,我挑三个最常用的讲:极值法、灰度重心法、Steger算法。

3.2.1 极值法

这是最朴素的方法。对每一列像素,找到灰度值最大的那个点,就认为是光条中心。

// 伪代码:极值法
for each column in image:
    max_gray = 0
    center_row = 0
    for each row in column:
        if gray(row, col) > max_gray:
            max_gray = gray(row, col)
            center_row = row
    save_center(column, center_row)

优点:快,真的快。缺点:精度只有像素级,而且对噪声敏感。

我一般只在快速预览或者粗定位时用极值法。真要出数据,还得看下面两种。

3.2.2 灰度重心法

这个方法比极值法聪明一点。它不找最亮的点,而是找光条的「重心」。就像找一根不均匀木棍的平衡点一样。

// 伪代码:灰度重心法
for each column in image:
    sum_gray = 0
    sum_weighted = 0
    for each row in column:
        g = gray(row, col)
        sum_gray += g
        sum_weighted += row * g
    center_row = sum_weighted / sum_gray
    save_center(column, center_row)

灰度重心法能达到亚像素精度。我实测过,在光条质量好的情况下,重复精度能做到0.1像素以内。

注意:灰度重心法对光条的对称性有要求。如果激光打在镜面或者透明物体上,光条会变形,重心法就会偏。我曾经在测玻璃面板时吃过这个亏。

3.2.3 Steger算法

Steger算法是目前工业界公认的「天花板」。它基于Hessian矩阵,把光条看成一条曲线,然后找到曲线的脊线。

说白了,它不光看灰度值,还看灰度变化的趋势。就像爬山,极值法只看山顶,重心法看整座山的重心,Steger算法则分析山的坡度变化,找到真正的山脊线。

// 伪代码:Steger算法核心步骤
1. 对图像做高斯平滑,计算一阶和二阶偏导数
2. 构建Hessian矩阵:H = [Ixx, Ixy; Ixy, Iyy]
3. 计算Hessian矩阵的特征值和特征向量
4. 在法线方向上,用泰勒展开求极值点
5. 亚像素精度定位

Steger算法的精度很高,通常能做到0.05像素级别。但代价是计算量大。我建议在离线标定或者高精度检测场景下使用。在线实时检测的话,得用GPU加速。

算法 精度 速度 抗噪能力 适用场景
极值法 像素级 极快 粗定位、预览
灰度重心法 亚像素(~0.1px) 中等 常规检测
Steger算法 高精度(~0.05px) 较慢 高精度标定、离线检测

3.3 标定板设计

有了算法,还得有标定板。没有标定,你测出来的数据就是「像素偏移」,不是「毫米高度」。

标定板的作用,说白了就是建立像素坐标和世界坐标之间的映射关系。

我常用的标定板有两种:

  • 台阶式标定板:几个已知高度的台阶,激光打上去形成几条平行线。通过线间距反算像素-高度比例。
  • 斜面式标定板:一个已知角度的斜面,激光打上去是一条斜线。通过斜线的斜率计算映射关系。

我个人更偏爱台阶式。为什么?因为台阶的边界清晰,不容易引入拟合误差。斜面标定板对安装角度要求太高,稍微偏一点,标定结果就漂了。

避坑指南:标定板的表面处理很重要。我曾经用了一块磨砂不锈钢板,结果激光打上去有散斑,光条提取精度直接掉了一个数量级。后来换成黑色阳极氧化处理的铝板,效果就好多了。

标定步骤大致如下:

  1. 将标定板放在测量范围内多个已知位置
  2. 采集每个位置的光条图像
  3. 提取光条中心(建议用Steger算法)
  4. 建立像素偏移量与实际高度的映射表
  5. 用多项式拟合或插值法生成标定曲线

嗯,这里要注意:标定不是一次性的。温度变化、机械振动、镜头松动都会导致标定参数漂移。我建议每次开机后先跑一遍标定验证流程,确认偏差在允许范围内再开始测量。

总结一下:激光三角法的核心就三件事——几何关系要算对,光条中心要提准,标定要做扎实。这三件事做好了,剩下的就是工程细节了。

激光三角法知识体系 激光三角法 几何关系 光条中心提取 标定板设计 直射式三角法 夹角选择30°-45° 极值法 灰度重心法 Steger算法 台阶式标定板 斜面式标定板 核心公式:ΔZ = Δx / (M × sinθ) 几何关系 + 精确提取 + 可靠标定 = 高精度测量

公众号:蓝海资料掘金营,微信deep3321