1. 程式人生 > >基於OpenGL和OpenCV的三維顯示

基於OpenGL和OpenCV的三維顯示

        最近想用OpenCV+OpenGL+QT實現三維顯示,但是一直都麼有弄出來,今天看了一篇部落格,感覺很不錯,拿來分享下。

簡而言之,這段程式碼是如何從disparity image獲得點雲資料(Point cloud)並利用OpenGL顯示出來。 如果想使用程式碼,請確認OpenGL和OpenCV都安裝在電腦中。我使用的是Visual Studio 2008...(關於如何安裝OPENGL 請參

// 

//Huang,Haiqiao coded on Dec.2009


#include "stdafx.h"
#include <iostream>

#include <stdlib.h>

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <math.h>

#include <GL/glut.h>  

using namespace std;


float imgdata[500][500];
int w=0;
int h=0;
float scalar=50;//scalar of converting pixel color to float coordinates

void renderScene(void) {
   
   glClear (GL_COLOR_BUFFER_BIT);
   glLoadIdentity();// Reset the coordinate system before modifying 
   gluLookAt (0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
   //glRotatef(-30, 0.0, 1.0, 0.0); //rotate about the x axis
   glRotatef(-180, 0.0, 0.0, 1.0); //rotate about the z axis
   glRotatef(-180, 0.0, 1.0, 0.0); //rotate about the y axis
   
   float imageCenterX=w*.5;
   float imageCenterY=h*.5;
   float x,y,z;

   glPointSize(1.0); 
   glBegin(GL_POINTS);//GL_POINTS
      for (int i=0;i<h;i++){ 
         for (int j=0;j<w;j++){
            // color interpolation 
            glColor3f(1-imgdata[i][j]/255, imgdata[i][j]/255, imgdata[i][j]/255);
            x=((float)j-imageCenterX)/scalar;
            y=((float)i-imageCenterY)/scalar;
            z=imgdata[i][j]/scalar; 
            glVertex3f(x,y,z); 
         }
      }
   glEnd();
   glFlush();
}



void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode (GL_MODELVIEW);
}


void displayDisparity(IplImage* disparity){

   double xyscale=100;
   int j=0;
   int i=0;
   CvScalar s;
  
   //accessing the image pixels
   for (i=0;i<h;i++){ 
      for (j=0;j<w;j++){
         s=cvGet2D(disparity,i,j);
         imgdata[i][j]=s.val[0];//for disparity is a grey image.
      }
   } 
}


int main(int argc, char *argv[]) 
{  
   cout << "OpenCV and OpenGL working together!"<<endl; 
   char* filename="D:\\OpenCV_stuff\\SampleImages\\tsuDisparity.bmp";
   IplImage* imgGrey = cvLoadImage(filename,0); //read image as a grey one 
   if (imgGrey==NULL){
      cout << "No valid image input."<<endl; 
      char c=getchar();
      return 1;
   } 
    w=imgGrey->width;
    h=imgGrey->height;

   displayDisparity(imgGrey); 
   cvNamedWindow("original", CV_WINDOW_AUTOSIZE );
   cvShowImage( "original", imgGrey );

   //------------------OpenGL-------------------------
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
   glutInitWindowPosition(100,100);
   glutInitWindowSize(500,500);
   glutCreateWindow("3D disparity image");
   glutDisplayFunc(renderScene);

   glutReshapeFunc (reshape);
   glutMainLoop();


   cvWaitKey(0); 
   //release opencv stuff.
   cvReleaseImage(&imgGrey);
   cvDestroyWindow("Original");
   
    return 0; 
}
在此基礎上,我又綜合了一小段程式碼,隨著滑鼠移動,可以從多個視角觀看生成的三維點雲圖(VS中還要加上預編譯頭):)
#include <iostream>
#include <stdlib.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <math.h>
#include <gl/glut.h>
using namespace std;

float imgdata[500][500];
int w=0;
int h=0;
float scalar=50;//scalar of converting pixel color to float coordinates

#define pi 3.1415926
bool mouseisdown=false;
bool loopr=false;
int mx,my;
int ry=10;
int rx=10;

