OpenCV::LMSolver 得到一个简单的例子 运行
OpenCV::LMSolver getting a simple example to run
问题:至少可以说,opencv.org 上 cv::LMSolver
的文档非常薄。在互联网上找到一些有用的示例也是不可能的。
APPROACH: 所以,我确实写了一些简单的代码:
#include <opencv2/calib3d.hpp>
#include <iostream>
using namespace cv;
using namespace std;
struct Easy : public LMSolver::Callback {
Easy() = default;
virtual bool compute(InputArray f_param, OutputArray f_error, OutputArray f_jacobian) const override
{
Mat param = f_param.getMat();
if( f_error.empty() ) f_error.create(1, 1, CV_64F); // dim(error) = 1
Mat error = f_error.getMat();
vector<double> x{param.at<double>(0,0), param.at<double>(1,0)}; // dim(param) = 2
double error0 = calc(x);
error.at<double>(0,0) = error0;
if( ! f_jacobian.needed() ) return true;
else if( f_jacobian.empty() ) f_jacobian.create(1, 2, CV_64F);
Mat jacobian = f_jacobian.getMat();
double e = 1e-10; // estimate derivatives in epsilon environment
jacobian.at<double>(0, 0) = (calc({x[0] + e, x[1] }) - error0) / e; // d/dx0 (error)
jacobian.at<double>(0, 1) = (calc({x[0], x[1] + e}) - error0) / e; // d/dx1 (error)
return true;
}
double calc(const vector<double> x) const { return x[0]*x[0] + x[1]*x[1]; }
};
int main(int argc, char** argv)
{
Ptr<Easy> callback = makePtr<Easy>();
Ptr<LMSolver> solver = LMSolver::create(callback, 100000, 1e-37);
Mat parameters = (Mat_<double>(2,1) << 5, 100);
solver->run(parameters);
cout << parameters << endl;
}
问题:
LMSolver::Callback::compute()
的 return 值向调用者报告什么?
- 目前,它在 (-9e-07,4e-5) 找到最小值,而不是预期的 (0.0, 0.0)。如何提高精度?
What does the return value of LMSolver::Callback::compute() report to the caller?
值得庆幸的是,opencv 是开源的,所以我们也许可以通过查看代码来解决这个问题。
查看源代码 on Github,我发现对 compute()
的所有调用看起来像:
if( !cb->compute(x, r, J) )
return -1;
返回 false
只会导致求解器退出。所以回调的 compute()
的 return 值似乎只是 jacobian 的生成是否成功。
Currently, it finds the minimum at (-9e-07,4e-5). How can the precision be improved?
如果有的话,您至少应该将 run()
的 return 值与您的最大迭代次数进行比较,以确保它确实尽可能地收敛。
问题:至少可以说,opencv.org 上 cv::LMSolver
的文档非常薄。在互联网上找到一些有用的示例也是不可能的。
APPROACH: 所以,我确实写了一些简单的代码:
#include <opencv2/calib3d.hpp>
#include <iostream>
using namespace cv;
using namespace std;
struct Easy : public LMSolver::Callback {
Easy() = default;
virtual bool compute(InputArray f_param, OutputArray f_error, OutputArray f_jacobian) const override
{
Mat param = f_param.getMat();
if( f_error.empty() ) f_error.create(1, 1, CV_64F); // dim(error) = 1
Mat error = f_error.getMat();
vector<double> x{param.at<double>(0,0), param.at<double>(1,0)}; // dim(param) = 2
double error0 = calc(x);
error.at<double>(0,0) = error0;
if( ! f_jacobian.needed() ) return true;
else if( f_jacobian.empty() ) f_jacobian.create(1, 2, CV_64F);
Mat jacobian = f_jacobian.getMat();
double e = 1e-10; // estimate derivatives in epsilon environment
jacobian.at<double>(0, 0) = (calc({x[0] + e, x[1] }) - error0) / e; // d/dx0 (error)
jacobian.at<double>(0, 1) = (calc({x[0], x[1] + e}) - error0) / e; // d/dx1 (error)
return true;
}
double calc(const vector<double> x) const { return x[0]*x[0] + x[1]*x[1]; }
};
int main(int argc, char** argv)
{
Ptr<Easy> callback = makePtr<Easy>();
Ptr<LMSolver> solver = LMSolver::create(callback, 100000, 1e-37);
Mat parameters = (Mat_<double>(2,1) << 5, 100);
solver->run(parameters);
cout << parameters << endl;
}
问题:
LMSolver::Callback::compute()
的 return 值向调用者报告什么?- 目前,它在 (-9e-07,4e-5) 找到最小值,而不是预期的 (0.0, 0.0)。如何提高精度?
What does the return value of LMSolver::Callback::compute() report to the caller?
值得庆幸的是,opencv 是开源的,所以我们也许可以通过查看代码来解决这个问题。
查看源代码 on Github,我发现对 compute()
的所有调用看起来像:
if( !cb->compute(x, r, J) )
return -1;
返回 false
只会导致求解器退出。所以回调的 compute()
的 return 值似乎只是 jacobian 的生成是否成功。
Currently, it finds the minimum at (-9e-07,4e-5). How can the precision be improved?
如果有的话,您至少应该将 run()
的 return 值与您的最大迭代次数进行比较,以确保它确实尽可能地收敛。