OpenCV 将坐标传递给 OpenGL 但 OpenGL 无法绘制它

发布于 2025-01-04 09:00:03 字数 5427 浏览 0 评论 0原文

下面是我的程序,它通过 OpenCV 计算棋盘的旋转向量、旋转矩阵。然后通过从这个向量和矩阵创建 16 个值的数组,我将其传递给 OpenGL。但OpenGL窗口无法显示任何内容。 这种连接OpenCV和OpenGL的方法正确吗? 为什么OpenGL不绘制形状?

// this function for calculating rotation matrix and vector
void calculateOpenCVPoints(IplImage* image)
    {

    board_w = 4; // Board width in squares
    board_h = 5; // Board height 
    n_boards =3; // Number of boards
    board_n = board_w * board_h;
    CvSize board_sz = cvSize( board_w, board_h );

    CvMat* warp_matrix = cvCreateMat(3,3,CV_32FC1);
    CvPoint2D32f* corners = new CvPoint2D32f[ board_n ];
    int corner_count;
    char pressedChar;
    //cvNamedWindow("Livevideo",CV_WINDOW_AUTOSIZE);
    imgPoints = cvCreateMat(n_boards*board_n,2,CV_32FC1) ;
    objectPoints=cvCreateMat(n_boards*board_n,3,CV_32FC1);
    pointCounts = cvCreateMat(n_boards,1,CV_32SC1);
    intrinsicMatrix = cvCreateMat(3,3,CV_32FC1);
    distortionCoeffs = cvCreateMat(5,1,CV_32FC1);
    corners = new CvPoint2D32f[ board_n ];

    IplImage *grayImage = cvCreateImage(cvGetSize(image),8,1);//subpixel
    successes = 0;
        while(successes < n_boards) 
        {
            printf("\nIn calculateOpenCVPoints function for calculating image points ==%d",successes);
            //Skip every board_dt frames to allow user to move chessboard
            if(frame++ % board_dt == 0) 
                {
                    //Find chessboard corners:
                    int found = cvFindChessboardCorners(image, board_sz, corners, &cornerCount,
                        CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);    

                cvCvtColor( image, grayImage, CV_BGR2GRAY );
                cvFindCornerSubPix( grayImage, corners, cornerCount, cvSize( 11, 11 ), 
                cvSize( -1, -1 ), cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));
                cvDrawChessboardCorners(image, board_sz, corners,cornerCount, found);
                cvShowImage("Calibration", image );

                if( cornerCount == board_n )
                    {
                    step = successes*board_n;
                    for( int i=step, j=0; j < board_n; ++i, ++j )
                        {
                        CV_MAT_ELEM( *imgPoints, float, i, 0 ) = corners[j].x;
                        CV_MAT_ELEM( *imgPoints, float, i, 1 ) = corners[j].y;
                        CV_MAT_ELEM( *objectPoints, float, i, 0 ) = j/board_w;
                        CV_MAT_ELEM( *objectPoints, float, i, 1 ) = j%board_w;
                        CV_MAT_ELEM( *objectPoints, float, i, 2 ) = 0.0f;
                        }
                    CV_MAT_ELEM( *pointCounts, int, successes, 0 ) = board_n;
                    successes++;
                    }
                }//if(frame++ % board_dt == 0) 
            image = cvQueryFrame( cvCapture );
            //cvShowImage("liveVideo",image);
            presssedChar=cvWaitKey(5);
        } //while(successes < n_boards) 
        cvFindExtrinsicCameraParams2(objectPoints,imgPoints,intrinsic,distortion,rotationVector,translationVector,0);
        cvRodrigues2(rotationVector,rotationMatrix,NULL);
        printf("\nRotation Vector and Rotation Matrx are calculated\n");
        float rv[]={rotationVector->data.fl[0],rotationVector->data.fl[1],rotationVector->data.fl[2]};
        float tv[]={translationVector->data.fl[0],translationVector->data.fl[1],translationVector->data.fl[2]};
        float rm[9];


        for(int i=0;i<9;i++)
            rm[i]=rotationMatrix->data.fl[i];

        for (int f=0; f<3; f++)
            {
            for (int c=0; c<3; c++)
                {
                toGLMatrix[c*4+f] = rm[f*3+c];  //transposed
                }
            }   

        toGLMatrix[3] = 0.0;
        toGLMatrix[7] = 0.0;    
        toGLMatrix[11] = 0.0;
        toGLMatrix[12] = -tv[0];
        toGLMatrix[13] = -tv[1]; 
        toGLMatrix[14] = tv[2];
        toGLMatrix[15] = 1.0;

    }


