Python实现DLT算法前2D图像点归一化咨询(RMS距离为√2)
Alright, let's break down exactly how to normalize your 2D image points so their centroid is at the origin and their root-mean-square (RMS) distance from the origin is √2. This normalization is critical for DLT because it reduces numerical instability and boosts the accuracy of your homography estimation.
核心步骤讲解
First, let's recall the two key goals of this normalization:
- Translate all points so their centroid (average position) lands at (0,0).
- Scale the points so the RMS distance from each point to the origin equals √2.
Here's how to do each step mathematically and in code:
1. 计算图像点的质心
给定一组N个图像点points_2d(形状为N×3,每行是[u, v, 1]):
- 计算所有u坐标的平均值:
cu = mean(points_2d[:, 0]) - 计算所有v坐标的平均值:
cv = mean(points_2d[:, 1])
2. 计算缩放因子
首先,计算原始点到质心的均方根距离:
distances = sqrt((points_2d[:, 0] - cu)**2 + (points_2d[:, 1] - cv)**2) rms_dist = sqrt(mean(distances**2))
然后缩放因子s为:
s = sqrt(2) / rms_dist
这个因子能保证归一化后,点到原点的均方根距离恰好是√2。
3. 构建归一化变换矩阵
我们用一个3×3的齐次变换矩阵来组合平移和缩放操作:
T = np.array([ [s, 0, -s * cu], [0, s, -s * cv], [0, 0, 1] ])
将每个图像点(作为列向量)乘以这个矩阵,就能得到归一化后的点。
完整Python实现
下面是一个基于NumPy的可复用函数:
import numpy as np def normalize_image_points(points_2d): """ 为DLT算法归一化2D图像点: - 质心移动到原点 - 点到原点的均方根距离为√2 参数: points_2d: N×3的numpy数组,存储齐次坐标的2D点(u, v, 1) 返回: normalized_points: N×3的numpy数组,存储归一化后的点 T: 3×3的归一化变换矩阵 """ # 步骤1:计算质心 cu = np.mean(points_2d[:, 0]) cv = np.mean(points_2d[:, 1]) # 步骤2:计算点到质心的均方根距离 dx = points_2d[:, 0] - cu dy = points_2d[:, 1] - cv rms_dist = np.sqrt(np.mean(dx**2 + dy**2)) # 步骤3:计算缩放因子 s = np.sqrt(2) / rms_dist # 步骤4:构建变换矩阵 T = np.array([ [s, 0, -s * cu], [0, s, -s * cv], [0, 0, 1] ]) # 对所有点应用变换 normalized_points = (T @ points_2d.T).T return normalized_points, T
示例用法
用一组测试点来验证效果:
# 6个示例图像点(齐次坐标) sample_points = np.array([ [10, 20, 1], [30, 40, 1], [50, 60, 1], [70, 80, 1], [90, 100, 1], [110, 120, 1] ]) normalized, T = normalize_image_points(sample_points) print("归一化后的点:\n", normalized) print("\n归一化变换矩阵T:\n", T)
归一化后验证要点:
- 归一化后的u和v坐标的平均值应该接近0(由于浮点精度,可能是1e-16级别的极小值)
- 计算归一化点到原点的均方根距离,应该非常接近√2(约1.4142)
DLT后续注意事项
记住,当你用归一化后的点计算出单应矩阵H_normalized后,需要还原归一化操作:最终的单应矩阵H是np.linalg.inv(T) @ H_normalized(如果只对图像点做了归一化的话),所以一定要保存好变换矩阵T。
内容的提问来源于stack exchange,提问作者Vanias

