我需要将数据拟合到用户选择的曲线作为预定义函数的总和。这个想法是创建类似于peak-o-mat对光谱数据所做的事情。
示例:将一些数据拟合为一个函数,该函数是一个线性函数(两个参数)和一个柯西函数(两个参数)之和。
如果我在编译时知道,我要拟合的曲线是线性和柯西的总和,我可以为此创建一个特定的残差。但问题是我只在运行时知道它。
我想做的是:
1)根据我向用户公开的功能列表定义残差:
struct Residual {
Residual(double x, double y) : m_x(x), m_y(y) {}
protected:
// Observations for a sample.
const double m_x;
const double m_y;
};
struct LorentzianResidual : Residual {
LorentzianResidual(double x, double y) : Residual(x, y) {}
template <typename T>
bool operator()(const T* const m, const T* const c, T* residual) const {
residual[0] = T(m_y) - (1 / M_PI) * (0.5 * c[0]) /
((T(m_x) - m[0]) * (T(m_x) - m[0]) +
(0.5 * c[0]) * (0.5 * c[0]));
return true;
}
};
struct LinearResidual : Residual {
LinearResidual(double x, double y) : Residual(x, y) {}
template <typename T>
bool operator()(const T* const m, const T* const c, T* residual) const {
residual[0] = T(m_y) - (m[0] * T(m_x) + c[0]);
return true;
}
};
2)ceres::Problem
根据用户选择的功能组合解决添加残差块。
我在想两种选择:
a) 创建一个曲线拟合类,其成员具有所有选定的函数和每个函数的参数数组。然后我会在这个类中创建一个 Residual,它有x
和y
作为参数,但是会循环遍历这些函数和参数,返回它们的输出之和。问题是我无法使用以下方法添加残差块:
ceres::CostFunction* cost_function1 =
new ceres::AutoDiffCostFunction<Residual, 1, 1, 1>(
new Residual(xdata[i], ydata[i]));
<Residual, 1, 1, 1>
因为我只会在运行时知道的模板参数(最多有 9 个)。
所以我一直在寻找一个不同的选择,我可以分别添加每个残差。我尝试了一个带有线性和柯西(洛伦兹)残差的简单示例,但它不起作用。
std::vector<double> linear_coeffs{0.0, 0.0};
std::vector<double> lorentz_coeffs{0.0, 0.0};
ceres::Problem problem;
for (size_t i = 0; i < xdata.size(); ++i) {
ceres::CostFunction* cost_function1 =
new ceres::AutoDiffCostFunction<ExponentialResidual, 1, 1, 1>(
new ExponentialResidual(xdata[i], ydata[i]));
problem.AddResidualBlock(cost_function1, nullptr, &linear_coeffs[0],
&linear_coeffs[1]);
ceres::CostFunction* cost_function2 =
new ceres::AutoDiffCostFunction<LinearResidual, 1, 1, 1>(
new LinearResidual(xdata[i], ydata[i]));
problem.AddResidualBlock(cost_function2, nullptr, &lorentz_coeffs[0],
&lorentz_coeffs[1]);
}
Error in evaluating the ResidualBlock.
There are two possible reasons. Either the CostFunction did not evaluate and fill all
residual and jacobians that were requested or there was a non-finite value (nan/infinite)
generated during the or jacobian computation.
Residual Block size: 2 parameter blocks x 1 residuals
我检查了文档,但我没有找到任何关于结合不同功能的曲线拟合的内容。
有谁知道如何使它工作?