4、校准数学基础:线性变换、最小二乘法、仿射变换矩阵

做触摸校准,说白了就是解决一个问题:你点的是 A 点,系统却以为你点的是 B 点。怎么把 B 点映射回 A 点?这就得靠数学了。

我刚开始做触控驱动时,总觉得数学是理论派的事。直到有一次量产前发现一批屏的触摸偏差大到离谱,才老老实实把线性代数翻出来重新啃了一遍。嗯,今天这节内容,就是当年那批血的教训换来的。

核心思想:触摸校准的本质,就是找到一个数学映射关系,把触摸屏上报的原始坐标,转换成用户期望的物理坐标。

4.1 线性变换:校准的起点

先问一个问题:为什么是线性变换?

你想想看,触摸屏和显示屏之间,无非就是平移、旋转、缩放、剪切这几种关系。这些操作,恰好都是线性变换能描述的。说白了,线性变换就是一条直线搞定的事——输入和输出之间是比例关系。

数学上,一个二维线性变换可以写成:

x' = a * x + b * y + c
y' = d * x + e * y + f

这里 (x, y) 是触摸屏上报的原始坐标,(x', y') 是校准后的物理坐标。a, b, c, d, e, f 就是我们要找的六个参数。

我个人习惯把这个公式叫做「六参数模型」。为什么是六个?因为二维仿射变换的自由度就是 6——两个方向各有一个缩放、一个旋转、一个平移,加起来正好六个。

参数 物理含义 典型范围
a, e X/Y 方向缩放因子 0.8 ~ 1.2
b, d 旋转/剪切因子 -0.1 ~ 0.1
c, f X/Y 方向平移量 -50 ~ 50 (像素)

我的经验:如果校准后某个方向偏差特别大,先检查 a 和 e。有一次我发现 X 方向总是偏 5%,查了半天发现是触摸屏的 ADC 参考电压和显示屏的像素时钟不同步导致的。改完 a 参数,问题就解决了。

4.2 最小二乘法:从数据中找规律

好,公式有了,参数怎么求?

你不可能拿着尺子去量每个像素的偏差。实际做法是:让用户点几个已知坐标的点,然后根据这些「采样点」反推参数。

但问题来了——用户点的时候手会抖,触摸屏本身也有噪声。你采集到的数据,不可能完美落在一条直线上。这时候就需要最小二乘法出马了。

最小二乘法的思路很简单:让误差的平方和最小。什么叫误差?就是「你实际点的位置」和「模型算出来的位置」之间的差距。

数学上,我们定义误差函数:

E = Σ [ (x'_i - (a*x_i + b*y_i + c))² + (y'_i - (d*x_i + e*y_i + f))² ]

然后对 a, b, c, d, e, f 分别求偏导,令偏导等于 0,解这个方程组就行了。

我记得第一次手动推导这个方程组时,算了整整两页草稿纸。后来发现,其实可以用矩阵形式一步到位:

令:
  X = [x1, y1, 1; x2, y2, 1; ...; xn, yn, 1]  (n×3 矩阵)
  Y = [x'_1, y'_1; x'_2, y'_2; ...; x'_n, y'_n]  (n×2 矩阵)
  P = [a, d; b, e; c, f]  (3×2 矩阵)

则最小二乘解为:
  P = (X^T * X)^(-1) * X^T * Y

避坑指南:我曾经在项目里直接用浮点运算求逆矩阵,结果在低端 MCU 上跑一次要 200ms,用户明显感觉到卡顿。后来改用定点数 + 查表法,把时间压到了 5ms 以内。如果你的平台算力有限,记得做优化。

4.3 仿射变换矩阵:把一切串起来

有了最小二乘法,我们就能求出六个参数。但这六个参数怎么组织,才能方便后续计算?

答案是:仿射变换矩阵。

把前面的公式写成矩阵形式:

[x']   [a  b  c]   [x]
[y'] = [d  e  f] * [y]
[1 ]   [0  0  1]   [1]

这个 3×3 的矩阵,就是仿射变换矩阵。它把平移、旋转、缩放、剪切全部打包在一起。你想想看,有了这个矩阵,任何原始坐标 (x, y) 都能通过一次矩阵乘法得到校准后的坐标 (x', y'),多干净利落。

我个人习惯把这个矩阵叫做「校准矩阵」。在代码里,我通常用一个长度为 6 的数组来存:

// 校准矩阵参数:a, b, c, d, e, f
float calib[6];

// 校准函数
void touch_calibrate(int raw_x, int raw_y, int *cal_x, int *cal_y) {
    *cal_x = (int)(calib[0] * raw_x + calib[1] * raw_y + calib[2] + 0.5f);
    *cal_y = (int)(calib[3] * raw_x + calib[4] * raw_y + calib[5] + 0.5f);
}

我的习惯:加 0.5 做四舍五入,而不是直接截断。别小看这 0.5,它能减少 0.5 像素的系统偏差。在触摸屏这种高精度场景下,每一像素的偏差都可能影响用户体验。

4.4 知识体系总览

说了这么多,我把整个校准的数学逻辑画成了一张图,方便你理解:

触摸校准数学体系 原始触摸坐标 (x, y) 线性变换模型 校准后坐标 (x', y') 最小二乘法求解 采样点 (x_i, y_i, x'_i, y'_i) 仿射变换矩阵 六参数模型 a, b, c, d, e, f 一次矩阵乘法搞定

4.5 实战中的注意事项

理论讲完了,说几个我在项目中踩过的坑:

  • 采样点数量:最少 3 个点才能解六参数模型。但我建议用 5 个点以上,因为采样点越多,最小二乘法对噪声的抑制效果越好。
  • 采样点分布:别把点都挤在一个角落。尽量覆盖屏幕的四个角和中心,这样校准矩阵对全屏都有较好的效果。
  • 矩阵求逆的稳定性:如果采样点几乎共线,矩阵 X^T * X 会接近奇异,求逆结果会爆炸。我遇到过这种情况,后来加了条件数检查,条件数超过阈值就提示用户重新采样。
  • 浮点 vs 定点:在嵌入式平台上,能用定点就别用浮点。我一般把参数放大 2^16 倍存成整数,计算时用移位操作还原,速度和精度都能兼顾。

一句话总结:线性变换描述关系,最小二乘法求参数,仿射变换矩阵做计算。这三者串起来,就是触摸校准的数学骨架。