// openGL dispaly function
       void display
       {
                      calculateOpenCVPoints("Image from camera");
                       glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();

            //argDraw3dCamera( 0, 0 );
            glViewport(0, 0, 640,480);
            glMatrixMode(GL_PROJECTION);
            glLoadMatrixd(toGLMatrix);

            glClearDepth( 1.0 );
            glClear(GL_DEPTH_BUFFER_BIT);
            glEnable(GL_DEPTH_TEST);
            glDepthFunc(GL_LEQUAL);
            glMatrixMode(GL_MODELVIEW);
            // Loading the calculated matrix from OpenCV rotation matrix and vector
            glLoadMatrixd(toGLMatrix);

            glEnable(GL_LIGHTING);
            glEnable(GL_LIGHT0);
            glLightfv(GL_LIGHT0, GL_POSITION, light_position);
            glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);
            glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
            glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash);
            glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny);  
            glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
            glMatrixMode(GL_MODELVIEW);
            glColor3d(1.0f,1.0f,1.0f);
            glTranslatef( 0.0, 0.0,0.0 );
            glutSolidCube(140);
            glDisable( GL_LIGHTING );
            glDisable( GL_DEPTH_TEST );
                        glutSwapBuffers();
           }

// and remaining as initialize glut etc 

Below is my program which calculates the rotation vector, rotation matrix from chessboard through OpenCV. And then by creating array of 16 values from this vector and matrix I am passing this to OpenGL. But OpenGL window cant show anything.
Is this way is correct to connect OpenCV and OpenGL?
Why OpenGL not drawing the shape?

// this function for calculating rotation matrix and vector
void calculateOpenCVPoints(IplImage* image)
    {

    board_w = 4; // Board width in squares
    board_h = 5; // Board height 
    n_boards =3; // Number of boards
    board_n = board_w * board_h;
    CvSize board_sz = cvSize( board_w, board_h );

    CvMat* warp_matrix = cvCreateMat(3,3,CV_32FC1);
    CvPoint2D32f* corners = new CvPoint2D32f[ board_n ];
    int corner_count;
    char pressedChar;
    //cvNamedWindow("Livevideo",CV_WINDOW_AUTOSIZE);
    imgPoints = cvCreateMat(n_boards*board_n,2,CV_32FC1) ;
    objectPoints=cvCreateMat(n_boards*board_n,3,CV_32FC1);
    pointCounts = cvCreateMat(n_boards,1,CV_32SC1);
    intrinsicMatrix = cvCreateMat(3,3,CV_32FC1);
    distortionCoeffs = cvCreateMat(5,1,CV_32FC1);
    corners = new CvPoint2D32f[ board_n ];

    IplImage *grayImage = cvCreateImage(cvGetSize(image),8,1);//subpixel
    successes = 0;
        while(successes < n_boards) 
        {
            printf("\nIn calculateOpenCVPoints function for calculating image points ==%d",successes);
            //Skip every board_dt frames to allow user to move chessboard
            if(frame++ % board_dt == 0) 
                {
                    //Find chessboard corners:
                    int found = cvFindChessboardCorners(image, board_sz, corners, &cornerCount,
                        CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);    

                cvCvtColor( image, grayImage, CV_BGR2GRAY );
                cvFindCornerSubPix( grayImage, corners, cornerCount, cvSize( 11, 11 ), 
                cvSize( -1, -1 ), cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));
                cvDrawChessboardCorners(image, board_sz, corners,cornerCount, found);
                cvShowImage("Calibration", image );

                if( cornerCount == board_n )
                    {
                    step = successes*board_n;
                    for( int i=step, j=0; j < board_n; ++i, ++j )
                        {
                        CV_MAT_ELEM( *imgPoints, float, i, 0 ) = corners[j].x;
                        CV_MAT_ELEM( *imgPoints, float, i, 1 ) = corners[j].y;
                        CV_MAT_ELEM( *objectPoints, float, i, 0 ) = j/board_w;
                        CV_MAT_ELEM( *objectPoints, float, i, 1 ) = j%board_w;
                        CV_MAT_ELEM( *objectPoints, float, i, 2 ) = 0.0f;
                        }
                    CV_MAT_ELEM( *pointCounts, int, successes, 0 ) = board_n;
                    successes++;
                    }
                }//if(frame++ % board_dt == 0) 
            image = cvQueryFrame( cvCapture );
            //cvShowImage("liveVideo",image);
            presssedChar=cvWaitKey(5);
        } //while(successes < n_boards) 
        cvFindExtrinsicCameraParams2(objectPoints,imgPoints,intrinsic,distortion,rotationVector,translationVector,0);
        cvRodrigues2(rotationVector,rotationMatrix,NULL);
        printf("\nRotation Vector and Rotation Matrx are calculated\n");
        float rv[]={rotationVector->data.fl[0],rotationVector->data.fl[1],rotationVector->data.fl[2]};
        float tv[]={translationVector->data.fl[0],translationVector->data.fl[1],translationVector->data.fl[2]};
        float rm[9];


        for(int i=0;i<9;i++)
            rm[i]=rotationMatrix->data.fl[i];

        for (int f=0; f<3; f++)
            {
            for (int c=0; c<3; c++)
                {
                toGLMatrix[c*4+f] = rm[f*3+c];  //transposed
                }
            }   

        toGLMatrix[3] = 0.0;
        toGLMatrix[7] = 0.0;    
        toGLMatrix[11] = 0.0;
        toGLMatrix[12] = -tv[0];
        toGLMatrix[13] = -tv[1]; 
        toGLMatrix[14] = tv[2];
        toGLMatrix[15] = 1.0;

    }


