4、三点校准法:三个校准点的选取策略、建立方程组、求解转换矩阵

三点校准法,说白了就是触摸屏校准里最经典、最实用的方法。你想想看,两点校准只能解决平移和缩放,但实际触摸屏的安装、贴合过程中,难免会有旋转和倾斜。这时候,三点校准就派上用场了。

我个人习惯把三点校准叫做“全参数校准”。因为它能同时修正X轴和Y轴的缩放、旋转、平移,以及两轴之间的正交误差。嗯,这里要注意——正交误差是什么?就是触摸屏的X轴和LCD的X轴不完全平行,有个小夹角。这在批量生产中很常见,两点校准根本搞不定。

4.1 三个校准点的选取策略

选点不是随便点的。我在项目中踩过坑,一开始图省事,把三个点选在屏幕左上角附近,结果校准完,右下角偏差大得离谱。后来才明白,选点要讲究“覆盖”和“分散”。

具体来说,有这几个原则:

  • 覆盖显示区域:三个点应该尽量分散在屏幕的不同角落,形成一个三角形,覆盖大部分有效显示区。
  • 避免共线:三个点绝对不能在同一条直线上。一旦共线,方程组就解不出来了,矩阵会奇异。说白了就是“无解”。
  • 远离边缘:我个人建议离屏幕边缘留出5%-10%的余量。因为边缘区域的触摸线性度往往最差,选在边缘反而引入误差。
  • 对称分布:最经典的选法是左上、右上、左下(或右下),形成一个近似等边三角形。这样各方向的权重均衡。
我的经验: 曾经在一个7寸屏项目上,我把三个点选在(10%, 10%)、(90%, 10%)、(50%, 90%)的位置。这个分布覆盖了左右和底部,效果很稳定。你可以参考这个比例,但要根据实际分辨率微调。

下面这张图展示了三个校准点的典型分布策略:

三点校准法——校准点分布策略 有效显示区域 5%-10% 余量 P1 (10%, 10%) P2 (90%, 10%) P3 (50%, 90%) ✓ 三角形覆盖大部分区域 ✓ 三点不共线,方程组可解 ✓ 远离边缘,避开非线性区

4.2 建立方程组——从物理坐标到显示坐标

好,点选好了。接下来要干什么?建立数学关系。说白了,就是找到一个转换矩阵,能把触摸屏上报的物理坐标(x, y)映射到LCD的显示坐标(X, Y)。

三点校准用的是仿射变换模型。它比两点校准多了一个旋转项。数学表达式是这样的:

X = A * x + B * y + C
Y = D * x + E * y + F

这里有6个未知数:A、B、C、D、E、F。每个点提供两个方程(一个X,一个Y),三个点正好提供6个方程。方程组刚好可解。

你想想看,如果只有两个点,只能解出4个参数,旋转和正交误差就丢了。这就是为什么三点校准更准的根本原因。

把三个点的数据代入,得到完整的方程组:

对于点1 (x1, y1) → (X1, Y1):
  X1 = A * x1 + B * y1 + C
  Y1 = D * x1 + E * y1 + F

对于点2 (x2, y2) → (X2, Y2):
  X2 = A * x2 + B * y2 + C
  Y2 = D * x2 + E * y2 + F

对于点3 (x3, y3) → (X3, Y3):
  X3 = A * x3 + B * y3 + C
  Y3 = D * x3 + E * y3 + F
核心要点: 这6个方程是线性的。虽然触摸屏和LCD的关系是非线性的,但在小范围内(比如一个屏幕内),用线性仿射变换近似已经足够。如果屏幕很大或者畸变严重,那就得考虑更复杂的模型了——不过那是后话。

4.3 求解转换矩阵——两种实用方法

方程组有了,怎么解?我一般用两种方法,看项目资源来选。

方法一:矩阵求逆法(适合有数学库的平台)

把方程组写成矩阵形式:

| X1 |   | x1  y1  1  0   0   0 |   | A |
| Y1 |   | 0   0   0  x1  y1  1 |   | B |
| X2 | = | x2  y2  1  0   0   0 | * | C |
| Y2 |   | 0   0   0  x2  y2  1 |   | D |
| X3 |   | x3  y3  1  0   0   0 |   | E |
| Y3 |   | 0   0   0  x3  y3  1 |   | F |

