SciPy的非线性最小二乘
我尝试用Python进行束调整(bundle adjustment)。所以我在测试非线性最小二乘模块。然后我写了下面的代码。我想得到正确的Pmat,它代表三个相机的投影矩阵。但我遇到了一个错误,“ValueError: object too deep for desired array”(值错误:对象太深,无法放入所需的数组)。
有没有人能给我一些提示来解决这个问题?
问候,
Jinho Yoo。
from math import* from numpy import *
import pylab as p from scipy.optimize
import leastsq
Projected_x = \ mat([[ -69.69 , 255.3825, 1. ],
[ -69.69 , 224.6175, 1. ],
[-110.71 , 224.6175, 1. ],
[-110.71 , 255.3825, 1. ],
[ 709.69 , 224.6175, 1. ],
[ 709.69 , 255.3825, 1. ],
[ 750.71 , 255.3825, 1. ],
[ 750.71 , 224.6175, 1. ]])
Projected_x = Projected_x.transpose()
Pmat = \ mat( [[ 5.79746167e+02, 0.00000000e+00, 3.20000000e+02, 0.00000000e+00],
[ 0.00000000e+00, 4.34809625e+02, 2.40000000e+02, 0.00000000e+00],
[ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00] ] )
reconst_X = \ mat([[-0.95238194, -0.58146697, 0.61506506, 0.00539229],
[-0.99566105, -0.76178453, 0.72451719, 0.00502341],
[-1.15401215, -0.81736486, 0.79417098, 0.00546999],
[-1.11073304, -0.6370473 , 0.68471885, 0.00583888],
[ 2.71283058, 2.34190758, -1.80448545, -0.00612243],
[ 2.7561097 , 2.52222514, -1.91393758, -0.00575354],
[ 2.9144608 , 2.57780547, -1.98359137, -0.00620013],
[ 2.87118168, 2.39748791, -1.87413925, -0.00656901]])
def residuals(p, y, x):
err = y - p*x.transpose()
err = err * err.transpose()
return err
p0 = Pmat
plsq = leastsq(residuals, p0, args=(Projected_x, reconst_X ) )
print plsq[0]
2 个回答
1
有几点小建议:
- 如果可以的话,使用 np.array
- 不要使用 import *
我把代码改成了使用 np.array,来说明 user333700 的意思。同时,我把投影矩阵转换成了一个12维的向量,因为大多数优化器都希望你优化的变量是以向量的形式出现。
你运行下面修改后的代码时会遇到一个错误,错误信息是 TypeError: Improper input parameters。我认为这是因为你试图通过线性最小二乘法来找到12个参数,但你只有8个约束条件。
import numpy as np
import pylab as p
from scipy.optimize import leastsq
Projected_x = np.array([[ -69.69 , 255.3825, 1. ],
[ -69.69 , 224.6175, 1. ],
[-110.71 , 224.6175, 1. ],
[-110.71 , 255.3825, 1. ],
[ 709.69 , 224.6175, 1. ],
[ 709.69 , 255.3825, 1. ],
[ 750.71 , 255.3825, 1. ],
[ 750.71 , 224.6175, 1. ]])
Projected_x = Projected_x.transpose()
Pmat = np.array( [ 5.79746167e+02, 0.00000000e+00, 3.20000000e+02, 0.00000000e+00,
0.00000000e+00, 4.34809625e+02, 2.40000000e+02, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00] )
reconst_X = np.array([[-0.95238194, -0.58146697, 0.61506506, 0.00539229],
[-0.99566105, -0.76178453, 0.72451719, 0.00502341],
[-1.15401215, -0.81736486, 0.79417098, 0.00546999],
[-1.11073304, -0.6370473 , 0.68471885, 0.00583888],
[ 2.71283058, 2.34190758, -1.80448545, -0.00612243],
[ 2.7561097 , 2.52222514, -1.91393758, -0.00575354],
[ 2.9144608 , 2.57780547, -1.98359137, -0.00620013],
[ 2.87118168, 2.39748791, -1.87413925, -0.00656901]])
def residuals(p, y, x):
err = y - np.dot(p.reshape(3,4),x.T)
print p
return np.sum(err**2, axis=0)
p0 = Pmat
plsq = leastsq(residuals, p0, args=(Projected_x, reconst_X ) )
print plsq[0]
3
我猜测:leastsq这个函数不太喜欢矩阵,
你可以使用数组和np.dot,或者在返回之前把np.asarray(err)转换一下。也可以在你的残差函数里面把p转换成矩阵。
混用矩阵和数组可能会让人很难管理。