SciPy的非线性最小二乘

2 投票
2 回答
2678 浏览
提问于 2025-04-16 05:43

我尝试用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

有几点小建议:

  1. 如果可以的话,使用 np.array
  2. 不要使用 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转换成矩阵。

混用矩阵和数组可能会让人很难管理。

撰写回答