2017-09-20 27 views
1

問題は次のとおりです。私はOpenGLティーポットを図面付き紙に表示するコードを書いています。このために、用紙の4つのコーナーを追跡します(SURF検出&のマッチングに続いてホモグラフィ行列を計算し、コーナー位置の平均を移動してジッタを減らします)。コーナー座標は、カメラの固有の&(それぞれcalibrateCamera()およびsolvePnP()を使用)を計算するために使用されます。回転行列は、Rodrigues()を使用して計算されます。その後、decomposeProjectionMatrix()を使用して回転角度を計算しました。ここで、コードのOpenCVの一部です: AR with OpenCV&OpenGL

... 
objPoints.push_back(objCorners); 
scenePoints.push_back(sceneCorners); 
calibrateCamera(objPoints, scenePoints, Size(640,480), camMtx, distortCoeff, RVecs, tVecs); 
solvePnP(objCorners, sceneCorners, camMtx, distortCoeff, RVec, tVec); 
Rodrigues(RVec, rotMtx); 
getAngles(rotMtx, rotAngles); 

objCorners

コーナーであるが、テンプレート画像の座標([1 1]、[IMG幅1]、[IMG幅IMG高さ]、[1つのIMG高さ])。 sceneCornersはホモグラフィ行列を使用して計算されたWebカメラフレームのコーナー座標です。次のように機能 getAngles()は、次のよう

void getAngles(Mat &rotCamMtx, Vec3d &angles) 
{ 
    Mat camMtx, rotMtx, transVec, rotMtxX, rotMtxY, rotMtxZ; 
    double *r = rotCamMtx.ptr<double>(); 
    double projMtx[12] = {r[0], r[1], r[2], 0, 
          r[3], r[4], r[5], 0, 
          r[6], r[7], r[8], 0}; 

    decomposeProjectionMatrix(Mat(3,4,CV_64FC1,projMtx), camMtx, rotMtx, transVec, rotMtxX, rotMtxY, rotMtxZ, angles); 
} 

そしてIは、OpenGLモデルビュー行列の要素を設定:

modelViewMat[0] = 1.0; 
modelViewMat[1] = 0.0; 
modelViewMat[2] = 0.0; 
modelViewMat[3] = 0.0; 
modelViewMat[4] = 0.0; 
modelViewMat[5] = 1.0; 
modelViewMat[6] = 0.0; 
modelViewMat[7] = 0.0; 
modelViewMat[8] = 0.0; 
modelViewMat[9] = 0.0; 
modelViewMat[10] = 1.0; 
modelViewMat[11] = 0.0; 
modelViewMat[12] = 2*matCenter.x/639 - 641/639; 
modelViewMat[13] = 481/479 - 2*matCenter.y/479; 
modelViewMat[14] = -0.25; 
modelViewMat[15] = 1.0; 

matCenter中心の平均を取ることによって得られる紙の座標であります4つのコーナー。 modelViewMat[12]およびmodelViewMat[13]の値は、ピクセル座標([1 640]、[1 480])を([-1 1]、[1 -1])にマッピングすることによって得られます。

... 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 

glMatrixMode(GL_MODELVIEW); 
glLoadMatrixd(modelViewMat); 

glRotated(-45, 1.0, 0.0, 0.0); 
glRotated(rotAngles[2], 0.0, 1.0, 0.0); 

glShadeModel(GL_SMOOTH); 
glColor3f(1.0, 1.0, 1.0); 
glutSolidTeapot(0.3); 

私はそれが紙の上に「座って」見える作るためにティーポットにx軸の周りに-45度回転:コードのOpenGLの一部。 結果は次のようになります:私が机の上で紙を翻訳すると、紙の上のティーポットの位置は(同じ場所で)多かれ少なかれ正しいです。紙を回転させると、ティーポットは回転(y軸の周り)に正しく追従しますが、正しい位置にはなりません。質問は、紙の同じ場所にティーポットを「ピン止め」する方法です。私はRodrigues()solvePnP()の結果をOpenGLモデルビューマトリックス(OpenCV + OpenGL: proper camera pose using solvePnPで示唆)で直接使用しようとしましたが、結果は正しくありません。

