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

如何修改3D点基础矩阵计算代码适配2D图像对应点?

适配2D点集的基础矩阵计算代码修改方案

问题背景

需要计算两张图像间的基础矩阵,已获取2D对应点列表:

pts1_list = [
    [224.95256042, 321.64755249],
    [280.72879028, 296.15835571],
    [302.34194946, 364.82437134],
    [434.68283081, 402.86990356],
    [244.64321899, 308.50286865],
    [488.62979126, 216.26953125],
    [214.77470398, 430.75869751],
    [299.20846558, 312.07217407],
    [266.94125366, 119.36679077],
    [384.41549683, 442.05865479],
    [475.28448486, 254.28138733]
]

pts2_list = [
    [253.88285828, 335.00772095],
    [304.884552,   308.89205933],
    [325.33914185, 375.91308594],
    [455.15515137, 411.18075562],
    [271.48794556, 322.07028198],
    [515.11816406, 221.74610901],
    [245.31390381, 441.54830933],
    [321.74771118, 324.31417847],
    [289.86627197, 137.46456909],
    [403.3711853,  451.08905029],
    [496.16610718, 261.36074829]
]

现有一段基于8点法的基础矩阵计算代码,但仅支持3维齐次坐标输入,核心代码如下:

import numpy as np

def compute_fundamental(x1, x2):
  '''Computes the fundamental matrix from corresponding points x1, x2 using
  the 8 point algorithm.'''
  n = x1.shape[1]
  if x2.shape[1] != n:
    raise ValueError('Number of points do not match.')

  # Normalization is done in compute_fundamental_normalized().
  A = np.zeros((n, 9))
  for i in range(n):
    A[i] = [x1[0, i] * x2[0, i],  x1[0, i] * x2[1, i],  x1[0, i] * x2[2, i],
            x1[1, i] * x2[0, i],  x1[1, i] * x2[1, i],  x1[1, i] * x2[2, i],
            x1[2, i] * x2[0, i],  x1[2, i] * x2[1, i],  x1[2, i] * x2[2, i],
           ]

  # Solve A*f = 0 using least squares.
  U, S, V = np.linalg.svd(A)
  F = V[-1].reshape(3, 3)

  # Constrain F to rank 2 by zeroing out last singular value.
  U, S, V = np.linalg.svd(F)
  S[2] = 0
  F = np.dot(U, np.dot(np.diag(S), V))
  return F / F[2, 2] 

需要修改代码以适配2D点集,重点调整A矩阵的计算逻辑。

解决方案

原代码的核心是处理3维齐次坐标(第三维为1),2D点只需补充齐次坐标分量,或直接简化A矩阵的构造:

方式1:将2D点转换为齐次坐标后调用原函数

这是最简单的方式,无需修改原compute_fundamental函数,只需在调用前把2D点转为3维齐次坐标(第三维补1):

import numpy as np

# 转换2D点为齐次坐标
def make_homog(points):
    # 输入为N×2的2D点数组,返回3×N的齐次坐标数组
    points = np.array(points)
    return np.vstack([points.T, np.ones(points.shape[0])])

# 转换用户提供的点集
x1 = make_homog(pts1_list)
x2 = make_homog(pts2_list)

# 直接调用原函数计算基础矩阵
F = compute_fundamental(x1, x2)
print(F)

方式2:修改函数直接处理2D点

如果不想额外转换坐标,可以直接修改compute_fundamental函数,针对2D点构造A矩阵(利用齐次坐标第三维为1的特性简化计算):

import numpy as np

def compute_fundamental_2d(x1, x2):
  '''适配2D点的基础矩阵计算,输入为N×2的点数组'''
  x1 = np.array(x1)
  x2 = np.array(x2)
  n = x1.shape[0]
  if x2.shape[0] != n:
    raise ValueError('Number of points do not match.')

  A = np.zeros((n, 9))
  for i in range(n):
    u1, v1 = x1[i]
    u2, v2 = x2[i]
    # 齐次坐标第三维为1,所以直接展开对应项
    A[i] = [u1*u2, u1*v2, u1,
            v1*u2, v1*v2, v1,
            u2,    v2,    1]

  # 后续逻辑与原函数一致
  U, S, V = np.linalg.svd(A)
  F = V[-1].reshape(3, 3)

  U, S, V = np.linalg.svd(F)
  S[2] = 0
  F = np.dot(U, np.dot(np.diag(S), V))
  return F / F[2, 2]

# 直接传入2D点集计算
F = compute_fundamental_2d(pts1_list, pts2_list)
print(F)

关键说明

  • 两种方式本质等价:方式1是显式补全齐次坐标,方式2是利用齐次坐标特性简化了A矩阵的元素计算。
  • 原代码提到的compute_fundamental_normalized是带归一化的版本,建议实际使用时加上归一化步骤(对坐标进行平移缩放,提升计算稳定性),可以参考原代码结构补充该逻辑。

内容的提问来源于stack exchange,提问作者blazingcannon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 06:05:21