Search code examples
c++opencvceres-solver

convert T* array (Jet* or float*) to cv::Mat<CV_32f>


I am using ceres-solver with AutoDiffCostFunction. My cost function takes as parameter 1x3 vector and outputs 1x1 residual. How can I create opencv Mat out of my T* parameter vector? It may be either Jet or float. I tried following code, but get error "cannot conver from Jet to float"

struct ErrorFunc
{
    template <typename T>
    bool operator()(const T * const Kparams, T * residual) const // Kparams - [f, u, v]
    {
        cv::Mat K = cv::Mat::eye(3, 3, CV_32F);
        K.at<float>(0, 0) = float(Kparams[0]); // error
        K.at<float>(0, 2) = float(Kparams[1]); // error
        K.at<float>(1, 1) = float(Kparams[0]); // error
        K.at<float>(1, 2) = float(Kparams[2]); // error

        Mat Hdot = K.inv() * H * K;

        cv::decomposeHomographyMat(Hdot, K, rot, tr, norm); //want to call this opencv function

        residual[0] = calcResidual(norm);
        return true;
    }
    Mat H;
}

There is a way to get Eigen matrix out of T* matrix:

const Eigen::Matrix< T, 3, 3, Eigen::RowMajor> hom = Eigen::Map< const Eigen::Matrix< T, 3, 3, Eigen::RowMajor> >(Matrix)

but I want to call cv::decomposeHomographyMat . How can I do this?


Solution

  • You cannot use an OpenCV method in a ceres::AutoDiffCostFunction in this way. The OpenCV method is not templated with type T as required by ceres to do the automatic differentiation. The float cast cannot be done because the ceres jet of Jacobians is a vector and not a scalar.

    You have two options:

    1) Use numerical differentiation: see http://ceres-solver.org/nnls_tutorial.html#numeric-derivatives

    2) Use a templated library (e.g. Eigen http://eigen.tuxfamily.org/index.php?title=Main_Page) to rewrite the required homography decomposition