简写为:V = M * P

那么:P = M⁻¹ * V

只要M可逆(三个点不共线就能保证),直接求逆矩阵,乘一下,6个参数就出来了。我在Cortex-M4上跑过,浮点运算大概几十微秒,完全够用。

方法二:高斯消元法(适合裸机、无数学库)

如果平台没有矩阵库,或者你不想引入依赖,那就手写高斯消元。把6个方程当成6元一次方程组,逐行消去。代码量不大,我贴一个我常用的实现片段:

// 三点校准 - 高斯消元求解6个参数
// 输入:三个点的触摸坐标 (tx[], ty[]) 和显示坐标 (lx[], ly[])
// 输出:参数 A, B, C, D, E, F
void calc_3point_calib(float *tx, float *ty, float *lx, float *ly,
                       float *A, float *B, float *C, 
                       float *D, float *E, float *F) {
    // 构造增广矩阵 (6行 x 7列)
    float mat[6][7];
    for (int i = 0; i < 3; i++) {
        int r = i * 2;
        mat[r][0] = tx[i];  mat[r][1] = ty[i];  mat[r][2] = 1;
        mat[r][3] = 0;      mat[r][4] = 0;       mat[r][5] = 0;
        mat[r][6] = lx[i];
        
        mat[r+1][0] = 0;    mat[r+1][1] = 0;     mat[r+1][2] = 0;
        mat[r+1][3] = tx[i]; mat[r+1][4] = ty[i]; mat[r+1][5] = 1;
        mat[r+1][6] = ly[i];
    }
    
    // 高斯消元(列主元)
    for (int col = 0; col < 6; col++) {
        // 找主元
        int max_row = col;
        for (int row = col + 1; row < 6; row++) {
            if (fabs(mat[row][col]) > fabs(mat[max_row][col]))
                max_row = row;
        }
        // 交换行
        for (int j = col; j <= 6; j++) {
            float tmp = mat[col][j];
            mat[col][j] = mat[max_row][j];
            mat[max_row][j] = tmp;
        }
        // 消去
        for (int row = col + 1; row < 6; row++) {
            float factor = mat[row][col] / mat[col][col];
            for (int j = col; j <= 6; j++) {
                mat[row][j] -= factor * mat[col][j];
            }
        }
    }
    
    // 回代求解
    for (int i = 5; i >= 0; i--) {
        mat[i][6] /= mat[i][i];
        for (int j = i - 1; j >= 0; j--) {
            mat[j][6] -= mat[j][i] * mat[i][6];
        }
    }
    
    *A = mat[0][6]; *B = mat[1][6]; *C = mat[2][6];
    *D = mat[3][6]; *E = mat[4][6]; *F = mat[5][6];
}
我曾经踩过的坑: 有一次在STM32上跑这个代码,发现校准结果偶尔跳变。查了半天,原来是触摸坐标有噪声,导致矩阵轻微病态。后来我在采集每个点时做了多次采样取平均,问题就解决了。所以——输入数据一定要滤波,不然矩阵再漂亮也白搭。

4.4 参数验证与常见问题

参数算出来就完事了?当然不是。我建议做两步验证:

  1. 回代验证:把三个点的触摸坐标代回公式,算出来的显示坐标应该和原始显示坐标几乎一致。偏差超过1个像素就要警惕了。
  2. 随机点验证:在屏幕上随机点几个位置,看看校准后的坐标是否准确。这一步能发现“过拟合”问题——三个点很准,但中间区域反而偏了。

下面这个表格总结了三点校准的常见问题和对策:

问题现象 可能原因 我的建议
校准后边缘偏差大 校准点太靠近边缘,或分布不均匀 重新选点,保证三角形覆盖中心区域
校准结果偶尔跳变 触摸坐标噪声大,矩阵病态 多次采样取平均,或增加滤波
三个点准,中间不准 触摸屏本身非线性严重 考虑四点或九点校准,用更复杂的模型
矩阵求逆失败 三个点共线或太接近 检查选点,确保三角形面积足够大

最后说一句,三点校准法虽然经典,但不是万能的。如果触摸屏的畸变是桶形或枕形(比如一些曲面屏),线性模型就扛不住了。那时候得用更高阶的模型——不过那是后面章节的内容了。