我已经努力了几天,以找出如何将代码从MatLab或Python移植到C ++ ...
我的问题是移植非线性最小二乘优化函数,由于到目前为止一切工作正常,我基本上遇到了障碍。
MathLab实现:https://github.com/SuwoongHeo/Deformation-Transfer-Matlab
Python实现:https://github.com/ziyeshanwai/python-deformation-transfer
我在移植时遇到的确切代码...
MatLab代码为:
[b, res, resi] = lsqnonlin(@(b) resSimXform( b,double(A),double(B) ),(double(b0)),[],[],options);
function result = resSimXform( b,A,B )
r = b(1:4);
t = b(5:7);
s = b(8);
% s = b(8:10);
n = size(A,2);
if ~isreal(r)
a = 1;
end
R = vrrotvec2mat(r);
test =repmat(t', 1, n);
rot_A = diag(s) * R * A + repmat(t', 1, n);
result = sum(sum((B-rot_A).^2,2));
end
和等效的python代码是:
b = least_squares(fun=resSimXform, x0=b0, jac='3-point', method='lm', args=(Points_A, Points_B),
ftol=1e-12, xtol=1e-12, gtol=1e-12, max_nfev=100000)
def resSimXform(b, A, B):
print("resSimXform function")
t = b[4:7]
R = np.zeros((3, 3))
R = R_axis_angle(R, b[0:3], b[3])
rot_A = b[7]*R.dot(A) + t[:, np.newaxis]
result = np.sqrt(np.sum((B-rot_A)**2, axis=0))
return result
我很幸运地尝试了C ++中的各种优化库...它们的工作方式显然不同于Python或Matlab中的库。
[我已经尝试了Eigen的LevenbergMarquardt
和DLibs solve_least_squares_lm
,但是失败了...我不知道如何设置它们,因为它们显然与它们的对应物不同。
我已经在C ++中实现了“相似性残差”功能(resSimXform
),并且工作正常。我一直在不断调试结果,并对照MathLab和Python的输出进行检查。
我的C ++版本看起来像:((当我弄清楚如何用最小二乘函数使用它时,我会尝试对其进行更多清理……但是目前它返回的值与Matlab相同)]
double residual(MatrixXd x, MatrixXd A, MatrixXd B) {
MatrixXd r(1, 4);
r(0, 0) = x(0, 0);
r(0, 1) = x(0, 1);
r(0, 2) = x(0, 2);
r(0, 3) = x(0, 3);
MatrixXd t(1, 3);
t(0, 0) = x(0, 4);
t(0, 1) = x(0, 5);
t(0, 2) = x(0, 6);
double s = x(0, 7);
MatrixXd R(3, 3);
R = R_axis_angle(r);
MatrixXd rot_A(A.rows(), A.cols());
t.transposeInPlace();
t = t.col(0).replicate(1, A.cols());
rot_A = s * R * A + t;
MatrixXd fvecM = B - rot_A;
for (int i = 0; i < fvecM.rows(); i++) {
for (int j = 0; j < fvecM.cols(); j++) {
fvecM(i, j) = pow(fvecM(i, j), 2);
}
}
Eigen::VectorXd sums(3);
sums(0) = fvecM.row(0).sum();
sums(1) = fvecM.row(1).sum();
sums(2) = fvecM.row(2).sum();
return fvecM.sum();
}
如果有任何人可以帮助我弄清楚哪种c ++优化库在这种情况下可以工作,以及如何实现它,...如果我自从使用Matlab或Python以来,与Matlab或Python有很大的不同,我将不胜感激。这种优化器是有限的。
提前感谢...我已经尝试谷歌搜索了几天,却找不到解决方案,所以这就是为什么我在这里:)
使用Eigen不支持的LevenbergMarquardt来解决。您建立一个仿函数... my_functor(void):仿函数(8,8){} ..如果要求解8个值...则必须为8x8 ...