cs231A Homework-2:ps-code2-part-3
三、 The Factorization Method
- 此方法用来解决SFM问题;
一、 算法过程
Tomasi & Kanade algorithm
分为两步:
- Data centering
- Factorization
1. centering step
- 居中数据: 对于一张图片中的每个点,定义新的坐标点,通过减去图片中心点:
并且可知:
上述两个式子可以得到:
居中后的3D点和居中后的图片点通过一个2*3矩阵A相关;
但是,只知道图片中的点,不知道A和X;
2、 建立D矩阵
通过建立一个处理矩阵D,由m个相机的n个观察点组成;
- M:2m*3
- S: 3 * n
- D = M * S
- rank(D) = 3
3. 因素化
通过使用SVD方法将D分解为运动矩阵M和结构矩阵S:
- 因为D的秩为3, 但是由于噪声和仿射变换近似,rank(D) >3, 但是只需要取3仍然是最好的近似;
Tomasi and Kanade 的方法:
最佳因素化选择:
【问题】
- 怎么得到M : 2m * 3? 难道其他元素为0?
- S也是类似?
- 因为M,S两个矩阵最大秩为3,所以两个矩阵的乘积Rank=3;实际中,D的rank大于3,但是rank为3是最佳近似;
- 由于D有秩为3,将分解为(2m 3)(3 3)(3 * n)的三个矩阵;
二、 python实现
1.因素化方法
def factorization_method(points_im1, points_im2):
N = points_im1.shape[0]
points_sets = [points_im1, points_im2] # 2* (N * 3)
# 建立D矩阵
D = np.zeros((4, N))
for i in range(len(points_sets)): # len : 2
points = points_sets[i] # N * 3
# 中心化点
centroid = 1.0 / N * points.sum(axis=0) # 均值 (x,y),
points[:, 0] -= centroid[0] * np.ones(N) # x
points[:, 1] -= centroid[1] * np.ones(N) # y
D[2*i:2*i+2, :] = points[:, 0:2].T # 每一副图片的(x,y)复制到D中
# svd分解D矩阵
u, s, vt = np.linalg.svd(D)
print(u.shape, s.shape, vt.shape)
print(s)
M = u[:, 0:3] # Motion
S = np.diag(s)[0:3, 0:3].dot(vt[0:3, :]) # structure
return S, M
在svd分解后,直接使用u作为M运动矩阵,S = singa*vT,作为结构矩阵;其实可以选择上面最后的最佳选择;
2. 主函数
import numpy as np
from scipy.misc import imread
import matplotlib.pyplot as plt
import scipy.io as sio
import matplotlib.gridspec as gridspec
from epipolar_utils import *
if __name__ == '__main__':
for im_set in ['data/set1', 'data/set1_subset']:
# Read in the data
im1 = imread(im_set+'/image1.jpg')
im2 = imread(im_set+'/image2.jpg')
points_im1 = get_data_from_txt_file(im_set + '/pt_2D_1.txt')
points_im2 = get_data_from_txt_file(im_set + '/pt_2D_2.txt')
points_3d = get_data_from_txt_file(im_set + '/pt_3D.txt')
assert (points_im1.shape == points_im2.shape)
# Run the Factorization Method
structure, motion = factorization_method(points_im1, points_im2)
# Plot the structure
fig = plt.figure()
ax = fig.add_subplot(121, projection = '3d')
scatter_3D_axis_equal(structure[0,:], structure[1,:], structure[2,:], ax)
ax.set_title('Factorization Method')
ax = fig.add_subplot(122, projection = '3d')
scatter_3D_axis_equal(points_3d[:,0], points_3d[:,1], points_3d[:,2], ax)
ax.set_title('Ground Truth')
plt.show()
三、结果
(4, 4) (4,) (37, 37)
[959.5852216 540.47613178 184.43174791 27.9151956 ]
(4, 4) (4,) (18, 18)
[264.54396508 210.06072009 7.21921783 5.12857709]
图对比: