如何修改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
相关产品推荐
相关产品推荐

