如何加快函数least_square
的速度?我们有六个变量(3个方向角和3个轴平移)需要优化。我们将两组3D点、平面上的两组点和投影矩阵应用于函数的输入
dSeed = np.zeros(6)
optRes = least_squares(minReproj, dSeed, method='lm', max_nfev=600,
args=(points_prev, points_cur, d3d_prev, d3d_cur, Proj1))
此函数将点的前后投影误差降至最低
def minReproj(dof, d2dPoints1, d2dPoints2, d3dPoints1, d3dPoints2, w2cMatrix):
Rmat = genEulerZXZ(dof[0], dof[1], dof[2]) # my function
translationArray = np.array([[dof[3]], [dof[4]], [dof[5]]])
temp = np.hstack((Rmat, translationArray))
perspectiveProj = np.vstack((temp, [0, 0, 0, 1]))
numPoints = d2dPoints1.shape[0]
errorA = np.zeros((numPoints,3))
errorB = np.zeros((numPoints,3))
forwardProj = np.matmul(w2cMatrix, perspectiveProj)
backwardProj = np.matmul(w2cMatrix, np.linalg.inv(perspectiveProj))
for i in range(numPoints):
Ja = np.ones((3))
Jb = np.ones((3))
Wa = np.ones((4))
Wb = np.ones((4))
Ja[0:2] = d2dPoints1[i,:]
Jb[0:2] = d2dPoints2[i,:]
Wa[0:3] = d3dPoints1[i,:]
Wb[0:3] = d3dPoints2[i,:]
JaPred = np.matmul(forwardProj, Wb)
JaPred /= JaPred[-1]
e1 = Ja - JaPred
JbPred = np.matmul(backwardProj, Wa)
JbPred /= JbPred[-1]
e2 = Jb - JbPred
errorA[i,:] = e1
errorB[i,:] = e2
residual = np.vstack((errorA,errorB))
return residual.flatten()
def genEulerZXZ(psi, theta, sigma):
c1 = cos(psi)
s1 = sin(psi)
c2 = cos(theta)
s2 = sin(theta)
c3 = cos(sigma)
s3 = sin(sigma)
mat = np.zeros((3,3))
mat[0,0] = (c1 * c3) - (s1 * c2 * s3)
mat[0,1] = (-c1 * s3) - (s1 * c2 * c3)
mat[0,2] = (s1 * s2)
mat[1,0] = (s1 * c3) + (c1 * c2 * s3)
mat[1,1] = (-s1 * s3) + (c1 * c2 * c3)
mat[1,2] = (-c1 * s2)
mat[2,0] = (s2 * s3)
mat[2,1] = (s2 * c3)
mat[2,2] = c2
return mat
这种优化需要0.2到0.4秒,这太多了。也许你知道如何加快这个过程? 或者也许有另一种方法可以找到两个点集的相对旋转和平移? 对于rpoleski:
96 0.023 0.000 19.406 0.202 /usr/local/lib/python3.7/dist-packages/scipy/optimize/_lsq/least_squares.py:240(least_squares)
4548 0.132 0.000 18.986 0.004 /usr/local/lib/python3.7/dist-packages/scipy/optimize/_lsq/least_squares.py:801(fun_wrapped)
96 0.012 0.000 18.797 0.196 /usr/local/lib/python3.7/dist-packages/scipy/optimize/_lsq/least_squares.py:42(call_minpack)
4548 11.102 0.002 18.789 0.004 /home/pi/helperFunctions.py:29(minimizeReprojection)
最有可能的是,在^{} 期间,大部分时间都花在计算残差上,在您的例子中,残差的形式是
minReproj()
中的代码但是,您在
minReproj()
中提供的代码似乎有一个次优内存管理,通过预分配可以大大改进。这将大大提高速度例如,
vstack()
和hstack()
由于必须将其参数复制到其最终结果的内存中而遭受重大惩罚。考虑^ ^ {CD2}}的前几行,我在^ {CD7}}中重新分组。这些可以重写为gen_affine()
,具有更好的计时(我还重写了gen_euler_zxz()
以不分配新内存):类似地,通过定义更大的残差并为
errorA
和errorB
提供关于它的视图,可以避免residual = np.vstack((errorA,errorB))
调用另一个例子是在创建
Ja
、Jb
、Wa
、Wb
时:另外,
.flatten()
正在制作一个您不需要的副本,而.ravel()
将只返回一个视图,但这已经足够满足您的需要,并且速度更快:最后一点是关于主回路的加速。 我并没有为此设计一个简单的矢量化重写,但您可以使用Numba加快速度(只要它在非对象模式下编译)
为此,还需要JIT修饰
gen_euler_zxz()
,并且需要用np.dot()
替换np.matmul()
调用(因为Numba不支持np.matmul()
)最终,修订后的
minReproj()
将如下所示:在一些玩具数据上进行测试,结果显示速度显著提高,当适当使用Numba时,速度变得非常快:
相关问题 更多 >
编程相关推荐