4.27 How to read a frame buffer of OpenGL and convert it to cv::Mat of OpenCV?

The following BlurredMaterializedSpheres is a very simple example to draw some materializes shepres on an OpenGLView and to captute the pixel data of the OpenGL frame buffer of the view, and display a blurred cv::Mat image created from the captured cv::Mat image on an OpenCVScrolledImageView.





/*
 * BlurredMaterializedShperes.cpp 
 * Copyright (c) 2017 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */

#include <sol/StringT.h>
#include <sol/PushButton.h>

#include <sol/opengl/OpenGLMainView.h>
#include <sol/opengl/OpenGLView.h>
#include <sol/opengl/OpenGLGC.h>
#include <sol/opengl/OpenGLTexture2D.h>
#include <sol/opengl/OpenGLLight.h>
#include <sol/opengl/OpenGLMaterial.h>
#include <sol/opengl/OpenGLSolidSphere.h>
#include <sol/opengl/OpenGLWireSphere.h>

#include <sol/opencv/OpenCVImageInfo.h>
#include <sol/opencv/OpenCVScrolledImageView.h>
#include <sol/opencv/OpenCVImageFileReader.h>


namespace SOL {

class MainView :public OpenGLMainView {
public:

private:
  //Inner OpenGLView class starts.
  class SimpleGLView: public OpenGLView {
  private:
    static const int        SPHERES=4;
    SmartPtr<OpenGLGC>      gc;
    SmartPtr<OpenGLGeometry>  sphere[SPHERES];
    float                    angle;
 
  public:
    virtual void display()
    {
      if (gc == NULL) {
        return;
      }
      
      if (sphere[0]) {
        setPerspective();

        gc->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        gc->lookAt(4.0, 8.0, 12.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

        gc->clearColor(0.0, 0.0, 0.0, 1.0);
        gc->enable(GL_CULL_FACE); 
        gc->enable(GL_LIGHTING);

        OpenGLLight light(GL_LIGHT0);
        GLfloat lightPosition[] = {10, 10, 10, 1.0};  
        light.position(lightPosition);

        for (int i = 0; i<SPHERES; i++) {
          gc->pushMatrix();
          gc->rotate(angle, 0.0f, 1.0f, 0.0f);
          sphere[i]->draw(gc, -2.0f+1.3f*i, 0.5f,  0.0f+ 0.3f*i);
          gc->popMatrix();
        }
      }
    }
  
    cv::Mat capture()
    {
      int w, h;
      getSize(w, h);
      
      w = (w/8)*8;

      glReadBuffer(GL_FRONT);
      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

      unsigned char* pixels = new unsigned char[3 * w * h];
      glReadPixels(0, 0, w, h, GL_BGR, GL_UNSIGNED_BYTE, pixels);
        
      return cv::Mat(h, w, CV_8UC3, pixels);
    }

    virtual void resize(int w, int h)
    {
      if (w == 0 || h == 0) {
        return;
      }
      setPerspective();
    }

    virtual void initialize()
    {
      gc = new OpenGLGC();
      
      Color4  black         = { 0.0, 0.0, 0.0, 1.0 };
      Color4  ambient       = { 0.5, 0.5, 0.5, 1.0 };
      Color4  diffuse       = { 0.2, 0.4, 0.8, 1.0 };
      Color4  specular      = { 1.0, 1.0, 1.0, 1.0 };
      Color4  emission      = { 0.8, 0.0, 0.0, 0.0 };
      GLfloat lowShining    = { 10.0 };
      GLfloat highShining   = {100.0 };

      OpenGLMateria mat1(GL_FRONT, ambient, diffuse, specular, emission, lowShining);
      OpenGLMateria mat2(GL_FRONT, black,   diffuse, specular, emission, lowShining);
      OpenGLMateria mat3(GL_FRONT, black,   diffuse, black,    emission, highShining);
      OpenGLMateria mat4(GL_FRONT, ambient, diffuse, specular, black,    highShining);
      OpenGLMateria materias[] = {mat1, mat2, mat3, mat4};
      for (int i = 0; i<SPHERES; i++) {
        if (i%2 ==0) {
          sphere[i] = new OpenGLWireSphere(materias[i], 0.5f,  40, 40);
        } else {
          sphere[i] = new OpenGLSolidSphere(materias[i], 0.5f,  40, 40);
        }
      }
    }

  public:
    SimpleGLView(View* parent, const char* name, Args& args)
    :OpenGLView(parent, name, args),
    angle(100.0f)
    {
    } 
  };

  //Inner OpenCVScrolledImageView class start
  class SimpleCVView: public OpenCVScrolledImageView {
  private:
    cv::Mat        originalImage; 
    cv::Mat        blurredImage;

  public:
    SimpleCVView(View* parent, const char* name, Args& args)
    :OpenCVScrolledImageView(parent, name, args)
    {
    } 
    
    void blur(cv::Mat& originalImage)
    {
      int ksize = 13;
      int sigma = 10;
      ksize = (ksize/2)*2 + 1;
      blurredImage = cv::Mat::zeros(originalImage.size(), 
                                originalImage.type() );
      //Blur operation is applied to the original image.
      cv::GaussianBlur(originalImage, blurredImage, cv::Size(ksize, ksize), 
            (double)sigma, //sigmaX, 
            (double)sigma); //sigmaY 
    }

    void setMat(cv::Mat mat, bool flip=false)
    {
      try {
        cv::Mat flipped = mat;
        
        if (flip) {;
          cv::flip(mat, flipped, 0); 
          originalImage = flipped;
        }
        originalImage = flipped;

        blur(originalImage);
        
        setScaledImage(blurredImage, 80);

      } catch (SOL::Exception& ex) {
        caught(ex);
      }
    }    
  };
  //Inner class ends.
    
private:

  SmartPtr<SimpleGLView>  glView;
  SmartPtr<SimpleCVView>  cvView;
  SmartPtr<PushButton>    captureButton;
 
  void resize(int w, int h)
  {
    int CP_WIDTH = 100;
    int ww = (w - CP_WIDTH)/2;
    if (glView && cvView && captureButton) { 
      glView -> reshape(0, 0, ww-1, h);
      cvView -> reshape(ww+1, 0, ww-2, h);
      captureButton -> reshape(w-CP_WIDTH+2, 0,CP_WIDTH-4, 30);
    }
  }

  void captureImage(Action& action)
  {
    cv::Mat image =  glView->capture();
    cvView->setMat(image, true);
  }

public:
  MainView(Application& applet, const char* name, Args& args)
  :OpenGLMainView(applet, name, args)
  {
    Args ar;    

    ar.reset();
    glView = new SimpleGLView(this, "", ar);

    ar.reset();
    cvView = new SimpleCVView(this, "", ar);
          
    ar.reset();
    captureButton = new PushButton(this, "Capture", ar);
    captureButton->addCallback(XmNactivateCallback, this,
       (Callback)&MainView::captureImage, NULL);
    
    postResizeRequest();    
  }
};
}

//
void Main(int argc, char** argv) 
{
  try {
    glutInit(&argc, argv);

    const char*  name = appName(argv[0]);
    Application applet(name, argc, argv);

    Args args;
    args.set(XmNwidth, 900);
    args.set(XmNheight, 400);
    MainView view(applet, name, args);
    view.realize();
    applet.run();
    
  } catch (SOL::Exception& ex) {
    caught(ex);
  }
}

Last modified: 18 Sep. 2017

Copyright (c) 2017 Antillia.com ALL RIGHTS RESERVED.