- 计算机视觉
- 深度学习
- 图像处理
【免费下载链接】kornia
🐍 Geometric Computer Vision Library for Spatial AI
本篇技术指南聚焦 Kornia 中一次关键的单应矩阵(Homography)估计数值修复:find_homography_dlt(..., solver="lu")对最小四点系统改用自适应齐次 Gauge(adaptive homogeneous gauge)求解,取代了对奇异正规矩阵(normal matrix)的 LU 分解。该变更直接影响RANSAC(model_type="homography")在每一轮最小样本上的估计结果,修复了 Windows + PyTorch 2.14 下的全 NaN 单应矩阵问题,并显著降低了传输残差。读完本文,你将理解 DLT 最小四点系统为何数值上脆弱、新 Gauge 算法如何工作、它对 RANSAC 精度的影响,以及哪些使用路径不受影响。
变更背景:最小四点系统为何是数值"雷区"
DLT(Direct Linear Transform)是估计单应矩阵的经典方法。给定两幅图像间的 N 组点对应(points1, points2),每个对应关系贡献两个线性方程(ax与ay两行),Kornia 在 kornia/geometry/homography.py 中通过拼接构造出形状为(B, 2N, 9)的设计矩阵A:
ax = torch.cat([zeros, zeros, zeros, -x1, -y1, -ones, y2 * x1, y2 * y1, y2], dim=-1) ay = torch.cat([x1, y1, ones, zeros, zeros, zeros, -x2 * x1, -x2 * y1, -x2], dim=-1) A = torch.cat((ax, ay), dim=-1).reshape(ax.shape[0], -1, ax.shape[-1])欠定问题与奇异正规矩阵
单应矩阵H是 3×3 矩阵、有 9 个参数,但齐次坐标下尺度自由,实际只有 8 个自由度。当样本恰好为 4 个点时,A的形状是(B, 8, 9),8 个方程求解 9 个未知数——这是一个**欠定(underdetermined)**系统,解空间是一维的(即零空间向量,null vector)。
旧实现把所有情况统一处理:先构造成正规方程AᵀA(见 kornia/geometry/homography.py),再对AᵀA(形状(B, 9, 9))做 LU 分解求解。问题在于:四点情形下AᵀA是奇异的(秩至多为 8),对其做 LU 分解在数值上是不稳定的——这正是旧代码在特定平台产出全 NaN 单应矩阵的根源。
固定 h33=1 Gauge 的隐患
齐次坐标下还需要固定一个"规范"(gauge)来消除尺度模糊,最常见的选择是固定h33 = 1。但源码注释明确指出:
A fixed h33=1 gauge is invalid whenever the bottom-right entry is zero.
当真实单应矩阵的右下角元素h33恰好(或数值上)接近 0 时,固定h33=1的约束本身就让求解系统退化。对应测试 tests/geometry/test_homography.py 展示了一个这样的构造:归一化坐标系下的零向量最后一维约为-1.3e-16,此时固定h33=1的 gauge 是奇异的。
Windows + PyTorch 2.14 的全 NaN 复现
find_homography_dlt是RANSAC(model_type="homography")在每个最小样本上都要调用的估计器(见 kornia/geometry/ransac.py)。RANSAC 每轮迭代会从数百上千个点对中抽取一个四点最小样本,只要抽样抽到上述退化配置,旧 LU 路径就可能在特定平台(如 Windows + PyTorch 2.14)上产出全 NaN 的H。而 NaN 会沿 RANSAC 的验证链路静默传播,污染整个估计结果——这正是本次修复要消灭的核心问题。
新求解器:自适应齐次 Gauge
本次修复(PR #4197,见 changelog.d/+migration-097.fixed.md)的关键决策是:四点最小样本不再构造正规方程,而是直接从设计矩阵本身求零向量。源码中的路径判断非常清晰(kornia/geometry/homography.py):
minimal_lu = solver == "lu" and points1.shape[1] == 4 if not minimal_lu: A = A.transpose(-2, -1) @ A if w_full is None else (A.transpose(-2, -1) * w_full) @ A只有当solver == "lu"且点数恰好为 4 时,才走新的自适应 Gauge 路径;其余情况保持原正规方程公式。新路径的算法步骤(kornia/geometry/homography.py)如下:
第 1 步:完整 QR 求零向量
对转置后的加权设计矩阵执行完整的 QR 分解:
Q, _ = torch.linalg.qr(Aw.detach().to(gauge_dtype).transpose(-2, -1), mode="complete") null = Q[..., -1]Q的最后一列即Aw的零向量(null vector),它张成最小四点系统的一维解空间。值得注意的是,QR 在float64(若输入是 float64)或float32的gauge_dtype下计算,且带.detach()——该中间过程不参与反向传播,避免奇异中间量污染梯度(这也与测试 tests/geometry/test_homography.py 中"奇异梯度穿过估计单应矩阵"的防护目标一致)。
第 2 步:argmax 选择 Gauge
gauge = null.abs().argmax(dim=-1)取零向量绝对值最大的分量作为固定位置。这样,gauge 是自适应的:它总能选到一个非零分量来固定,不会像固定h33=1那样在特定配置下失效。每个 batch 样本可以选择不同的 gauge 分量。
第 3 步:求解保留的 8×8 系统
固定第gauge个分量为 1 后,剩下的 8 个未知数组成一个 8×8 系统:
retained = torch.arange(8, device=device).expand(A.shape[0], -1) retained = retained + (retained >= gauge[:, None]).to(retained.dtype) selected = Aw.gather(-1, retained[:, None].expand(-1, 8, -1)) B = -Aw.gather(-1, gauge[:, None, None].expand(-1, 8, 1)).squeeze(-1) sol, _, valid = safe_solve_with_mask(B, selected)safe_solve_with_mask同时返回valid掩码,用于标记系统是否奇异。
第 4 步:零权重退化回退
当样本中存在权重为 0 的对应关系时,会零化设计矩阵的两行,使保留的 8×8 系统变得奇异。此时代码直接回退到零向量(它仍然有限,且满足幸存的方程),而不是把 NaN 交给调用方:
null = (null / null.gather(-1, gauge[:, None])).to(sol.dtype) sol = torch.where(valid[:, None], sol, null.gather(-1, retained))第 5 步:组装与反归一化
把解按 gauge 位置插回 9 维,重排为 3×3,再撤销前面的点归一化:
H = safe_inverse_with_mask(transform2)[0] @ (H @ transform1) return H / (H[..., -1:, -1:] + eps)对 RANSAC(homography) 的精度与行为影响
调用链确认
RANSAC在model_type="homography"时把find_homography_dlt绑定为minimal_solver(kornia/geometry/ransac.py),每一轮随机抽样产生的四点最小样本都会经过新路径,polisher 阶段则使用迭代加权的find_homography_dlt_iterated。因此这次修复的影响面是所有平台上的 homography RANSAC:
homography RANSAC results change on every platform, not only where the old formulation broke down
也就是说,这不仅是修一个崩溃 bug,而是让所有平台的 RANSAC 输出都发生数值变化(变得更准)。
实测残差下降
变更记录给出的量化结果是:在超过 2048 个最小样本的测试集上——
| 指标 | 修复前 | 修复后 |
|---|---|---|
| 中位传输残差(median transfer residual) | 2.3e-5 | 1.9e-6 |
| 最坏情况残差(worst case) | 4.2e+5 | 4.5e+2 |
中位残差下降约一个数量级,而最坏情况从4.2e+5骤降至4.5e+2(下降近 3 个数量级)——这直接反映了原先奇异系统在退化配置下产生的病态解有多离谱。
行为变化清单
- 修复 Windows + PyTorch 2.14 上四点样本的全 NaN 单应矩阵;
- 移除对应的 CPU 半精度(half-precision)已知失败(known failures)条目;
- 含零权重的四点样本现在返回有限(finite)的单应矩阵而非 NaN;
- 若项目中已有依赖旧 LU 数值结果的测试基准或管线,需要重新校准。
哪些路径保持不变
本次修复刻意保持了向后兼容的数值边界,源码注释与变更记录都明确:
- 五点及以上样本:仍然走正规方程
AᵀA公式,且"数值上不变"(numerically unchanged)。加权路径还特意保持了与原实现完全一致的运算顺序(见 kornia/geometry/homography.py),保证带权重结果与修复前逐位一致; solver="svd"路径:不受影响,仍对设计矩阵(或正规矩阵)做 SVD 取最小奇异值对应的右奇异向量(kornia/geometry/homography.py)。SVD 本身对奇异系统更稳健,但代价是计算开销更大;- 逐点归一化(
normalize_points)与反归一化、以及最终的h33归一化(带eps = 1e-8防除零)流程不变。
测试保障:从回归到梯度检查
Kornia 为这次修复配套了密集的测试,可在 tests/geometry/test_homography.py 中查看:
test_zero_weight_minimal_lu(tests/geometry/test_homography.py):用[1,1,1,0]、[1,1,0,0]、全零三种权重配置断言结果全部有限,且混合 batch 中健康样本的结果不受退化样本影响——防止 NaN 经 RANSAC 验证链路静默传播;test_scaled_fixed_points(tests/geometry/test_homography.py):目标点放大 100 倍的极端缩放场景,验证lu路径有限且重投影闭环正确;test_projective_fixed_points(tests/geometry/test_homography.py):专门守护自适应 Gauge 本身,覆盖h33 ≈ 0的投影退化配置;test_gradcheck_lu_minimal(tests/geometry/test_homography.py):对最小四点lu路径做梯度检查(gradcheck),保证find_homography_dlt保持可微——这一点对端到端可学习管线至关重要;test_nocrash_lu(tests/geometry/test_homography.py):输入含 NaN 点时不崩溃,保持形状输出。
此外,半精度已知失败清单testing/half_precision_xfails/cpu_bfloat16.txt与cpu_float16.txt中不再包含最小四点lu路径的失败条目,印证了"移除相应 CPU 半精度已知失败"的变更声明。
使用与验证建议
参数说明
find_homography_dlt的签名与参数(kornia/geometry/homography.py):
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
points1 | Tensor(B, N, 2) | — | 第一幅图像的点集,N ≥ 4,否则抛AssertionError |
points2 | Tensor(B, N, 2) | — | 第二幅图像的点集,形状须与points1一致 |
weights | Tensor(B, N)或None | None | 每个点对应的权重;None表示等权 |
solver | str | "lu" | 可选"svd"或"lu";仅lu且N == 4时走新 Gauge 路径 |
实操建议
- 默认
solver="lu"即可获得新算法的全部收益:四点最小样本自动走自适应 Gauge 路径,五点以上自动回落正规方程; - 若你的应用主要依赖五点以上样本(例如直接调用
find_homography_dlt而非 RANSAC),结果与修复前保持一致,无需改动; - 若你自定义了基于
RANSAC的单应矩阵管线,建议重新跑一遍回归测试并复核精度指标(传输残差、内点率),因为所有平台的最小样本估计结果都有数值变化; - 需要更高数值余量时仍可显式选择
solver="svd",它在奇异与近奇异配置下同样稳健,但开销更大、且不与新 Gauge 路径共享实现。
本次修复是 Kornia 几何核心层一次典型的"小函数、大影响"变更:find_homography_dlt一个函数的行为调整,通过RANSAC的minimal_solver调用链辐射到所有单应矩阵估计场景,用自适应齐次 Gauge 从根上消除了最小四点系统的奇异数值路径。
- 计算机视觉
- 深度学习
- 图像处理
【免费下载链接】kornia
🐍 Geometric Computer Vision Library for Spatial AI
相关推荐
Kornia 单应估计数值稳定性修复:find_homography_dlt 的自适应齐次 gauge 详解
Kornia 单应估计数值稳定性修复:find_homography_dlt 的自适应齐次 gauge 详解 本篇技术指南围绕 Kornia 几何模块的一次关键
人工智能计算机视觉深度学习图像处理多视图几何的终极指南:openMVG中的基础矩阵与单应矩阵估计
多视图几何的终极指南:openMVG中的基础矩阵与单应矩阵估计 多视图几何是3D计算机视觉的核心技术,而openMVG作为开源多视图几何库,提供了强大的基础矩阵
计算机视觉图像处理科研kornia.geometry.homography 完全指南:单应矩阵估计、评分与 RANSAC 集成
kornia.geometry.homography 完全指南:单应矩阵估计、评分与 RANSAC 集成 本指南以 kornia 文档中 kornia.geom
计算机视觉深度学习图像处理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考