cvLevenbergMarquardtOptimizationで最小化

void cvLevenbergMarquardtOptimization

void cvLevenbergMarquardtOptimization(pointer_LMJac JacobianFunction, pointer_LMFunc function, CvMat *X0, CvMat *observRes, CvMat *resultX, int maxIter, double epsilon);

な,長い・・・

引数

  • JacobianFunction:pointer_LMJac型のヤコビアン行列を返す関数のポインタ
  • function:pointer_LMJac型の計算値を返す関数のポインタ
  • X0:CvMat*型の初期値
  • observRes:CvMat*型の観測値
  • resultX:CvMat*型の結果
  • maxIter:int型の最大反復回数
  • epsilon:double型の収束しきい値

解説

  • pointer_LMJac型とはfunction( const CvMat*src, CvMat* dst)という形の関数
  • 関数を2つ作る
    • srcを引数としてdstに計算値を代入する関数
    • srcを引数としてdstに編微分を羅列した関数行列を返す関数
  • X0には初期値,observResは観測値,あとは反復回数と収束しきい値を指定する
  • 関数について
    • 例えばP行列は未知数11の行列で,計算値は2次元座標
    • PX=x
    • ここでPが未知でXが既知,xが観測できる値
    • 例えば10点の座標からPを推定する場合,srcは11行1列のベクトルになり,dstは10*2(次元)で20行1列のベクトルとなる.
    • 既知の3次元座標はあらかじめ何とか渡しておかなければならない.
  • ヤコビ行列を返す関数は理論的には要らないはず(Levenberg-Marquradt法は本来そういうもの)なのだが,何故か関数を求められる上に,NULLポインタでごまかすこともできない.

返り値

  • voidなので返さない

サンプルコード

  1.  //cvaux/src/cvlevmartif.cppにTriFocalを求める過程でLevenbergMarqurdtが求められている.
  2.  #include <cvlevmar.cpp>
  3.  #include <cv.h>
  4.  #include <cvaux.h>
  5.  #include <cxcore.h>
  6.  #include <highgui.h>
  7.  #include <stdio.h>
  8.  #include <math.h>
  9.  #define A 100
  10.  #define B 102
  11.  #define PRECISION 100
  12.  #define DERIV_STEP 0.00001
  13.  
  14.  void CalcDiff( const CvMat *src, CvMat *dst);
  15.  void CalcDerivDiff( const CvMat *src, CvMat *dst);
  16.  double coreCalculation( const CvMat *src, double x);
  17.  
  18.  int main(){
  19.   CvMat *src, *dst, *X0, *res;
  20.   FILE *fp = fopen("./data", "w");
  21.   fclose(fp);
  22.   X0 = cvCreateMat(2, 1, CV_64F);
  23.   src = cvCreateMat(2, 1, CV_64F);
  24.   dst = cvCreateMat(PRECISION, 1, CV_64F);
  25.   res = cvCreateMat(X0->rows, X0->cols, CV_64F);
  26.   cvmSet(X0, 0, 0, 100);
  27.   cvmSet(X0, 1, 0, 102);
  28.   CalcDiff(X0, dst);
  29.   cvmSet(X0, 0, 0, 0);
  30.   cvmSet(X0, 1, 0, 0);
  31.   cvLevenbergMarquardtOptimization((pointer_LMJac)CalcDerivDiff, (pointer_LMFunc)CalcDiff, X0, dst, res, 50, 0.01);
  32.   return 0;
  33.  }
  34.  
  35.  void CalcDiff( const CvMat *src, CvMat *dst){
  36.   int i;
  37.   double x, val;
  38.   FILE *fp = fopen("./data", "a");
  39.   static count = 0;
  40.   printf("%d repeat\n", count++);
  41.   for(i = 0;i < PRECISION;i++){
  42.   x = CV_PI * ((double)i / PRECISION);
  43.   val = coreCalculation(src, x);
  44.   cvmSet(dst, i, 0, val);
  45.   fprintf(fp, "%f\t", cvmGet(dst, i, 0));
  46.   }
  47.   fprintf(fp, "\n");
  48.  }
  49.  
  50.  void CalcDerivDiff( const CvMat *src, CvMat *dst){
  51.   int i, j;
  52.   double x, val, nextval;
  53.   CvMat *next = cvCreateMat(src->rows,src->cols,src->type);
  54.   for(j = 0;j < 2;j++){
  55.   cvCopy( src, next);
  56.   cvmSet(next, j, 0, cvmGet(src, j, 0) + DERIV_STEP);
  57.   for(i = 0;i < PRECISION;i++){
  58.   x = CV_PI * ((double)i / PRECISION);
  59.   val = coreCalculation(src, x);
  60.   nextval = coreCalculation(next, x);
  61.   cvmSet(dst, i, j, nextval - val);
  62.   }
  63.   }
  64.  }
  65.  
  66.  double coreCalculation( const CvMat *src, double x){
  67.   double a = cvmGet(src, 0, 0);
  68.   double b = cvmGet(src, 1, 0);
  69.   //return a*cos(b*x) + b*sin(a*x);
  70.   return a*cos(3*x) + b*sin(60*x);
  71.  }

実体ファイル

  • OpenCV 1.1以前
    • cvaux/src/cvlevmartif.cpp
    • cvaux/src/cvlevmar.cpp
  • OpenCV 2.1
    • src/cv/cvcalibcation.cpp
    • include/cv.hpp
  • OpenCV 2.2以降
    • opencv2/calib3d/calib3d.hpp
    • modules/calib3d/src/calibration.cpp

ジャンル:OpenCV:OpenCV 1.0:OpenCV 2.1:OpenCV 2.2:OpenCV 2.3準拠


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-10-17 (月) 18:03:55 (2230d)