2016-06-06 146 views
0

我有一个opencv和opengl的问题。我需要用opengl来显示网络摄像头用opencv检索到的图像,并将其放入Razer OSVR。但是用我目前的代码,帧率大约是1 fps或2 fps,我不知道我在做什么错误。这里是我的代码,我觉得错误的是draw_cube()函数。Opencv垫与OSVR的opengl

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 

感谢。

+1

[在本演示中](https://github.com/karlphillip/GraphicsProgramming/blob/master/cvQTcameraGL/widget.cpp)演示了如何使用OpenCV从相机中检索帧并将其发送到GPU进行渲染通过OpenGL。 – karlphillip

+0

我试过你的解决方案,并获得了相同的结果。相同的fps速度。 – user3704922

回答

0

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

它不能在主循环中。

感谢您的回复。

+0

很高兴看到我的代码帮助你,毕竟。 – karlphillip

+0

当然,再次感谢。 – user3704922

1

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以外的主回路和借鉴作用,并通过在

+0

我试过你的解决方案,并获得了相同的结果。相同的fps速度。 – user3704922