opencv3使用ceres进行非线性方程求解

评价:
0
(0用户)

引言

在图像处理开发中常遇到复杂方程计算或者数据拟合的情形,在C++中需要使用数学软件库进行计算。图像处理开发常用软件库多数为opencv,虽然在其中包含大量图像处理方法,但大多方法都进行了封装,只提供图像处理接口供使用。Ceres Solver作为谷歌开发的数学求解器,拥有强大的非线性求解功能(非线性最小二乘问题)。

使用opencv构造仿函数

Ceres进行求解前需构造仿函数,将待求解方程使用程序编写出来。对于使用opencv中Mat_<T>类型进行计算时,在迭代过程中会出现错误:错误C2678 二进制“*”: 没有找到接受“const JetT”类型的左操作数的运算符,这是因为在Ceres的计算过程中会自动对仿函数中的未知数求导,以便快速收敛,在求导计算中需要使用JetT数据类型,然而opencv中Mat无法使用JetT类型进行“*”乘法运算,同理“+”“-”“÷”也都无法进行,因此会出现编译错误。

使用Eigen构造仿函数

Ceres针对另外一个数学运算库Eigen做出适配。
使用eigen中Matrix类型的仿函数构造如下:

struct costFunctor{
    costFunctor(Matrix3d _A, Vector3d _b, Vector3d _c, Vector3d _x):A(_A), b(_b), c(_c), x(_x){ }
    template <typename T> bool operator()(const T* const abc, T* residual) const {
        //进行模板类型定义
        typedef Matrix<T, Eigen::Dynamic, Eigen::Dynamic> MatrixXT;
        typedef Matrix<T, 3, 3> Matrix3T;
        typedef Matrix<T, 3, 1> Vector3T;
        //进行数据类型转换,适配后续的JetT类型
        Matrix3T _A_ = A.cast<T>();
        Vector3T _b_((T)b(0), (T)b(1), (T)b(2));
        Vector3T _c_((T)c(0), (T)c(1), (T)c(2));
        Vector3T _x_((T)x(0), (T)x(1), (T)x(2));

        Vector3T m = b + abc[0] * c;
        residual[0] = (A * m).dot(x);
    }
private:
    Matrix3d A;    //3×3维矩阵
    Vector3d b, c, x; //3维列向量
}

opencv数据类型与Eigen数据类型的转换

此时需要将opencv的Mat类型转换为Eigen中的Matrix类型,就可以正常进行编译运行。

//opencv Mat转eigen Matrix
#include "ceres/ceres.h"
#include "opencv2/core/eigen.hpp" //这两个头文件顺序不能颠倒
cv::cv2eigen(opencvMat, eigenMat);

 

本文为原创文章,转载请注明出处!

注册并通过认证的用户才可以进行评价!

admin:支持一下,感谢分享!,+10,  

发表评论