2009-06-10 12 views
7

cvProjectPoints2 işleviyle ilgili bazı sorunlar yaşıyorum. O'Reilly "Öğrenim OpenCV" kitabından fonksiyon özeti aşağıdadır:, tahmin edilenden istediğiniz noktaların listesiOpenCV cvProjectPoints2 işlevi nasıl kullanılır?

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, 
); 

İlk argüman, object_points olduğu; sadece nokta konumlarını içeren bir N-3 matrisidir. Bunları, nesnenin kendi yerel koordinat sisteminde verebilir ve ardından iki koordinatı ilişkilendirmek için 3'e 1 matrisleri rotation_vector * ve translation_vector'u sağlayabilirsiniz. belirli bir bağlamda kameranın koordinatlarında doğrudan çalışmak daha kolay ise, o zaman sadece o sistemde object_points verip hem rotation_vector ve translation_vector 0s içerecek şekilde ayarlayabilirsiniz. †

intrinsic_matrix ve distortion_coeffs sadece kamera içsel bilgilerdir ve cvCalibrateCamera2() 'den gelen distorsiyon katsayıları, Bölüm 11'de ele alınmıştır. image_points argümanı, hesaplama sonuçlarının yazılacağı bir N-2 matrisidir.

Her şeyden önce, object_points dizisiyle ilgili bir hata var gibi görünüyor. Tek bir nokta varsa, bu N = 1, program çöküyor. Neyse, birkaç kamera iç parametreler ve projeksiyon matrislerim var. Bozulma katsayıları 0 olarak verilir, yani herhangi bir bozulma yoktur. Kolaylık olması açısından , ben 2 kameralar var varsayalım:

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 
}; 

Bildiğim kadarıyla anladığım kadarıyla, bu bilgiler herhangi bir kamera görüntüsü üzerinde herhangi bir noktaya (x, y, z) proje için yeterlidir. Burada, x, y, z koordinatlarında, kamera 4'ün optik merkezi, dünya koordinatlarının kaynağıdır.

İşte benim kod:

#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; 
} 

görüntüleri * 768 1024, ve z görünen kısmı 44 ve Peki amaç kameralarının hem görülmelidir 120 arasında olduğu biliyorum, sağ? Ama sonuç kesinlikle yanlış. M = 1 için bile. Neyi yanlış yapıyorum?

+0

, ama kamera 4 için kamera intrinsics matriste 0,415492 faktör nedir? Ben 0.0 olması bekleniyor. – yhw42

cevap

3

Evet, cvProjectPoints noktaları dizi yansıtmak için kullanılır. Basit matris operasyonları ile bir nokta yansıtabilirsiniz: Kuralların bakmak için çok zamanım olmadı

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);