“libinput 校准矩阵”的具体格式是什么(即其每个元素代表什么)以及它与“坐标变换矩阵”有何关系?如果“坐标变换矩阵”负责将触摸屏点映射到显示点,为什么它不够用,为什么还需要“libinput 校准矩阵”?每个矩阵负责校准过程的哪一部分?
我找不到任何参考网站来解释“libinput 校准矩阵”元素的含义(相对于“坐标变换矩阵”而言)。我所能找到的只是以下相关系数的“定义”:
a = (screen_x * 6 / 8) / (c3_x - c0_x)
c = ((screen_x / 8) - (a * c0_x)) / screen_x
e = (screen_y * 6 / 8) / (c3_y - c0_y)
f = ((screen_y / 8) - (e * c0_y)) / screen_y
没有任何解释说明它们是如何得出的/它们应该代表什么。总结一下:“libinput 校准矩阵”的“官方”定义是什么,它与“坐标变换矩阵”有何不同?
答案1
我开发了 xlibinput_calibrator。在这里 [1],您可以找到“校准矩阵”计算背后的数学实现。
基本上,你需要将坐标从“触摸空间”转换到“屏幕空间”。为此,首先你需要收集“触摸空间”和“屏幕空间”中至少 3 个点的坐标。[2]
校准矩阵(C)、“触摸空间”中的坐标(tx_i,ty_i,其中i=1,2,3)和“屏幕空间”中的坐标(sx_i,sy_i)通过以下公式关联:
⎡tx₁ tx₂ tx₃⎤ ⎢ ⎥ Ti = ⎢ty₁ ty₂ ty₃⎥ ⎢ ⎥ ⎣ 0 0 1 ⎦ ⎡sx₁ sx₂ sx₃⎤ ⎢ ⎥ Si = ⎢sy₁ sy₂ sy₃⎥ ⎢ ⎥ ⎣ 0 0 1 ⎦ ⎡abc⎤ ⎢ ⎥ C = ⎢def⎥ ⎢ ⎥ ⎣0 0 1⎦ ⎡abc⎤ ⎡tx₁ tx₂ tx₃⎤ ⎡sx₁ sx₂ sx₃⎤ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎢def⎥ x ⎢ty₁ ty₂ ty₃⎥ = ⎢sy₁ sy₂ sy₃⎥ ⎢ ⎥ ⎢ ⎥ ⎢ ⎥ ⎣0 0 1⎦ ⎣ 0 0 1 ⎦ ⎣ 0 0 1 ⎦ C * Ti = Si => C = Si * inv(Ti)
其中“inv(Ti)”计算 Ti 的逆矩阵。结果是(感谢 Octave):
sx₁⋅ty₂ - sx₂⋅ty₁ a = ────────────────── tx₁⋅ty₂ - tx₂⋅ty₁ - sx₁⋅tx₂ + sx₂⋅tx₁ b = ──────────────────── tx₁⋅ty₂ - tx₂⋅ty₁ sx₁⋅(tx₂⋅ty₃ - tx₃⋅ty₂) + sx₂⋅(tx₁⋅ty₃ - tx₃⋅ty₁) + sx₃⋅(tx₁⋅ty₂ - tx₂⋅ty₁) c = ────────────────────────────────────────────────────────────────────────────── tx₁⋅ty₂ - tx₂⋅ty₁ sy₁⋅ty₂ - sy₂⋅ty₁ d = ────────────────── tx₁⋅ty₂ - tx₂⋅ty₁ -sy₁⋅tx₂ +sy₂⋅tx₁ e = ────────────────── tx₁⋅ty₂ - tx₂⋅ty₁ sy₁⋅(tx₂⋅ty₃ - tx₃⋅ty₂) - sy₂⋅(tx₁⋅ty₃ - tx₃⋅ty₁) + sy₃⋅(tx₁⋅ty₂ - tx₂⋅ty₁) f = ──────────────────────────────────────────────────────────────────────────── tx₁⋅ty₂ - tx₂⋅ty₁
上面的公式是“通用”公式,其中还考虑了旋转和轴反转(以及它们的组合)等情况。您发布的公式比较简单(只需要 2 个点),在这些情况下可能会失败。
你还必须考虑到 libinput 需要标准化形式 (Cn) 的矩阵。因此它变成
⎡ b⋅sy b⋅dy⋅sy c ⎤ ⎢ a ──── a⋅dx + ─────── + ── - dx⎥ ⎢ sx sx sx ⎥ ⎢ ⎥ ⎢d⋅sx d⋅dx⋅sx f ⎥ Cn = ⎢──── e ─────── + dy⋅e - dy + ──⎥ ⎢ sy sy sy⎥ ⎢ ⎥ ⎣ 0 0 1 ⎦
在哪里
- sx = 1/宽度
- sy = 1/身高
- dx = 最小x
- dy = miny
[1]https://github.com/kreijack/xlibinput_calibrator/blob/master/src/calibrator.cc#L144
[2] 在 xlibinput_calibrator 中,我取 4 个点,结果矩阵是这些点的任意组合计算出的 4 个矩阵的平均值。