4.26 How to map cv::Mat of OpenCV to a shape of OpenGL as a texture?

In the latest SOL9 library, we have implemented the following classe to extract the raw image data from a cv::Mat.

  • OpenGLImageInfo

  • OpenCVImageInfo

  • And we have added a new image method, which takes an OpenGLImageInfo argument, to OpenGLTextured2D class.

    The following OpenGLCVViews is a very simple example to draw an image file on OpenCVScrolledImageView in the left pane , and to map a blurred image of the sampe image file to a quad of OpenGLView as a texture in the right pane.




    
    /*
     * OpenGLCVImageViews.cpp 
     * Copyright (c) 2017 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
     */
    #include <sol/StringT.h>
    #include <sol/opengl/OpenGLMainView.h>
    #include <sol/opengl/OpenGLView.h>
    #include <sol/opengl/OpenGLGC.h>
    
    #include <sol/opengl/OpenGLTexture2D.h>
    //#include <sol/opengl/OpenGLBulletinBoard.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 OpenCVImageView class start
      class SimpleCVView: public OpenCVScrolledImageView {
    
      public:
        SimpleCVView(View* parent, const char* name, Args& args)
        :OpenCVScrolledImageView(parent, name, args)
        {
          try {
            const char* filename = (const char*)args.get(XmNimageFileName);
            int imageLoadingFlag = args.get(XmNimageLoadingFlag);
            loadImage(filename, imageLoadingFlag);
    
            rescale(60); //60%
          } catch (SOL::Exception ex) {
            caught(ex);
          }
        } 
    
        ~SimpleCVView()
        {
        }
      };
    
      //Inner OpenGLView class starts.
      class SimpleGLView: public OpenGLView {
      private:
        SmartPtr<OpenGLGC>         gc;
        SmartPtr<OpenGLTexture2D>  texture;
        bool             textured; 
        cv::Mat          blurredImage;
        StringT<char>    imageFile;
        int              imageLoadingFlag;
    
      private:
        void imageToTexture()
        {
          try {
            int width  = 0;
            int height = 0;
            OpenGLImageInfo imageInfo;
    
            OpenCVImageInfo cvImageInfo;
            cvImageInfo.getImageInfo(blurredImage, imageInfo); 
            
            texture->image(imageInfo);
    
          } catch (SOL::Exception& ex) {
            caught(ex);
          }
        }
    
      public:
        virtual void display()
        {
          if (gc == NULL) {
            return;
          }
          
          if (textured == false) {
            imageToTexture();
            textured = true;
          }
          //Set a proportional perspective.
          gc->matrixMode(GL_PROJECTION);
          gc->loadIdentity();
          gc->perspective(16.0, (double)width() / (double)height(), 0.3, 90.0); 
          gc->matrixMode(GL_MODELVIEW);
    
          gc->clearColor(1.0, 1.0, 1.0, 1.0);
          gc->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
          gc->rotate(20.0, 0.0, 0.0, 1.0);
    
          gc->begin(GL_QUADS);
          texture->coord(0.0, 0.0); 
          gc->vertex(-1.0,  1.0, 1.0);
    
          texture->coord(1.0, 0.0); 
          gc->vertex( 1.0,  1.0, 0.0);
    
          texture->coord(1.0, 1.0); 
          gc->vertex( 1.0, -1.0, 1.0);
    
          texture->coord(0.0, 1.0); 
          gc->vertex(-1.0, -1.0, 0.0);
          gc->end();
        }
     
        virtual void resize(int w, int h)
        {
          if (w == 0 || h == 0) {
            return;
          }
          if (gc) {
          gc->matrixMode(GL_PROJECTION);
          gc->loadIdentity();
          gc->ortho(-1.25, 1.25, -1.25, 1.25, 1., 20.);
    
          gc->matrixMode(GL_MODELVIEW);
          gc->loadIdentity();
          gc->lookAt(0., 0., 10., 0., 0., 0., 0., 1., 0.);
          }
        }
    
        virtual void initialize()
        {
          gc = new OpenGLGC();
          
          gc->enable(GL_DEPTH_TEST);
          gc->enable(GL_TEXTURE_2D);
          gc->rotate(20.0, 0.0, 0.0, 1.0);
    
          texture = new OpenGLTexture2D();
          
          texture->bind();
    
          texture->parameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
          texture->parameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
          texture->env(GL_TEXTURE_ENV_MODE, GL_MODULATE); 
          
        }
    
        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 
        }
    
      public:
        SimpleGLView(View* parent, const char* name, Args& args)
        :OpenGLView(parent, name, args)
        {
          textured = false;
          const char* filename = (const char*)args.get(XmNimageFileName);
          int   imageLoadingFlag = args.get(XmNimageLoadingFlag);
    
          if (filename) {
            OpenCVImageFileReader reader;
            cv::Mat image = reader.load(filename, imageLoadingFlag);
            blur(image);
          }
        } 
    
        ~SimpleGLView()
        {
        }
    
      };
      //Inner class ends.
        
    private:
      SmartPtr<SimpleGLView>  glView;
      SmartPtr<SimpleCVView>  cvView;
    
      void resize(int w, int h)
      {
        if (cvView && glView) { 
          cvView -> reshape(0, 0, w/2-1, h);
          cvView->postResizeRequest(w/2-1, h);
          glView -> reshape(w/2+1, 0, w/2-2, h);
          glView ->postResizeRequest(w/2-2, h);
        }
      }
    
    public:
      MainView(Application& applet, const char* name, Args& args)
      :OpenGLMainView(applet, name, args)
      {
        Args ar;    
    
        const char* filename = "..\\..\\opencv_app\\images\\flower.png"; 
    
        ar.reset();
        ar.set(XmNimageFileName, filename);
        ar.set(XmNimageLoadingFlag, cv::IMREAD_COLOR);
        glView = new SimpleGLView(this, "", ar);
    
        ar.reset();
        ar.set(XmNimageFileName, filename);
        ar.set(XmNimageLoadingFlag, cv::IMREAD_COLOR);
        cvView = new SimpleCVView(this, "", ar);
    
        char title[MAX_PATH];
        sprintf_s(title, CountOf(title), "%s - %s", filename, name);
        setText(title);
      }
    
      ~MainView()
      {
      }
    };
    }
    
    //
    void Main(int argc, char** argv) 
    {
      try {
        const char*  name = appName(argv[0]);
        Application applet(name, argc, argv);
    
        Args args;
        args.set(XmNwidth, 800);
        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.