答えて

0

この問題は数日前、http://blog.yarrago.com/2011/08/introduction-to-augmented-reality.htmlのコードに基づいて解決されました。 3Dオブジェクトを正しく表示するには、まずOpenGL投影行列を設定し、次にOpenGLモデルの表示行列を設定します。次のように射影行列の要素は、カメラの固有マトリックスから計算される:

calibrateCamera(objPoints, scenePoints, Size(640,480), camMtx, distortCoeff, RVecs, tVecs); 
... 
projectionMat[0] = 2*camMtx.at<double>(0,0)/frameW; 
projectionMat[1] = 0; 
projectionMat[2] = 0; 
projectionMat[3] = 0; 
projectionMat[4] = 0; 
projectionMat[5] = 2*camMtx.at<double>(1,1)/frameH; 
projectionMat[6] = 0; 
projectionMat[7] = 0; 
projectionMat[8] = 1 - 2*camMtx.at<double>(0,2)/frameW; 
projectionMat[9] = -1 + (2*camMtx.at<double>(1,2) + 2)/frameH; 
projectionMat[10] = (zNear + zFar)/(zNear - zFar); 
projectionMat[11] = -1; 
projectionMat[12] = 0; 
projectionMat[13] = 0; 
projectionMat[14] = 2*zNear*zFar/(zNear - zFar); 
projectionMat[15] = 0; 

frameWframeHは、それぞれ、640480あります。 zNear0.1であり、zFar100である。

OpenGLモデルビュー行列の要素は、回転行列と並進ベクトル(solvePnP()Rodrigues()から取得)から計算されます。 3Dオブジェクトの正しい位置を取得するには、モデルビューマトリックスを計算する前に変換ベクトルを変換する必要があります。

// Offset value to move the translation vector 
double offsetC[3][1] = {424, 600, 0}; 
Mat offset(3, 1, CV_64F, offsetC); 
... 
solvePnP(objCorners, sceneCorners, camMtx, distortCoeff, RVec, tVec); 
Rodrigues(RVec, rotMtx); 
tVec = tVec + rotMtx*offset; // Move tVec to refer to the center of the paper 
tVec = tVec/250.0;   // Converting pixel coordinates to OpenGL world coordinates 
... 
modelviewMat[0] = rotMtx.at<double>(0,0); 
modelviewMat[1] = -rotMtx.at<double>(1,0); 
modelviewMat[2] = -rotMtx.at<double>(2,0); 
modelviewMat[3] = 0; 
modelviewMat[4] = rotMtx.at<double>(0,1); 
modelviewMat[5] = -rotMtx.at<double>(1,1); 
modelviewMat[6] = -rotMtx.at<double>(2,1); 
modelviewMat[7] = 0; 
modelviewMat[8] = rotMtx.at<double>(0,2); 
modelviewMat[9] = -rotMtx.at<double>(1,2); 
modelviewMat[10] = -rotMtx.at<double>(2,2); 
modelviewMat[11] = 0; 
modelviewMat[12] = tVec.at<double>(0,0); 
modelviewMat[13] = -tVec.at<double>(1,0); 
modelviewMat[14] = -tVec.at<double>(2,0); 
modelviewMat[15] = 1; 

offsetCの数値は、用紙の中央のピクセル座標です。コードのOpenGLの一部は次のようになります。ティーポットの正確な位置決めのための

glMatrixMode(GL_PROJECTION); 
glLoadMatrixf(projectionMat); 

glMatrixMode(GL_MODELVIEW); 
glLoadMatrixf(modelviewMat); 

glRotatef(90, -1.0, 0.0, 0.0); // Rotate the teapot first so that it will be displayed correctly on the paper 
glutSolidTeapot(1.0); 

一つ重要なことは、tVecの転換です。