拡張現実の2D-> 3D

画像



この記事では、シーン内のオブジェクトの見つかった位置を使用して、 拡張現実アプリケーションで3D空間を構築する方法を説明します。 これを行うには、2つのマトリックスを取得する必要があります。たとえば、OpenGLでの作業用の投影(GL_PROJECTION)とモデル(GL_MODELVIEW)です。 OpenCVライブラリを使用してこれを行います



最近、私はこの問題を解決しなければなりませんでしたが、その方法を段階的に説明しているリソースを見つけられませんでした(たぶん見苦しかったかもしれません)が、この問題には十分な落とし穴があります。 いずれにせよ、このタスクを説明するハブに関する記事は害を与えません。



エントリー



私自身はiOSプログラマーであり、空き時間には自分の拡張現実エンジンを開発しています。 ベースは、コンピュータービジョン用のオープンソースライブラリであるOpenCVが採用しました。



一般的に、この分野でのモバイルデバイス(iOS / Android)の最も興味深い提案は、Qualcommの開発です。



最近では、 Vuforiaという名前で独自のAR SDKをリリースしました。 同時に、ライセンスのパラグラフが誇らしげに述べているように、SDKの使用は開発とアプリケーションのストア(AppStore、AndroidMarket)の両方に無料で使用できます。 同時に、このSDKが匿名情報を収集してQualcommサーバーに送信する可能性があることをエンドユーザーに警告する必要があると書いています。 このセクションを見つけるには、右側のメニューのSDK入門のこのリンククリックします->ステップ3:コンパイルと実行...->アプリケーションの公開。 これに加えて、あなたは私が妄想的であると考えることができますが、SDKが一定の割合で人気を得ると、90%の確信があります。



したがって、自分のエンジンの開発は時間の無駄ではないと思います。



実際には、ポイントまで!



理論



この時点で、プロジェクトにOpenCVを実装し( 方法は? )、カメラからのフレーム内のオブジェクトを認識するメソッドをすでに作成していると考えています。 つまり、次のようなものがあります。



画像



この主題に関する理論は、多くの情報源で見つけることができます。 以下に主なリンクを提供しました。 多くの読み物の質問がありますが、最初のリソースはOpenCVドキュメントページです。



簡単に言えば、見つかった2Dホモグラフィから3D空間を構築するには、2つのマトリックスを知る必要があります。



練習する



実際には、OpenGLがオブジェクトの上に3Dモデルをレンダリングするために、それを設定する必要があります。



注: iOSでは、OpenGLESの2つのバージョン-1.1および2.0を使用できます。 主な違いは、2番目のバージョンのシェーダーの存在です。 どちらの場合でも、2つの行列を指定する必要があります。最初の場合のみ、それらは型の構造によって定義されます。



