You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现DLT算法前2D图像点归一化咨询(RMS距离为√2)

实现DLT前的2D图像点归一化(Python版)

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:

  1. Translate all points so their centroid (average position) lands at (0,0).
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:09:01