Передать параметры double, но получить Jet<double, 6>при использовании ceres solver

Я новый ученик в Ceres Solver, когда добавляю остаточный блок, используя

problem.AddResidualBlock( new ceres::AutoDiffCostFunction<Opt, 1, 6> (new Opt(Pts[i][j].x, Pts[i][j].y, Pts[i][j].z, Ns[i].at<double>(0, 0), Ns[i].at<double>(1, 0), Ns[i].at<double>(2, 0), Ds[i], weights[i]) ),
                      NULL,
                              param );

где param двойной [6];

struct Opt
{
const double ptX, ptY, ptZ, nsX, nsY, nsZ, ds, w;

Opt( double ptx, double pty, double ptz, double nsx, double nsy, double nsz, double ds1, double w1):
         ptX(ptx), ptY(pty), ptZ(ptz), nsX(nsx), nsY(nsy), nsZ(nsz), ds(ds1), w(w1) {}

template<typename T>
bool operator()(const T* const x, T* residual) const
{
    Mat R(3, 3, CV_64F), r(1, 3, CV_64F);
    Mat inverse(3,3, CV_64F);
    T newP[3];
    T xyz[3];
        for (int i = 0; i < 3; i++){
            r.at<T>(i) = T(x[i]);
            cout<<x[i]<<endl;
            }
    Rodrigues(r, R);
    inverse = R.inv();
    newP[0]=T(ptX)-x[3];
    newP[1]=T(ptY)-x[4];
    newP[2]=T(ptZ)-x[5];
    xyz[0]= inverse.at<T>(0, 0)*newP[0] + inverse.at<T>(0, 1)*newP[1] + inverse.at<T>(0, 2)*newP[2];
    xyz[1] = inverse.at<T>(1, 0)*newP[0] + inverse.at<T>(1, 1)*newP[1] + inverse.at<T>(1, 2)*newP[2];
    xyz[2] = inverse.at<T>(2, 0)*newP[0] + inverse.at<T>(2, 1)*newP[1] + inverse.at<T>(2, 2)*newP[2];
    T ds1 = T(nsX) * xyz[0] + T(nsY) * xyz[1] + T(nsZ) * xyz[2];
    residual[0] = (ds1 - T(ds)) * T(w);
}
};

но когда я вывел x[0], я получил это:

[-1.40926 ; 1, 0, 0, 0, 0, 0]

после того, как я изменил тип х, чтобы удвоить

Я получил эту ошибку:

note:   no known conversion for argument 1 from ‘const ceres::Jet<double, 6>* const’ to ‘const double*’

в

bool operator()(const double* const x, double* residual) const

что не так с моими кодами? Большое спасибо!

2 ответа

Решение

Я предполагаю, что вы используете cv::Mat.

Причина того, что функтор является шаблонным, заключается в том, что Ceres оценивает его, используя удвоения, когда ему нужны только остатки, и вычисляет с помощью объектов ceres:Jet, когда ему нужно вычислить якобиан. Так что ваша попытка заполнить г как

for (int i = 0; i < 3; i++){
    r.at<T>(i) = T(x[i]);
    cout<<x[i]<<endl;
}

пытаемся превратить джет в дабл. На что правильно жалуется компилятор.

Вы можете переписать свой код как (я не скомпилировал его, так что может быть несколько опечаток).

template<typename T>
bool operator()(const T* const x, T* residual) const {
    const T inverse_rotation[3] = {-x[0], -x[1], -x[3]};
    const T newP[3] = {ptX - x[3], ptY - x[4]. ptZ - x[5]};
    T xyz[3];
    ceres::AngleAxisRotatePoint(inverse_rotation, newP, xyz);
    const T ds1 = nsX * xyz[0] + nsY * xyz[1] + nsZ * xyz[2];
    residual[0] = (ds1 - ds) * w;
    return true;
}

Автоматические производные (AutoDiff) нуждаются в шаблонной функции стоимости для отслеживания операций.

Пожалуйста, ознакомьтесь с документацией ceres ( http://ceres-solver.org/nnls_modeling.html). Есть много хороших примеров. Я использовал их в качестве отправной точки для моих первых экспериментов.

Я не уверен, что вы можете использовать функции ceres cost с функциями OpenCV. В большинстве случаев Eigen используется, чтобы сделать функцию стоимости. Ceres поставляется с множеством "готовых к использованию" компонентов для таких функций, как ваша.

Другие вопросы по тегам