123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #include <utility>
- #include "ceres/ceres.h"
- #include "ceres/cubic_interpolation.h"
- #include "glog/logging.h"
- using Grid = ceres::Grid2D<double>;
- using Interpolator = ceres::BiCubicInterpolator<Grid>;
- struct AutoDiffBiCubicCost {
- EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
- template <typename T>
- bool operator()(const T* s, T* residual) const {
- using Vector2T = Eigen::Matrix<T, 2, 1>;
- Eigen::Map<const Vector2T> shift(s);
- const Vector2T point = point_ + shift;
- T v;
- interpolator_.Evaluate(point.y(), point.x(), &v);
- *residual = v - value_;
- return true;
- }
- AutoDiffBiCubicCost(const Interpolator& interpolator,
- Eigen::Vector2d point,
- double value)
- : point_(std::move(point)), value_(value), interpolator_(interpolator) {}
- static ceres::CostFunction* Create(const Interpolator& interpolator,
- const Eigen::Vector2d& point,
- double value) {
- return new ceres::AutoDiffCostFunction<AutoDiffBiCubicCost, 1, 2>(
- new AutoDiffBiCubicCost(interpolator, point, value));
- }
- const Eigen::Vector2d point_;
- const double value_;
- const Interpolator& interpolator_;
- };
- static double f(const double& x, const double& y) {
- return x * x - y * x + y * y;
- }
- int main(int argc, char** argv) {
- google::InitGoogleLogging(argv[0]);
-
- const int kGridRowsHalf = 9;
- const int kGridColsHalf = 11;
- const int kGridRows = 2 * kGridRowsHalf + 1;
- const int kGridCols = 2 * kGridColsHalf + 1;
- const int kPoints = 4;
- const Eigen::Vector2d shift(1.234, 2.345);
- const std::array<Eigen::Vector2d, kPoints> points = {
- Eigen::Vector2d{-2., -3.},
- Eigen::Vector2d{-2., 3.},
- Eigen::Vector2d{2., 3.},
- Eigen::Vector2d{2., -3.}};
-
-
-
- double data[kGridRows * kGridCols];
- for (int i = 0; i < kGridRows; ++i) {
- for (int j = 0; j < kGridCols; ++j) {
-
- int index = i * kGridCols + j;
- double y = i - kGridRowsHalf;
- double x = j - kGridColsHalf;
- data[index] = f(x, y);
- }
- }
- const Grid grid(data,
- -kGridRowsHalf,
- kGridRowsHalf + 1,
- -kGridColsHalf,
- kGridColsHalf + 1);
- const Interpolator interpolator(grid);
- Eigen::Vector2d shift_estimate(3.1415, 1.337);
- ceres::Problem problem;
- problem.AddParameterBlock(shift_estimate.data(), 2);
- for (const auto& p : points) {
- const Eigen::Vector2d shifted = p + shift;
- const double v = f(shifted.x(), shifted.y());
- problem.AddResidualBlock(AutoDiffBiCubicCost::Create(interpolator, p, v),
- nullptr,
- shift_estimate.data());
- }
- ceres::Solver::Options options;
- options.minimizer_progress_to_stdout = true;
- ceres::Solver::Summary summary;
- ceres::Solve(options, &problem, &summary);
- std::cout << summary.BriefReport() << '\n';
- std::cout << "Bicubic interpolation with automatic derivatives:\n";
- std::cout << "Estimated shift: " << shift_estimate.transpose()
- << ", ground-truth: " << shift.transpose()
- << " (error: " << (shift_estimate - shift).transpose() << ")"
- << std::endl;
- CHECK_LT((shift_estimate - shift).norm(), 1e-9);
- return 0;
- }
|