2013年12月10日火曜日

Ceres Solverの使用例(放物線の最小二乗法)

Ceres SolverはGoogleが開発した非線形最適化のためのC++ライブラリ。 使い方は本家サイトにもチュートリアルがあるし、サンプルコードもある。 でも、どれも単純すぎたり、難しすぎたり中途半端なので、 データが復数ある最小二乗法のサンプルコードを載せる。

\[ y=a x^2 \]

この関数をフィッティングする場合、データとして$(x_i, y_i)\ (i=0,1,\cdots,n-1)$が与えれるので、 求めるパラメータは、$a$のみ。ここのデータの誤差を \[ e_i = y_i - a*x_i^2 \] とすると、単純な最小二乗法では、 \[ E=\sum_i e_i^2 \] が最小化される。 ここでは、データ$(x_i, y_i)$として次のファイル「data.txt」が与えられるとする。

0 0
1 1.2
2 3.9
-1 0.9
-2 4.1

サンプルコード

まず、ヘッダー部分は単純にceresのヘッダをインクルードすれば良い。 namespaceはライブラリのexamplesを真似して追加した。 OpenCVのヘッダはデータ入力に使うだけなので本来必要ない。

#include "ceres/ceres.h"
#include "opencv2/opencv.hpp"
 
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::Problem;
using ceres::Solver;
using ceres::Solve;

次に、誤差関数の定義部分。 ErrorFunctionクラスのメンバ関数として定義する必要がある。 operator()関数をテンプレート関数として ここに書くのは$e_i$の部分だけ。 パラメータ$a$も残差$e_i$も配列で定義するみたい。 汎用性を考えてType型という抽象型になっているだけで今回はdoubleと思えば良い。

class ErrorFunction{
private:
    //1組のデータ
    const double x;
    const double y;
 
public:
    //データを1つずつ入力する際このコンストラクタが呼ばれる。
    ErrorFunction(double x, double y) : x(x), y(y) {}
 
    //e_iの定義。
    template <typename Type> bool operator()(const Type* const a, Type* residual) const {

        //e_i = y_i - a*x_i*x_i
        residual[0] = Type(y)  - a[0]*Type(x)*Type(x);
        return true;
    }
};

誤差関数が定義できれば、あとはデータを与えて最適化するだけ。 データの入力は面倒なので 「cv::Mat_をテキストファイルに保存・読み込み 」 で紹介した方法を使う。

void main(int argc, char *argv[]){

    //最適化するパラメータ。初期値を入力しておく。
    double a = 0.0;
 
    //データの入力
    cv::Mat_<double> data;
    readTxt("data.txt", data);
 
    //データの入力
    Problem problem;
    for (int i = 0; i < data.rows; ++i) {

        //x_i,y_iを1つずつ入力する
        problem.AddResidualBlock(
            new AutoDiffCostFunction<ErrorFunction, 1, 1>
            (
                //ここでデータを入れている
                new ErrorFunction(data(i, 0), data(i, 1))
            ),
            NULL,    //Loss function
            &a
        );
        //std::cout << data(i, 0) << ' ' << data(i, 1) << std::endl;
    }
 
    //ソルバの準備
    Solver::Options options;

    //CXSparseをインストールしていないときはDENSE_*にしないとエラーになる。
    options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY;   
 
    //最適化
    Solver::Summary summary;
    Solve(options, &problem, &summary);
 
    std::cout << "Fit complete:   a: " << a << "\n";
    return;
}

参考

Comparison of head-free gaze trackers

This page summerizes head-free gaze tracking hardwares.

SteelSeries Sentry Gaming Eye Tracker

https://steelseries.com/gaming-controllers/sentry-gaming-eye-tracker

  • Price:~$250
  • Acquisition rate:30 or 60 Hz
  • Angular resolution:0.5 - 1 deg (RMS)
  • Latency: < 20ms (at 60Hz)
  • FOV: 40cm x 30cm(at 30Hz, depth 65cm)
  • Depth range: 45cm – 75cm
  • Size: 20 x 1.9 x 1.9 cm
  • Weight: 70g

EyeTribe

https://theeyetribe.com/

  • Price:~$100
  • Acquisition rate:30 or 60 Hz
  • Angular resolution:0.5 - 1 deg (RMS)
  • Latency: < 20ms (at 60Hz)
  • FOV: 40cm x 30cm(at 30Hz, depth 65cm)
  • Depth range: 45cm – 75cm
  • Size: 20 x 1.9 x 1.9 cm
  • Weight: 70g

Gazepoint GP3 Desktop Eye Tracker

http://gazept.com/

  • Price: ~$500
  • Rate: 60Hz
  • Angular resolution:0.5-1 deg (RMS)
  • Latency: 50 – 70ms
  • FOV:25cm x 11cm (at 65cm)
  • Depth range: ±15 cm
  • Size: 20 x 1.9 x 1.9 cm (W x H x D)
  • Weight: 70g

S2 Eye Tracker

http://mirametrix.com/products/eye-tracker/

  • Price: ~$500k
  • Rate: 60 Hz
  • Angular resolution: 0.5 deg (RMS)
  • Latency: ? (0.3 deg)
  • FOV: 25 x 11 cm
  • Depth range:30 cm
  • Size: 35 x 4 x 3 cm (W x H x D)
  • Weight: 300 kg

Tobii X2-30 Eye Tracker Compact Edition

