OpenCV for Ios 學習筆記(9)-用OPENGL渲染AR情境2

來源:互聯網
上載者:User

本文原始地址:OpenCV for Ios 學習筆記(9)-用OPENGL渲染AR情境2

drawFrame的操作步驟是:

1.清除情境。

2.啟動正射投影繪製背景。

3.在視口繪製最後一個從相機擷取到的映像。

4.根據相機內在參數設定透視投影。

5.把每個偵測到的標記的座標系移動到標記的3維位置(把4x4的變換矩陣應用到opengl的模型矩陣上)。

6.呈現一個任意的3維物體。

7.展示幀緩衝。

 我們將會在幀準備好時調用drawFrame - 當一個新的相機幀被上傳到視頻記憶體中,並且標記監測的步驟已經完成。

   下面的就是drawFrame的代碼:

- (void)drawFrame{    //啟動啟用的幀緩衝    [m_glview setFramebuffer];        // 繪製背景    [self drawBackground];        // 在檢測到的標記處繪製3維物體    [self drawAR];        // 呈現幀緩衝    bool ok = [m_glview presentFramebuffer];        int glErCode = glGetError();    if (!ok || glErCode != GL_NO_ERROR)    {        std::cerr << "opengl 檢測出錯,錯誤碼是:" << glErCode << std::endl;    }}

繪製一個背景對我們來說相當容易。我們啟用正視投影並繪製一個全屏的當前幀的映像紋理。下面是opengl es1的代碼:

- (void) drawBackground{    //擷取視口的寬高    GLfloat w = m_glview.bounds.size.width;    GLfloat h = m_glview.bounds.size.height;        //四個頂點座標    const GLfloat squareVertices[] =    {        0, 0,        w, 0,        0, h,        w, h    };        //紋理頂點     static const GLfloat textureVertices[] =     {     1, 0,     1, 1,     0, 0,     0, 1     };        //正視矩陣    static const GLfloat proj[] =    {        0, -2.f/w, 0, 0,        -2.f/h, 0, 0, 0,        0, 0, 1, 0,        1, 1, 0, 1    };    /*     glMatrixMode - 指定哪一個矩陣是當前矩陣          mode 指定哪一個矩陣堆棧是下一個矩陣操作的目標,可選值: GL_MODELVIEW、GL_PROJECTION、GL_TEXTURE.     說明     glMatrixMode設定當前矩陣模式:     GL_MODELVIEW,對模型視景矩陣堆棧應用隨後的矩陣操作.     GL_PROJECTION,對投影矩陣應用隨後的矩陣操作.     GL_TEXTURE,對紋理矩陣堆棧應用隨後的矩陣操作.     與glLoadIdentity()一同使用     glLoadIdentity():該函數的功能是重設當前指定的矩陣為單位矩陣。     在glLoadIdentity()之後我們為情境設定了透視圖。glMatrixMode(GL_MODELVIEW)設定當前矩陣為模型視圖矩陣,模型視圖矩陣儲存了有關物體的資訊。     */    glMatrixMode(GL_PROJECTION);    glLoadMatrixf(proj);        glMatrixMode(GL_MODELVIEW);    glLoadIdentity();        glDepthMask(FALSE);    glDisable(GL_COLOR_MATERIAL);        glEnable(GL_TEXTURE_2D);    glBindTexture(GL_TEXTURE_2D, m_backgroundTextureId);        // 更新屬性值.    glVertexPointer(2, GL_FLOAT, 0, squareVertices);    glEnableClientState(GL_VERTEX_ARRAY);    glTexCoordPointer(2, GL_FLOAT, 0, textureVertices);    glEnableClientState(GL_TEXTURE_COORD_ARRAY);        glColor4f(1,1,1,1);    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);        glDisableClientState(GL_VERTEX_ARRAY);    glDisableClientState(GL_TEXTURE_COORD_ARRAY);    glDisable(GL_TEXTURE_2D);}


在情境中渲染虛擬物體是很機靈的事。首先我們需要根據相機內在參數,適應OpenGL投影矩陣。如果沒有這步,我們將得到錯誤的透射投影,這會使虛擬物體看起來不那麼自然,好像“飄在空中”,沒有真實感!正確的投影是所有增強現實應用的必備。

下面是根據相機內參建立OpenGL投影矩陣的一片代碼:

- (void)buildProjectionMatrix:(Matrix33)cameraMatrix: (int)screen_width: (int)screen_height: (Matrix44&) projectionMatrix{    float near = 0.01;  // 近裁剪距離    float far  = 100;  // 遠裁剪距離        // 相機的參數    float f_x = cameraMatrix.data[0]; // Focal length in x axis    float f_y = cameraMatrix.data[4]; // Focal length in y axis (usually the same?)    float c_x = cameraMatrix.data[2]; // Camera primary point x    float c_y = cameraMatrix.data[5]; // Camera primary point y        projectionMatrix.data[0] = - 2.0 * f_x / screen_width;    projectionMatrix.data[1] = 0.0;    projectionMatrix.data[2] = 0.0;    projectionMatrix.data[3] = 0.0;        projectionMatrix.data[4] = 0.0;    projectionMatrix.data[5] = 2.0 * f_y / screen_height;    projectionMatrix.data[6] = 0.0;    projectionMatrix.data[7] = 0.0;        projectionMatrix.data[8] = 2.0 * c_x / screen_width - 1.0;    projectionMatrix.data[9] = 2.0 * c_y / screen_height - 1.0;    projectionMatrix.data[10] = -( far+near ) / ( far - near );    projectionMatrix.data[11] = -1.0;        projectionMatrix.data[12] = 0.0;    projectionMatrix.data[13] = 0.0;    projectionMatrix.data[14] = -2.0 * far * near / ( far - near );    projectionMatrix.data[15] = 0.0;}

在我們載入這個矩陣到OpenGL管道後,接下來我們繪製物體。

任何一個變換都能夠被4x4矩陣呈現並且載入到OpenGL模型視圖矩陣,這一步將會把座標系移動到全局座標系中的標記處。

例如,讓我們在每個標記的上方繪製一個座標軸-它將會展示標記的在空間中的方向,並用漸層的矩形填充整個標記

。這個視覺化操作將會像預期一樣給我們視覺上反饋。

下面是drawAR函數的實現:

- (void) drawAR{    Matrix44 projectionMatrix;    //相機的內參 螢幕的寬高 待輸出的投影矩陣    [self buildProjectionMatrix:m_calibration.getIntrinsic():m_frameSize.width :m_frameSize.height :projectionMatrix];        glMatrixMode(GL_PROJECTION);    glLoadMatrixf(projectionMatrix.data);        glMatrixMode(GL_MODELVIEW);    glLoadIdentity();        glDepthMask(TRUE);    glEnable(GL_DEPTH_TEST);    //glDepthFunc(GL_LESS);    //glDepthFunc(GL_GREATER);        glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_NORMAL_ARRAY);        glPushMatrix();    glLineWidth(3.0f);        //三條軸    float lineX[] = {0,0,0,1,0,0};    float lineY[] = {0,0,0,0,1,0};    float lineZ[] = {0,0,0,0,0,1};        const GLfloat squareVertices[] = {        -0.5f, -0.5f,        0.5f,  -0.5f,        -0.5f,  0.5f,        0.5f,   0.5f,    };    const GLubyte squareColors[] = {        255, 255,   0, 255,        0,   255, 255, 255,        0,     0,   0,   0,        255,   0, 255, 255,    };        //遍曆標記變換    for (size_t transformationIndex=0; transformationIndex<m_transformations.size(); transformationIndex++)    {        const Transformation& transformation = m_transformations[transformationIndex];                Matrix44 glMatrix = transformation.getMat44();                glLoadMatrixf(reinterpret_cast<const GLfloat*>(&glMatrix.data[0]));                // 繪製資料        glVertexPointer(2, GL_FLOAT, 0, squareVertices);        glEnableClientState(GL_VERTEX_ARRAY);        glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);        glEnableClientState(GL_COLOR_ARRAY);                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);        glDisableClientState(GL_COLOR_ARRAY);                float scale = 0.5;        glScalef(scale, scale, scale);                glTranslatef(0, 0, 0.1f);                glColor4f(1.0f, 0.0f, 0.0f, 1.0f);        glVertexPointer(3, GL_FLOAT, 0, lineX);        glDrawArrays(GL_LINES, 0, 2);                glColor4f(0.0f, 1.0f, 0.0f, 1.0f);        glVertexPointer(3, GL_FLOAT, 0, lineY);        glDrawArrays(GL_LINES, 0, 2);                glColor4f(0.0f, 0.0f, 1.0f, 1.0f);        glVertexPointer(3, GL_FLOAT, 0, lineZ);        glDrawArrays(GL_LINES, 0, 2);    }        glPopMatrix();    glDisableClientState(GL_VERTEX_ARRAY);}

作為一個例子的結尾,我們將示範我們的成果並總結。

OpenCV for Ios 學習筆記(10)-標記檢測總結

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.