2012-04-25 14 views
6

Temel artırılmış gerçekliği yapmak için OpenCV kullanmaya çalışıyorum. Ben bu konuda bir yol bir kamera görüntüsünden puan almak için findChessboardCorners kullanıyor. Sonra, z = 0 düzlemi boyunca bir 3D dörtlü yaratıyorum ve görüntülenen noktalar ile düzlemsel noktalar arasında bir homografi elde etmek için solvePnP kullanın. Bundan sonra, görüntünün üstünde doğru poz ile küp oluşturmamı sağlayacak bir modelview matrisi oluşturabilmem gerektiğini düşünüyorum.OpenCV: Rotasyon/çeviri vektörü OpenGL model görünümü matrisi

solvePnP için documentation, "(çeviri vektörü ile birlikte), model koordinat sisteminden kamera koordinat sistemine noktalar getirdiği" bir döndürme vektörü çıkardığını belirtir. " Bence istediğimin tam tersi; benim dörtlü z = 0 düzleminde olduğundan, bu dörtgeni uygun 3B düzlemine dönüştürecek bir modelview matrisi istiyorum.

Karşılıklı sırayla ters çevirileri ve çevirileri yaparak, doğru modelview matrisini hesaplayabilirim, ancak işe yaramayacağını düşündüm. İşlenen nesne (bir küp) kamera görüntüsüyle hareket ederken ve çeviri açısından kabaca doğru gibi görünüyor olsa da, döndürme işlemi hiç çalışmıyor; Birden fazla eksenin sadece bir tanesinin üzerinde ve bazen de yanlış yönde dönmesi gerektiğinde. İşte ben bugüne kadar ne yapıyorum: Sonra çizim kodunda

std::vector<Point2f> corners; 
bool found = findChessboardCorners(*_imageBuffer, cv::Size(5,4), corners, 
             CV_CALIB_CB_FILTER_QUADS | 
             CV_CALIB_CB_FAST_CHECK); 
if(found) 
{ 
    drawChessboardCorners(*_imageBuffer, cv::Size(6, 5), corners, found); 

    std::vector<double> distortionCoefficients(5); // camera distortion 
    distortionCoefficients[0] = 0.070969; 
    distortionCoefficients[1] = 0.777647; 
    distortionCoefficients[2] = -0.009131; 
    distortionCoefficients[3] = -0.013867; 
    distortionCoefficients[4] = -5.141519; 

    // Since the image was resized, we need to scale the found corner points 
    float sw = _width/SMALL_WIDTH; 
    float sh = _height/SMALL_HEIGHT; 
    std::vector<Point2f> board_verts; 
    board_verts.push_back(Point2f(corners[0].x * sw, corners[0].y * sh)); 
    board_verts.push_back(Point2f(corners[15].x * sw, corners[15].y * sh)); 
    board_verts.push_back(Point2f(corners[19].x * sw, corners[19].y * sh)); 
    board_verts.push_back(Point2f(corners[4].x * sw, corners[4].y * sh)); 
    Mat boardMat(board_verts); 

    std::vector<Point3f> square_verts; 
    square_verts.push_back(Point3f(-1, 1, 0));        
    square_verts.push_back(Point3f(-1, -1, 0)); 
    square_verts.push_back(Point3f(1, -1, 0)); 
    square_verts.push_back(Point3f(1, 1, 0)); 
    Mat squareMat(square_verts); 

    // Transform the camera's intrinsic parameters into an OpenGL camera matrix 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    // Camera parameters 
    double f_x = 786.42938232; // Focal length in x axis 
    double f_y = 786.42938232; // Focal length in y axis (usually the same?) 
    double c_x = 217.01358032; // Camera primary point x 
    double c_y = 311.25384521; // Camera primary point y 


    cv::Mat cameraMatrix(3,3,CV_32FC1); 
    cameraMatrix.at<float>(0,0) = f_x; 
    cameraMatrix.at<float>(0,1) = 0.0; 
    cameraMatrix.at<float>(0,2) = c_x; 
    cameraMatrix.at<float>(1,0) = 0.0; 
    cameraMatrix.at<float>(1,1) = f_y; 
    cameraMatrix.at<float>(1,2) = c_y; 
    cameraMatrix.at<float>(2,0) = 0.0; 
    cameraMatrix.at<float>(2,1) = 0.0; 
    cameraMatrix.at<float>(2,2) = 1.0; 

    Mat rvec(3, 1, CV_32F), tvec(3, 1, CV_32F); 
    solvePnP(squareMat, boardMat, cameraMatrix, distortionCoefficients, 
       rvec, tvec); 

    _rv[0] = rvec.at<double>(0, 0); 
    _rv[1] = rvec.at<double>(1, 0); 
    _rv[2] = rvec.at<double>(2, 0); 
    _tv[0] = tvec.at<double>(0, 0); 
    _tv[1] = tvec.at<double>(1, 0); 
    _tv[2] = tvec.at<double>(2, 0); 
} 