glMatrixMode(GL_PROJECTION); glLoadMatrixf(projectionMatrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(modelViewMatrix);
      
      







2番目の方法では、シェーダーへの入力にそれらを渡します。



次に、カメラから取得するフレームのサイズがcameraSize =(width、height)であると判断します。 私の場合、cameraSize =(640、480)。



各マトリックスの作成方法を理解しましょう。



射影行列


このマトリックスは、カメラマトリックスに基づいています。 上記のように、後者は特定のカメラパラメータで構成されています。 理論的には、これらのパラメーターはカメラの技術的特性に基づいて計算できますが、実際には誰も計算しません。



カメラパラメータを見つけるプロセスは、キャリブレーションと呼ばれます。 OpenCVには、キャリブレーションを実行するために必要なすべての機能が含まれています。 また、ウェブカメラをオンラインで簡単に調整できるもあります。 ただし、デバイス(iPhone / iPad / iPod)のカメラを調整する必要があります。 そしてここで私はここで説明さた道に沿って行っ



カメラを「オフライン」で較正します。 つまり、デバイスのカメラでキャリブレーションテンプレート(チェッカーボード)の写真を撮影し、写真をコンピューターに転送して、これらの写真からパラメーターを計算します。 いくつかのポイント:



Xcodeプロジェクトキャリブレーションプログラムは、 こちらからダウンロードできます 。 この場合、OpenCVをコンパイルしておく必要があります。 または、ここからコンパイル済みフレームワークダウンロードできます。

写真自体は、コンパイル済みのバイナリを含むフォルダーに入れ、順番に名前を変更する必要があります。

すべてが正常であれば、プログラム出力に2つのファイルが表示されます。



一部の画像でテンプレートが見つからない場合は、これらの画像を他の画像に置き換えてみてください。照明の角度を変えて、テンプレートに対してあまり鋭角にしないでください。 OpenCVは、テンプレートのすべての内部ポイントを簡単に見つけるはずです。

これらのファイルから数値を取得して、OpenGLの射影行列を作成できます。



 float cameraMatrix[9] = {6.24860291e+02, 0., cameraSize.width*0.5f, 0., 6.24860291e+02, cameraSize.height*0.5f, 0., 0., 1.}; - (void)buildProjectionMatrix { // Camera parameters double f_x = cameraMatrix[0]; // Focal length in x axis double f_y = cameraMatrix[4]; // Focal length in y axis (usually the same?) double c_x = cameraMatrix[2]; // Camera primary point x double c_y = cameraMatrix[5]; // Camera primary point y double screen_width = cameraSize.width; // In pixels double screen_height = cameraSize.height; // In pixels double near = 0.1; // Near clipping distance double far = 1000; // Far clipping distance projectionMatrix[0] = 2.0 * f_x / screen_width; projectionMatrix[1] = 0.0; projectionMatrix[2] = 0.0; projectionMatrix[3] = 0.0; projectionMatrix[4] = 0.0; projectionMatrix[5] = 2.0 * f_y / screen_height; projectionMatrix[6] = 0.0; projectionMatrix[7] = 0.0; projectionMatrix[8] = 2.0 * c_x / screen_width - 1.0; projectionMatrix[9] = 2.0 * c_y / screen_height - 1.0; projectionMatrix[10] = -( far+near ) / ( far - near ); projectionMatrix[11] = -1.0; projectionMatrix[12] = 0.0; projectionMatrix[13] = 0.0; projectionMatrix[14] = -2.0 * far * near / ( far - near ); projectionMatrix[15] = 0.0; }
      
      







いくつかのメモ:





行列モデル


このマトリックスを作成するときに、StackOverflowのこの質問が役に立ちました。

幸いなことに、OpenCVでは必要な機能はすでに実装されています。



だからコード:

 float cameraMatrix[9] = {6.24860291e+02, 0., cameraSize.width*0.5f, 0., 6.24860291e+02, cameraSize.height*0.5f, 0., 0., 1.}; float distCoeff[5] = {1.61426172e-01, -5.95113218e-01, 7.10574386e-04, -1.91498715e-02, 1.66041708e+00}; - (void)buildModelViewMatrixUseOld:(BOOL)useOld { clock_t timer; startTimer(&timer); CvMat cvCameraMatrix = cvMat( 3, 3, CV_32FC1, (void*)cameraMatrix ); CvMat cvDistortionMatrix = cvMat( 1, 5, CV_32FC1, (void*)distCoeff ); CvMat* objectPoints = cvCreateMat( 4, 3, CV_32FC1 ); CvMat* imagePoints = cvCreateMat( 4, 2, CV_32FC1 ); // Defining object points and image points int minDimension = MIN(detector->modelWidth, detector->modelHeight)*0.5f; for (int i=0; i<4; i++) { float objectX = (detector->x_corner[i] - detector->modelWidth/2.0f)/minDimension; float objectY = (detector->y_corner[i] - detector->modelHeight/2.0f)/minDimension; cvmSet(objectPoints, i, 0, objectX); cvmSet(objectPoints, i, 1, objectY); cvmSet(objectPoints, i, 2, 0.0f); cvmSet(imagePoints, i, 0, detector->detected_x_corner[i]); cvmSet(imagePoints, i, 1, detector->detected_y_corner[i]); } CvMat* rvec = cvCreateMat(1, 3, CV_32FC1); CvMat* tvec = cvCreateMat(1, 3, CV_32FC1); CvMat* rotMat = cvCreateMat(3, 3, CV_32FC1); cvFindExtrinsicCameraParams2(objectPoints, imagePoints, &cvCameraMatrix, &cvDistortionMatrix, rvec, tvec); // Convert it CV_MAT_ELEM(*rvec, float, 0, 1) *= -1.0; CV_MAT_ELEM(*rvec, float, 0, 2) *= -1.0; cvRodrigues2(rvec, rotMat); GLfloat RTMat[16] = {cvmGet(rotMat, 0, 0), cvmGet(rotMat, 1, 0), cvmGet(rotMat, 2, 0), 0.0f, cvmGet(rotMat, 0, 1), cvmGet(rotMat, 1, 1), cvmGet(rotMat, 2, 1), 0.0f, cvmGet(rotMat, 0, 2), cvmGet(rotMat, 1, 2), cvmGet(rotMat, 2, 2), 0.0f, cvmGet(tvec, 0, 0) , -cvmGet(tvec, 0, 1), -cvmGet(tvec, 0, 2), 1.0f}; cvReleaseMat(&objectPoints); cvReleaseMat(&imagePoints); cvReleaseMat(&rvec); cvReleaseMat(&tvec); cvReleaseMat(&rotMat); printTimerWithPrefix((char*)"ModelView matrix computation", timer); }
      
      





最初に、オブジェクトの4組のポイントとフレーム内の対応する位置を定義する必要があります。

フレーム内の位置ポイントは、フレーム内の(境界)オブジェクトを記述する四角形の頂点です。 変換Hのホモグラフィを使用してポイントデータを取得するには、このホモグラフィを使用してテンプレートの極端なポイントに単純に対処できます。



画像



オブジェクト自体のポイントに関して、いくつかのポイントがあります。



構築された行列は、 cvFindExtrinsicCameraParams2関数に渡されます。 彼女は、回転ベクトルと転送ベクトルを作成します。 回転ベクトルから、回転行列を取得する必要があります。 これは、2番目と3番目の要素に-1を掛けて回転ベクトルを少し変換した後、 cvRodrigues2関数を使用して行われます。 さらに、取得したデータをOpenGLのモデルマトリックスに保存するだけです。 この場合、OpenGLマトリックスを転置する必要があります。

これですべて、一時オブジェクトが削除され、モデルのマトリックスが取得されます。



合計



2つの行列を作成する手順があれば、GLViewを安全に作成し、そこにモデルを描画できます。 モデルのマトリックスを見つける機能は、iPhone 4で10ミリ秒以下で実行されることに注意してください。つまり、その使用は認識のFPSを大幅に低下させません。

ご清聴ありがとうございました。



詳細:



1.http//old.uvr.gist.ac.kr/wlee/web/techReports/ar/Camera%20Models.html

2. http://www.hitl.washington.edu/artoolkit/mail-archive/message-thread-00653-Re--Questions-concering-.html

3.http: //sightations.wordpress.com/2010/08/03/simulating-calibrated-cameras-in-opengl/

4.http ://www.songho.ca/opengl/gl_projectionmatrix.html



All Articles