Opencv Mat для opengl с OSVR

У меня проблема с opencv и opengl. Мне нужно показать с помощью opengl изображения, полученные веб-камерой с помощью opencv, и поместить их в Razer OSVR. Но с моим текущим кодом частота кадров составляет около 1 кадра в секунду или 2 кадра в секунду, и я не знаю, что я делаю неправильно. Вот мой код, я думаю, что неправильно в draw_cube() функция.

main.cpp

// Internal Includes

#include <osvr/ClientKit/ClientKit.h>
#include <osvr/ClientKit/Display.h>
#include "SDL2Helpers.h"

#include "OpenGLCube.h"

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>


// Library/third-party includes
#include <SDL.h>
#include <SDL_opengl.h>

// Standard includes
#include <iostream>

static auto const WIDTH = 1920;
static auto const HEIGHT = 1080;

// Forward declarations of rendering functions defined below.
void render(osvr::clientkit::DisplayConfig &disp);

int main(int argc, char *argv[]) {
    namespace SDL = osvr::SDL2;

    // Open SDL
    SDL::Lib lib;

    // Use OpenGL 2.1
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);

    // Create a window
    auto window = SDL::createWindow("OSVR", SDL_WINDOWPOS_UNDEFINED,
                                SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT,
                                SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
    if (!window) {
        std::cerr << "Could not create window: " << SDL_GetError() << std::endl;
        return -1;
    }

    // Create an OpenGL context and make it current.
    SDL::GLContext glctx(window.get());

    // Turn on V-SYNC
    SDL_GL_SetSwapInterval(1);

    // Start OSVR and get OSVR display config
    osvr::clientkit::ClientContext ctx("com.osvr.example.SDLOpenGL");
    osvr::clientkit::DisplayConfig display(ctx);
    if (!display.valid()) {
        std::cerr << "\nCould not get display config (server probably not "
                 "running or not behaving), exiting."
              << std::endl;
        return -1;
    }

    std::cout << "Waiting for the display to fully start up, including "
             "receiving initial pose update..."
          << std::endl;
    while (!display.checkStartup()) {
        ctx.update();
    }
    std::cout << "OK, display startup status is good!" << std::endl;

    // Event handler
    SDL_Event e;
#ifndef __ANDROID__ // Don't want to pop up the on-screen keyboard
    SDL::TextInput textinput;
#endif
    bool quit = false;
    while (!quit) {
        // Handle all queued events
        while (SDL_PollEvent(&e)) {
            switch (e.type) {
            case SDL_QUIT:
                // Handle some system-wide quit event
                quit = true;
                break;
            case SDL_KEYDOWN:
                if (SDL_SCANCODE_ESCAPE == e.key.keysym.scancode) {
                    // Handle pressing ESC
                    quit = true;
                }
                break;
            }
            if (e.type == SDL_QUIT) {
                quit = true;
            }
        }

        // Update OSVR
        ctx.update();

        // Render
        render(display);

        // Swap buffers
        SDL_GL_SwapWindow(window.get());
    }

    return 0;
}


void render(osvr::clientkit::DisplayConfig &disp) {

    /// For each viewer, eye combination...
    disp.forEachEye([](osvr::clientkit::Eye eye) {

      /// For each display surface seen by the given eye of the given
    /// viewer...
        eye.forEachSurface([](osvr::clientkit::Surface surface) {
            auto viewport = surface.getRelativeViewport();
            glViewport(static_cast<GLint>(viewport.left),
                   static_cast<GLint>(viewport.bottom),
                   static_cast<GLsizei>(viewport.width),
                   static_cast<GLsizei>(viewport.height));

        glLoadIdentity();

   cv::VideoCapture cap(0); // open the default camera

   cv::Mat img;
   cap >> img; // get a new frame from camera

     cv::flip(img,img,0);

//resize(img, img, Size(160, 140), 0, 0, INTER_CUBIC);

draw_cube(img);
        });
    });

}

OpenGLCube.h

#ifndef INCLUDED_OpenGLVIDEO_h
#define INCLUDED_OpenGLVIDEO_h_

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;


GLuint texture;

void draw_cube(cv::Mat img) 
{

glGenTextures(1, &texture);

glBindTexture(GL_TEXTURE_2D, texture);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);


glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,img.size().width,img.size().height, 0, GL_BGR,GL_UNSIGNED_BYTE,img.data);


glEnable(GL_TEXTURE_2D);

glBegin(GL_QUADS);
glTexCoord2d(0.0, 1.0);
glVertex2d(-1,1);
glTexCoord2d(0.0, 0.0);
glVertex2d(-1,-1);
glTexCoord2d(1.0, 0.0);
glVertex2d(1,-1);
glTexCoord2d(1.0, 1.0);
glVertex2d(1,1);
glEnd();

glDisable(GL_TEXTURE_2D);

glDeleteTextures(1, &texture);
}

#endif 

Благодарю.

2 ответа

Решение

Эта строка:cv::VideoCapture cap(0); // open the default camera

Это не должно быть в основном цикле.

Спасибо за ваши ответы.

glGenTextures должен вызываться один раз, перед вашим основным циклом, так как вам не нужно создавать новую текстуру каждый кадр. Вы можете просто перезаписать предыдущие данные, используя тот же объект текстуры, используя glTexImage2D так же, как ты сейчас. Точно так же, как хорошее соглашение, glDeleteTextures должен быть вызван один раз перед выходом из программы.

Например, следующее должно быть сделано вне вашего основного цикла:

glGenTextures(1, &texture);

glBindTexture(GL_TEXTURE_2D, texture);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

Вам, конечно, нужно будет объявить texture за пределами вашего основного цикла и функции рисования и передать это в.

Другие вопросы по тегам