// openGL dispaly function
       void display
       {
                      calculateOpenCVPoints("Image from camera");
                       glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();

            //argDraw3dCamera( 0, 0 );
            glViewport(0, 0, 640,480);
            glMatrixMode(GL_PROJECTION);
            glLoadMatrixd(toGLMatrix);

            glClearDepth( 1.0 );
            glClear(GL_DEPTH_BUFFER_BIT);
            glEnable(GL_DEPTH_TEST);
            glDepthFunc(GL_LEQUAL);
            glMatrixMode(GL_MODELVIEW);
            // Loading the calculated matrix from OpenCV rotation matrix and vector
            glLoadMatrixd(toGLMatrix);

            glEnable(GL_LIGHTING);
            glEnable(GL_LIGHT0);
            glLightfv(GL_LIGHT0, GL_POSITION, light_position);
            glLightfv(GL_LIGHT0, GL_AMBIENT, ambi);
            glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
            glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash);
            glMaterialfv(GL_FRONT, GL_SHININESS, mat_flash_shiny);  
            glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
            glMatrixMode(GL_MODELVIEW);
            glColor3d(1.0f,1.0f,1.0f);
            glTranslatef( 0.0, 0.0,0.0 );
            glutSolidCube(140);
            glDisable( GL_LIGHTING );
            glDisable( GL_DEPTH_TEST );
                        glutSwapBuffers();
           }

// and remaining as initialize glut etc 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

各自安好 2025-01-11 09:00:03
        glViewport(0, 0, 640,480);
        glMatrixMode(GL_PROJECTION);
        glLoadMatrixd(toGLMatrix);

        glMatrixMode(GL_MODELVIEW);
        // Loading the calculated matrix from OpenCV rotation matrix and vector
        glLoadMatrixd(toGLMatrix);

您在这里加载矩阵两次。这没有道理。它将把顶点转换为

v' = M M v = M² v

绝对不是你想要的。

OpenCV 提供的矩阵结合了投影和模型视图。理想情况下,您不会使用固定功能 OpenGL,而是使用顶点着色器。这会让事情变得更清楚。

对于简单的应用程序,只需将 OpenCV 中的矩阵加载到模型视图中,并使投影成为恒等变换。

如果您希望它正确,请将 OpenCV 中的矩阵分成两部分:正交模型视图部分和匹配投影部分,其中 Z 列的 x 和 y 分量为零。令 C 为 OpenCV 的矩阵。为此求解方程组:

C = P M

P.zx = 0
P.zy = 0
P.zz =/= 0
P.zw =/= 0

M.x · M.y = 0
M.y · M.z = 0
M.z · M.x = 0

M.xw = 0
M.yw = 0
M.zw = 0
M.ww = 1

| M.x | = 1
| M.y | = 1
| M.z | = 1
        glViewport(0, 0, 640,480);
        glMatrixMode(GL_PROJECTION);
        glLoadMatrixd(toGLMatrix);

        glMatrixMode(GL_MODELVIEW);
        // Loading the calculated matrix from OpenCV rotation matrix and vector
        glLoadMatrixd(toGLMatrix);

You're loading the matrix two times here. That doesn't make sense. It would transform the vertices as

v' = M M v = M² v

Definitely not what you want.

The matrix delivered by OpenCV combines projection and modelview. Ideally you wouldn't use fixed function OpenGL, but use a vertex shader for this. This would make things clearer.

For a simple drop in application, load the matrix from OpenCV just into modelview and make projection a identity transform.

If you want it to be correct, separate the matrix from OpenCV into two parts: A orthonormal modelview part and a matching projection one, with the x and y components of the Z column being zero. Let C be the matrix from OpenCV. For this solve the system of equations:

C = P M

P.zx = 0
P.zy = 0
P.zz =/= 0
P.zw =/= 0

M.x · M.y = 0
M.y · M.z = 0
M.z · M.x = 0

M.xw = 0
M.yw = 0
M.zw = 0
M.ww = 1

| M.x | = 1
| M.y | = 1
| M.z | = 1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文