void timer(int p)
{
     ry-=5;
     //marks the current window as needing to be redisplayed.
  glutPostRedisplay();
     if (loopr)
         glutTimerFunc(200,timer,0);
}


void mouse(int button, int state, int x, int y)
{
    if(button == GLUT_LEFT_BUTTON)
     {
        if(state == GLUT_DOWN)
         {
   mouseisdown=true;
   loopr=false;
  }
        else
  {
   mouseisdown=false;
  }
    }

     if (button== GLUT_RIGHT_BUTTON)
     if(state == GLUT_DOWN)
     {
        loopr=true; glutTimerFunc(200,timer,0);
     }
}

void motion(int x, int y)
{
    if(mouseisdown==true)
    {
       ry+=x-mx;
        rx+=y-my;
        mx=x;
        my=y;
        glutPostRedisplay();
    }
}

void special(int key, int x, int y)
{
    switch(key)
    {
    case GLUT_KEY_LEFT:
        ry-=5;
        glutPostRedisplay();
        break;
    case GLUT_KEY_RIGHT:
       ry+=5;
        glutPostRedisplay();
        break;
    case GLUT_KEY_UP:
        rx+=5;
        glutPostRedisplay();
        break;
    case GLUT_KEY_DOWN:
        rx-=5;
        glutPostRedisplay();
        break;
    }
}
void renderScene(void) {

       glClear (GL_COLOR_BUFFER_BIT);
       glLoadIdentity();// Reset the coordinate system before modifying
       gluLookAt (0.0, 0.0, 7.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0);
      //to invert the image
        glRotatef(ry,0,1,0);
        glRotatef(rx-180,1,0,0);

       float imageCenterX=w*.5;
       float imageCenterY=h*.5;
       float x,y,z;

       glPointSize(1.0);
       glBegin(GL_POINTS);//GL_POINTS
          for (int i=0;i<h;i++){
             for (int j=0;j<w;j++){
                // color interpolation
                glColor3f(1-imgdata[i][j]/255, imgdata[i][j]/255, imgdata[i][j]/255);//red,green,blue
                x=((float)j-imageCenterX)/scalar;
                y=((float)i-imageCenterY)/scalar;
                z=(255-imgdata[i][j])/scalar;
                glVertex3f(x,y,z);
             }
          }
       glEnd();
       glFlush();
    }

void reshape (int w, int h) {
   glViewport (0, 0, (GLsizei)w, (GLsizei)h);//set viewpoint
   glMatrixMode (GL_PROJECTION);//specify which matrix is the current matrix
   glLoadIdentity ();//replace the current matrix with the identity matrix
   gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
   glMatrixMode (GL_MODELVIEW);
}

void displayDisparity(IplImage* disparity){
   //double xyscale=100;
   int j=0;
   int i=0;
   CvScalar s;

   //accessing the image pixels
   for (i=0;i<h;i++){
      for (j=0;j<w;j++){
         s=cvGet2D(disparity,i,j);
         imgdata[i][j]=s.val[0];//for disparity is a grey image.
         //cout << imgdata[i][j]<<endl;
          }
       }
    }


    int main(int argc, char *argv[])
    {
       cout << "OpenCV and OpenGL works together!"<<endl;
       char* filename=argv[1];
       IplImage* imgGrey = cvLoadImage(filename,0); //read image as a grey one
       if (imgGrey==NULL){
          cout << "No valid image input."<<endl;
          return 1;
       }
        w=imgGrey->width;
        h=imgGrey->height;

       displayDisparity(imgGrey);
       cvNamedWindow("original", CV_WINDOW_AUTOSIZE );
       cvShowImage( "original", imgGrey );

       //------------------OpenGL-------------------------
       glutInit(&argc, argv);//initialize the GLUT library
       glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);//sets the initial display mode
       glutInitWindowPosition(100,100);
       glutInitWindowSize(500,500);
       glutCreateWindow("3D disparity image");
       glutDisplayFunc(renderScene);

       glutReshapeFunc (reshape);
       glutMouseFunc(mouse);
       glutMotionFunc(motion);
       glutSpecialFunc(special);
       glutMainLoop();


       cvWaitKey(0);
       //release opencv stuff.
       cvReleaseImage(&imgGrey);
       cvDestroyWindow("Original");

        return 0;
    }