7

cvProjectPoints2 関数に問題があります。以下は、O'Reilly の「Learning OpenCV」ブックからの関数の概要です。

void cvProjectPoints2(
const CvMat* object_points,
const CvMat* rotation_vector,
const CvMat* translation_vector,
const CvMat* intrinsic_matrix,
const CvMat* distortion_coeffs,
CvMat* image_points,
);

最初の引数 はobject_points、投影するポイントのリストです。これは、点の位置を含む N 行 3 列の行列です。オブジェクト独自のローカル座標系でこれらを指定してから、3 行 1 列の行列rotation_vector* をtranslation_vector指定して、2 つの座標を関連付けることができます。特定のコンテキストで、カメラ座標で直接作業する方が簡単な場合はobject_points、そのシステムを使用して、 と の両方rotation_vectorを設定translation_vectorし、0 を含めることができます。†

intrinsic_matrixとはdistortion_coeffs、カメラ固有の情報と、第 11 章で説明した cvCalibrateCamera2() からの歪み係数です。image_points引数は、計算結果が書き込まれる N 行 2 列の行列です。

まず、object_points配列にバグがあるようです。ポイントが 1 つしかない場合、つまり N=1 の場合、プログラムはクラッシュします。とにかく、私はいくつかのカメラ固有パラメータと射影行列を持っています。歪み係数は 0 として与えられます。つまり、歪みはありません。簡単にするために、2 台のカメラがあると仮定します。

double intrinsic[2][3][3] = {
//camera 0
1884.190000,    0, 513.700000,
0.0,    1887.490000,    395.609000,
0.0,    0.0,    1.0,
//camera 4
1877.360000,    0.415492,   579.467000,
0.0,    1882.430000,    409.612000,
0.0,    0.0,    1.0
};

double projection[2][3][4] = {
//camera 0
0.962107,   -0.005824,  0.272486,   -14.832727,
0.004023,   0.999964,   0.007166,   0.093097,
-0.272519,  -0.005795,  0.962095,   -0.005195,
//camera 4
1.000000,   0.000000,   -0.000000,  0.000006,
0.000000,   1.000000,   -0.000000,  0.000001,
-0.000000,  -0.000000,  1.000000,   -0.000003
};

私が理解している限り、この情報は任意のカメラ ビューに任意の点 (x、y、z) を投影するのに十分です。ここで、x、y、z 座標では、カメラ 4 の光学中心がワールド座標の原点です。

これが私のコードです:

#include <cv.h>
#include <highgui.h>
#include <cvaux.h>
#include <cxcore.h>
#include <stdio.h>

double intrinsic[2][3][3] = {
//0
1884.190000,    0, 513.700000,
0.0,    1887.490000,    395.609000,
0.0,    0.0,    1.0,
//4
1877.360000,    0.415492,   579.467000,
0.0,    1882.430000,    409.612000,
0.0,    0.0,    1.0
};

double projection[2][3][4] = {
//0
0.962107,   -0.005824,  0.272486,   -14.832727,
0.004023,   0.999964,   0.007166,   0.093097,
-0.272519,  -0.005795,  0.962095,   -0.005195,
//4
1.000000,   0.000000,   -0.000000,  0.000006,
0.000000,   1.000000,   -0.000000,  0.000001,
-0.000000,  -0.000000,  1.000000,   -0.000003
};


int main() {
    CvMat* camera_matrix[2]; //
    CvMat* rotation_matrix[2]; //
    CvMat* dist_coeffs[2]; 
    CvMat* translation[2];
    IplImage* image[2];
    image[0] = cvLoadImage("color-cam0-f000.bmp", 1);
    image[1] = cvLoadImage("color-cam4-f000.bmp", 1);
    CvSize image_size;
    image_size = cvSize(image[0]->width, image[0]->height);

    for (int m=0; m<2; m++) {
        camera_matrix[m] = cvCreateMat(3, 3, CV_32F);
        dist_coeffs[m] = cvCreateMat(1, 4, CV_32F);
        rotation_matrix[m] = cvCreateMat(3, 3, CV_32F);
        translation[m] = cvCreateMat(3, 1, CV_32F);
    }

    for (int m=0; m<2; m++) {
        for (int i=0; i<3; i++)
            for (int j=0; j<3; j++) {
                cvmSet(camera_matrix[m],i,j, intrinsic[m][i][j]);
                cvmSet(rotation_matrix[m],i,j, projection[m][i][j]);
            }
        for (int i=0; i<4; i++)
            cvmSet(dist_coeffs[m], 0, i, 0);
        for (int i=0; i<3; i++)
            cvmSet(translation[m], i, 0, projection[m][i][3]);
    }

    CvMat* vector = cvCreateMat(3, 1, CV_32F);
    CvMat* object_points = cvCreateMat(10, 3, CV_32F);
    cvmSet(object_points, 0, 0, 1000);
    cvmSet(object_points, 0, 1, 500);
    cvmSet(object_points, 0, 2, 100);

    CvMat* image_points = cvCreateMat(10, 2, CV_32F);
    int m = 0;
    cvRodrigues2(rotation_matrix[m], vector);
    cvProjectPoints2(object_points, vector, translation[m], camera_matrix[m], dist_coeffs[m], image_points);
    printf("%f\n", cvmGet(image_points, 0, 0));
    printf("%f\n", cvmGet(image_points, 0, 1));
    return 0;
}

画像は 1024*768 で、z の可視部分は 44 から 120 の間であることが知られています。つまり、点は両方のカメラで見られるはずですよね? しかし、結果は完全に間違っています。m = 1 の場合でも、何が間違っていますか?

4

1 に答える 1

3

ええ、cvProjectPoints は点の配列を射影するために使用されます。単純な行列演算で 1 点を射影できます。

CvMat *pt = cvCreateMat(3, 1, CV_32FC1);
CvMat *pt_rt = cvCreateMat(3, 1, CV_32FC1);
CvMat *proj_pt = cvCreateMat(3, 1, CV_32FC1);
cvMatMulAdd(rotMat, pt, translation, pt_rt);
cvMatMul(intrinsic, pt_rt, proj_pt);
// convertPointsHomogenious might be used
float scale = (float)CV_MAT_ELEM(*proj_pt, float, 2, 0); 
float x = CV_MAT_ELEM(*proj_pt, float, 0, 0) / scale;
float y = CV_MAT_ELEM(*proj_pt, float, 1, 0) / scale;
CvPoint2D32f img_pt = cvPoint2D32f(x, y);
于 2010-07-23T14:29:58.753 に答える