使用 ceres 求解器时传递 double 参数但得到 Jet<double,6>
pass parameters of double but get Jet<double,6>when using ceres solver
我是 Ceres 求解器的新手,在使用
添加残差块时
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 );
其中参数是 double[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]
在我将 x 的类型更改为 double 之后
我遇到了这个错误:
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
我的代码有什么问题?
非常感谢!
自动导数 (AutoDiff) 需要一个模板化成本函数来跟踪操作。
请查看 ceres 文档 (http://ceres-solver.org/nnls_modeling.html#autodiffcostfunction)。还有很多很好的例子。我用它们作为我的第一个谷神星实验的起点。
我不确定您是否可以将 ceres 成本函数与 OpenCV 函数一起使用。在大多数情况下,Eigen 用于制作成本函数。
Ceres 带有很多 "ready-to-use" 组件,用于像您这样的成本函数。
我猜你正在使用 cv::Mat。
函子被模板化的原因是因为 Ceres 在只需要残差时使用双精度计算它,而在需要计算雅可比行列式时使用 ceres:Jet 对象计算。因此,您尝试将 r 填充为
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;
}
我是 Ceres 求解器的新手,在使用
添加残差块时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 );
其中参数是 double[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]
在我将 x 的类型更改为 double 之后
我遇到了这个错误:
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
我的代码有什么问题? 非常感谢!
自动导数 (AutoDiff) 需要一个模板化成本函数来跟踪操作。
请查看 ceres 文档 (http://ceres-solver.org/nnls_modeling.html#autodiffcostfunction)。还有很多很好的例子。我用它们作为我的第一个谷神星实验的起点。
我不确定您是否可以将 ceres 成本函数与 OpenCV 函数一起使用。在大多数情况下,Eigen 用于制作成本函数。 Ceres 带有很多 "ready-to-use" 组件,用于像您这样的成本函数。
我猜你正在使用 cv::Mat。
函子被模板化的原因是因为 Ceres 在只需要残差时使用双精度计算它,而在需要计算雅可比行列式时使用 ceres:Jet 对象计算。因此,您尝试将 r 填充为
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;
}