lsqnonlin(Matlab)或C ++中的SciPy最小二乘等效项

问题描述 投票:0回答:1

我已经努力了几天,以找出如何将代码从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有很大的不同,我将不胜感激。这种优化器是有限的。

提前感谢...我已经尝试谷歌搜索了几天,却找不到解决方案,所以这就是为什么我在这里:)

c++ matlab eigen dlib
1个回答
0
投票

使用Eigen不支持的LevenbergMarquardt来解决。您建立一个仿函数... my_functor(void):仿函数(8,8){} ..如果要求解8个值...则必须为8x8 ...

© www.soinside.com 2019 - 2024. All rights reserved.