http://www.tobii.com/de/eye-tracking-research/global/products/hardware/tobii-x2-30-eye-tracker/

  • Price: ~$1M
  • Rate: 30 Hz
  • Angular resolution: 0.4 - 0.5 deg (RMS)
  • Latency: 50 - 70ms
  • FOV: 50 x 36 (at 70 cm)
  • Depth range: 40 - 90 cm
  • Size: 18.4 x 2.8 x 2.3 cm
  • Weight: 200g

Tobii X2-60 Eye Tracker Compact Edition

http://www.tobii.com/zh-CN/eye-tracking-research/global/products/hardware/tobii-x2-60-eye-tracker/

  • Price: ~$1M
  • Rate: 60 Hz
  • Angular resolution: 0.4 - 0.5 deg (RMS)
  • Latency: 35 ms
  • FOV: 50 x 36 (at 70 cm)
  • Depth range: 40 - 90 cm
  • Size: 18.4 x 2.8 x 2.3 cm
  • Weight: 200g

2013年12月7日土曜日

Ceres Solverのコンパイル方法 on Windows

Ceres Solverとは?

Ceres SolverはGoogleが開発した非線形最適化のためのC++ライブラリ。 何ができるのかというと、定義した誤差関数を最小化するパラメータを求めることができる。 非線形最適化のための定番アルゴリズムLevenberg–Marquardt法(LM法)などは実装済みで利用者は殆ど意識すること無く使用することができる。 何よりも、Automatic Differentiationという機能がすごい。 誤差関数の微分を数値的にではなくて、解析的に(数式的に)自動的に解いてLM法に組み込んでくれる。 つまり誤差関数そのものを実装するだけで良い。

誤差関数の微分の計算がなくなっただけでそんなに楽になるのだろうか? 例えば、ある誤差関数$f(x,y)$を作成し、これを最小化したいとする。 効率よく計算するためには、この関数の解析的な偏導関数$\frac{\partial f(x,y)}{\partial x}$と$\frac{\partial f(x,y)}{\partial y}$が必要になる。 この場合変数は$x$と$y$の2つだけど、変数が増えると必要な偏導関数の数が増える。 画像自体を推定する場合は、全ての画素の輝度がパラメータになる。 for文などで自動化出来ても$\sin$、$\cos$関数などが含まれている場合は、個々の偏導関数自体が非常に複雜になる場合もある。 誤差関数が複雜な場合、手で計算するのには限界がある。 Mathmaticaのような数式処理ソフトを使う方法もあるが、実装もなかなか面倒だった。

こうした実装をC言語でかつ安直な方法でやろうとすると、 読みづらいマクロと関数ポインタ、グローバル変数を使いまくる実装になってしまう。 Ceres SolverはC++の継承と関数オブジェクトを使って非常に美しく、使いやすい形でまとまっている。 現在のところ日本語の解説は、LinuxのみだったのでWindowsでの動作実績をまとめる。

インストール手順

  1. 必要なファイルライブラリをダウンロード、ビルド
    1. eigen-eigen-ffa86ffb5570.zipをダウンロード(3.1以上)する。ビルドの必要はない。
    2. glog-0.3.3.tar.gzをダウンロードする。
    3. 解凍し、oogle-glog.slnを叩いてビルドする。バッチビルドで全てを選んでビルドする。エラーが出るがビルドは成功。
    4. gflags-2.0-no-svn-files.tar.gzをダウンロード。問題無くビルド成功。
    5. 解凍してgflags.slnの読み取り専用設定を解除。
    6. gflags.slnを叩いてビルドする。
  2. ceresのダウンロード、フォルダ作成
    1. ceres-solver-1.8.0.tar.gzをダウンロードする。
    2. ceres\ceres-install、ceres\ceres-buildフォルダを作成する。
  3. cmakeによるVisual Studioのソリューションファイル作成
    1. cmakeを起動する。
    2. 「Where is the source code」にceres/ceres-solver-1.8.0設定する。
    3. 「Where to build the binaries」にC:/library/ceres/ceres-buildを設定する。
    4. 一度configureする。エラーが出て止まる。
    5. GroupedとAdvancedにチェックを入れると全てのオプションが見えるようになる。
    6. CMAKE_INSTALL_PREFIXにceres\ceres-installへの絶対パスを入れる。
    7. EIGEN_INCLUDE_DIRにeigen3.2への絶対パスを入れる。
    8. 再度configureする。エラーが出て止まる。
    9. GLOG_INCLUDE_DIRにglog-0.3.3\src\windowsへの絶対パスを入れる。
    10. GLOG_LIBRARYにglog-0.3.\Release3\libglog.libへの絶対パスを入れる。
    11. GFLAGS_INCLUDE_DIRにgflags-2.0\src\windowsへの絶対パスを入れる。
    12. GFLAGS_LIBRARYにgflags-2.0\Release\libgflags.libへの絶対パスを入れる。
    13. CX_SPARSE_INCLUDE_DIRにCXSparse\Includeの絶対パスを入れる。
    14. CX_SPARSE_LIBにCXSparse\Lib\CXSparse.libの絶対パスを入れる。
    15. 再度configureする。
    16. generateするとceres\ceres-buildにCERES.slnが生成されている。
  4. CERES.slnを叩いてビルドする。バッチビルドでALL_BUILDとINSTALLのチェックを全て付けてビルドする。

テスト環境

  • Visual Studio 2010 sp1
  • Windows 7 Pro

参考