引言
在图像处理开发中常遇到复杂方程计算或者数据拟合的情形,在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);
本文为原创文章,转载请注明出处!