OpenGL рендерится в мат OpenCV в качестве текстуры и повторно использует его в OpenCV - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть мат OpenCV, который я хочу визуализировать с помощью OpenGL.Поэтому я пытаюсь загрузить мат openCV как текстуру с помощью кода, который я нашел в сети, и выполнить рендеринг в эту текстуру:

void BindCVMat2GLTexture(cv::Mat& image, GLuint& imageTexture)
{
    if (image.empty()) {
        std::cout << "image empty" << std::endl;
    }
    else {
        glEnable(GL_TEXTURE_2D);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glGenTextures(1, &imageTexture);
        glBindTexture(GL_TEXTURE_2D, imageTexture);

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

        // Set texture clamping method
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

        cv::cvtColor(image, image, CV_RGB2BGR);

        glTexImage2D(GL_TEXTURE_2D,         // Type of texture
            0,                   // Pyramid level (for mip-mapping) - 0 is the top level
            GL_RGB,              // Internal colour format to convert to
            image.cols,          // Image width  i.e. 640 for Kinect in standard mode
            image.rows,          // Image height i.e. 480 for Kinect in standard mode
            0,                   // Border width in pixels (can either be 1 or 0)
            GL_RGB,              // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
            GL_UNSIGNED_BYTE,    // Image data type
            image.ptr());        // The actual image data itself
            //NULL);
    }
}

Затем я создаю FBO:

//init the texture
    GLuint imageTexture;
    BindCVMat2GLTexture(target, imageTexture);

    //init the frame buffer
    GLuint fbo = 0;
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    // Set "renderedTexture" as our colour attachement #0
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, imageTexture, 0);

Затем язвоню:

glViewport(0, 0, target.cols, target.rows);
MyDraw();

После этого звонка я использую другую функцию, которую я нашел, чтобы скопировать данные текстуры обратно в мат openCV:

cv::Mat GetOcvImgFromOglImg(GLuint ogl_texture_id)
{
    glBindTexture(GL_TEXTURE_2D, ogl_texture_id);
    GLenum gl_texture_width, gl_texture_height;

    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, (GLint*)&gl_texture_width);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, (GLint*)&gl_texture_height);

    unsigned char* gl_texture_bytes = (unsigned char*)malloc(sizeof(unsigned char)*gl_texture_width*gl_texture_height * 3);
    glGetTexImage(GL_TEXTURE_2D, 0 /* mipmap level */, GL_BGR, GL_UNSIGNED_BYTE, gl_texture_bytes);

    return cv::Mat(gl_texture_height, gl_texture_width, CV_8UC3, gl_texture_bytes);
}

и вызвать это по:

target = GetOcvImgFromOglImg(imageTexture);

Также я создаю вершины треугольника и вершинный шейдер, который просто оставляет их нетронутыми, и фрагментный шейдер, который просто выделяет красный цвет.В теории, я просто хочу нарисовать красный треугольник поверх этой текстуры в качестве первого шага.Однако это не работает, так как я не получаю никакого изображения вообще.Я очень новичок в openGL, и сейчас я не могу найти какое-либо решение самостоятельно.Есть идеи, что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Итак, я решил свою проблему, которую я должен был опубликовать больше кода, чтобы облегчить ответ, добавив VertexBufferObject, который я полностью проигнорировал в этом уроке.Кроме того, и это очень важно, я использую SFML lib одновременно для отображения своих кадров.SFML также использует OpenGL для внутренних целей.Поэтому мне нужно сохранить и восстановить состояния OpenGL, которые мешают друг другу.

Я опускаю эту ссылку на случай, если у кого-то возникнут похожие проблемы: использование-opengl-совместно-с-графическим-модулем

Это добавленное состояние сохранения / восстановления до того, как я использую SFML вместе с отсутствующим кодом VAO и сбросом привязок OpenGL после того, как мой метод Draw () заставил его работать.Возможно, это не самое эффективное решение, но сейчас это способ достичь того, что мне нужно.

0 голосов
/ 01 декабря 2018

OpenCV хранит изображение в виде строк, данные которых плотно упакованы, но могут выровнять их по определенным границам байтов, может быть 4 или 8, но мы не знаем, что если вам повезет, он будет использовать 4-байтовое выравнивание, которое также по умолчанию в OpenGL.Но лучше всего установить его вручную с режимами хранения пикселей, чтобы быть в безопасности:

// use fast 4-byte alignment (default anyway) if possible glPixelStorei(GL_UNPACK_ALIGNMENT, (image.step & 3) ? 1 : 4);

//set length of one complete row in data (doesn't need to equal image.cols) glPixelStorei(GL_UNPACK_ROW_LENGTH, image.step/image.elemSize());

Тогда вы должны учитыватьза то, что OpenCV хранит изображения сверху вниз, а GL использует снизу вверх.Чтобы позаботиться об этом, выполните следующие действия:

cv::flip(image, flipped, 0); image = flipped;

OpenCV сохраняет цветные изображения в формате BGR, поэтому загрузка их в формате RGB приведет к искажению цветов.Так что используйте GL_BGR в glTexImage2D.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...