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
за пределами вашего основного цикла и функции рисования и передать это в.