...

GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 0.0f); 
modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, -tv[1], -tv[0], -tv[2]); 
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, -rv[0], 1.0f, 0.0f, 0.0f); 
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, -rv[1], 0.0f, 1.0f, 0.0f); 
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, -rv[2], 0.0f, 0.0f, 1.0f); 

ben den yani (menşe etrafında birim uzunlukta bir küp oluşturmak render ediyorum köşe - Her bir kenar boyunca 0,5 ila 0,5 arasında. OpenGL çeviri işlevlerini kullanarak "ters sırayla" dönüşümleri gerçekleştirdiğimi biliyorum, böylece yukarıdaki küpü z, y ve sonra x ekseni boyunca döndürmeli ve sonra çevirmelidir. Ancak, önce çevrildiğini ve sonra döndürülmüş gibi görünüyor, bu yüzden belki de Apple'ın GLKMatrix4 farklı çalışır?

This question, benimkine çok benziyor ve özellikle kodlayıcı9'un cevabı, az çok aradığım şey gibi görünüyor. Ancak, bunu denedim ve sonuçları yöntemimle karşılaştırdım ve her iki durumda da geldiğim matrisler aynıydı. Cevabın doğru olduğunu hissediyorum, ancak bazı önemli ayrıntıları kaçırdığımı düşünüyorum.

+1

Bunu kendim yapmayı deneyin. Bu gönderiyi koordinat sistemi farklılıkları konusuna baktım. http://stackoverflow.com/questions/9081900/reference-coordinate-system-changes-between-opencv-opengl-and-android-sensor – Koobz

cevap

2

Eksenin doğru yöne baktığından emin olmalısınız. Özellikle y ve z ekseni, x-y-z tabanının doğrudan olduğundan emin olmak için OpenGL ve OpenCV'de farklı yönlere bakar. Bazı bilgi ve kodları (iPad kamera ile) bu blog post'da bulabilirsiniz.

- Düzenle - Ah ok. Ne yazık ki, bazı algoritmaları test etmek için bu kaynakları diğer yoldan (opengl ---> opencv) yapmak için kullandım. Benim asıl meselem görüntünün sıra sırasının OpenGL ve OpenCV arasında tersine çevrilmiş olmasıydı (belki bu yardımcı olur).

Kameraları simüle ederken, here ve generalized projection matrix paper numaralı belgelerdeki aynı projeksiyon matrislerine rastladım. Blog yayınının yorumlarında alıntılanan This paper da bilgisayar görüşü ve OpenGL projeksiyonları arasında bir bağlantı gösterir.

+0

Bağlantı için teşekkürler. Maalesef bu yazıyı daha önce görmüştüm. Kodunu az çok ya da daha az dil ile kullanmayı denedim ve temelde aynı sonuçları aldım. Bu yazının da önemli detayları kaçırdığını düşünüyorum çünkü muhtemelen önemli olan homografiyi nasıl hesapladığını göstermiyor. Ayrıca y/z ekseni farklarının farkındaydım, ama kodumu birkaç kez gözden geçirdim ve bunu ele alabildiğim kadarıyla. –

0

IOS programcısı değilim, bu yüzden bu yanıt yanıltıcı olabilir! Sorun, dönüşleri ve çeviriyi uygulama sırasına göre değilse, daha basit ve daha sık kullanılan bir koordinat sistemi kullanmanızı öneririz.

Köşelerdeki vektörler, görüntünün sol üst köşesindeki menşei (0,0) ve y ekseni görüntünün altına doğrudur.Genellikle matematikten, koordinat sistemini merkezdeki orijini ve y eksenini görüntünün üstüne doğru düşünmek için kullanılır. Koordinatlardan board_verts'e geçiyorsunuz sanırım aynı hatayı yapıyorsunuz. Eğer durum buysa, bu gibi bir şey tarafından köşelerinden pozisyonlarını dönüştürmek kolay:

for (i=0;i<corners.size();i++) { 
    corners[i].x -= width/2; 
    corners[i].y = -corners[i].y + height/2; 
} 

o zaman() solvePnP diyoruz. Bunun hata ayıklaması o kadar da zor değil, sadece dört köşenin pozisyonlarını ve tahmini R ve T'yi yazıp, mantıklı olup olmadıklarını görün. Sonra OpenGL adımına geçebilirsiniz. Lütfen bana nasıl olduğunu bilmeme izin ver.