cvCalibrateCamera2 その1

こいつが曲者だった。英語力がなかったので読み取れなかったが、複数枚の画像を使う。それにあわせて引数をちゃんと作ってやらなければならない。

void cvCalibrateCamera2( const CvMat* object_points, const CvMat* image_points,
                         const CvMat* point_counts, CvSize image_size,
                         CvMat* intrinsic_matrix, CvMat* distortion_coeffs,
                         CvMat* rotation_vectors=NULL, CvMat* translation_vectors=NULL,
                         int flags=0 );

const CvMat* object_points //位置関係の正しいコーナーの座標を格納したベクトル。
const CvMat* image_points //全画像のcornersをまとめて1つのCvMatに変換したもの。
const CvMat* point_counts //各画像ごとにコーナーの総数を格納したもの。
CvSize image_size //キャリブレーションしたい画像のサイズ
CvMat* intrinsic_matrix //返される3*3のカメラ行列。
CvMat* distortion_coeffs //返される4*1の歪み係数ベクトル。
CvMat* rotation_vectors //とりあえずNULLで良い。
CvMat* translation_vectors //とりあえずNULLで良い。
int flags //とりあえず0で良い。

object_pointsのz座標は1.0にすればよいので以下のようにする。10.0とかいうのは適当。とりあえず動いた。

#define CHESS_WIDTH 8				//コーナー列数
#define CHESS_HEIGHT 6				//コーナー行数
#define CHESS_SIZE (CHESS_WIDTH*CHESS_HEIGHT)	//1つのチェスボードに含まれるコーナーの総数
#define NUM_OF_IMAGES 5				//キャリブレーションに使う画像の枚数
#define TOTAL_CORNER (CHESS_SIZE*NUM_OF_IMAGES)	//全画像のコーナーの合計


CvPoint3D32f _objects[TOTAL_CORNER];
CvMat objects;

for(i=0;i<NUM_OF_IMAGES;i++){
    for(j=0;j<CHESS_HEIGHT;j++){
        for(k=0;k<CHESS_WIDTH;k++){
            _objects[i*CHESS_SIZE+j*CHESS_WIDTH+k].x = 10.0*(float)(k-CHESS_WIDTH/2);
            _objects[i*CHESS_SIZE+j*CHESS_WIDTH+k].y = 10.0*(float)(j-CHESS_HEIGHT/2);
            _objects[i*CHESS_SIZE+j*CHESS_WIDTH+k].z = 1.0;
        }
    }
}
cvInitMatHeader(&objects, TOTAL_CORNER, 1, CV_32FC3, _objects, CV_AUTOSTEP);

ていうかcvInitMatHeader()って

CvMat* cvInitMatHeader( CvMat* mat, int rows, int cols, int type,
                        void* data=NULL, int step=CV_AUTOSTEP );

ってなってるから普通にdataを多次元配列のポインタで渡しても大丈夫なんだろうか?未確認。