プログラミング」カテゴリーアーカイブ

Ceresの自動微分のみを使う

g2oのドキュメントを眺めていると,Ceresの一部を自動微分用に抜き出しているっぽいのが気になっていたので,実際に自動微分のモジュールだけ使用できるのか試してみました.

#include <iostream>
#include <ceres/autodiff.h>

struct F {
  template<typename T>
  // z0 = x0^2 + x2
  // z1 = x0 * x1 + x1^2 + x2^3
  bool operator()(const T* x, T* z) const {
    z[0] = x[0] * x[0] + x[2];
    z[1] = x[0] * x[1] + x[1] * x[1] + x[2] * x[2] * x[2];
    return true;
  }
};

int main(int argc, char** argv) {
  float* x = new float[3]{ 1.0f, 3.0f, 5.0f };  // parameters
  float* z = new float[2];                      // outputs
  float* J = new float[6];                      // jacobians

  F func;

  // autodiff
  const int num_parameters = 3;
  const int num_outputs = 2;

  ceres::internal::AutoDiff<F, float, num_parameters> ad;
  ad.Differentiate(func, &x, num_outputs, z, &J);

  // outputs
  std::cout << "--- outputs ---" << std::endl;
  for (int i = 0; i < 2; i++) {
    std::cout << z[i] << " ";
  }
  std::cout << std::endl;

  // jacobians
  std::cout << "--- J ---" << std::endl;
  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 3; j++) {
      std::cout << J[i * 3 + j] << " ";
    }
    std::cout << std::endl;
  }

  return 0;
}
--- outputs ---
6 137
--- J ---
2 0 1
3 7 75

ceresはg2oのEXTERNALに入っているものを使いました.
https://github.com/RainerKuemmerle/g2o/tree/master/EXTERNAL/ceres

思いのほか簡単に使えましたね.
ヘッダーオンリーで使えるので何かと便利そうです.
例えばEFKの微分をAutoDiffにするっていうのがceres全体を依存に入れなくてもできそうです.

[:ja]DSOでAR ~ 3. visual odometryを使ったAR[:]

[:ja]カメラ姿勢が得られれば単純なARを表示するのは非常に簡単です.基本的には表示したい3次元物体を,推定されたカメラ姿勢を基にカメラ座標系へ変換し,カメラ内部パラメータを使って画像上へ投影するだけです.

ただ,一つ問題になるのはスケールの推定です.原理的に単眼のvisual SLAM/odometryにおいては画像情報だけから環境のスケールを推定することができません.例えば,大きな箱を遠くから見ているのと,小さな箱を近く見ている場合には同じような絵が得られてしまうため大きさの区別がつきません.そのため,ARにおいて物体の大きさを指定して特定の場所に置くというのは少し難しい話になります(大きさ10cmの立方体をカメラから100cm前に置く!みたいなことを正確に行うのは難しい).今回はカメラの動きに非常に単純なアドホックな過程を置いてスケールの推定を行ってみます.

続きを読む