简体   繁体   English

OpenCV IplImage *图像到OpenGL GLuint纹理

[英]OpenCV IplImage *Image to OpenGL GLuint texture

I am trying to display video on two screen at the same time using OpenGL/GLFW and OpenCV. 我试图使用OpenGL / GLFW和OpenCV同时在两个屏幕上显示视频。 When I test my code on my laptop (mid 2010 13" Macbook Pro) and an external screen the program works just fine (minus the fact the video plays at a very fast FPS - anyone who can also solve this problem would be very helpful. Also its upside down, but OpenCV can flips things just fine.) But when I move my code to a early 2008 Mac Pro and run the code the image does not seem to texture correctly. Image below: 当我在我的笔记本电脑上测试我的代码(2010年中期13“Macbook Pro)和外部屏幕时,程序工作得很好(减去视频以非常快的FPS播放的事实 - 任何能够解决这个问题的人都会非常有帮助。它也是颠倒的,但OpenCV可以轻松翻转。)但是当我将代码移到2008年初的Mac Pro并运行代码时,图像似乎没有正确的纹理。图片如下:

三个颜色通道占据不同的列

For some reason the three color records are split in different columns and the framing isn't right. 由于某种原因,三个颜色记录被分成不同的列,并且框架不正确。 This is what it should look like: 它应该是这样的:

更好的形象

The placement of the images doesn't matter that is just because of the difference in the size of the screens. 图像的放置并不重要,这仅仅是因为屏幕尺寸的差异。 I was wondering if anyone has seen this problem before and if it could simply be a problem with how I am calling glTexImage2D? 我想知道是否有人之前已经看过这个问题,如果它只是一个问题我如何调用glTexImage2D? Posted below is the code I am using. 下面发布的是我正在使用的代码。

#include <stdio.h>
#include <string.h>

#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv2/imgproc/imgproc.hpp>

#include <GLFW/glfw3.h>
#include <GLUT/glut.h>

#define VIEWPORT_WIDTH              1280
#define VIEWPORT_HEIGHT             800
#define KEY_ESCAPE                  27

CvCapture* capture;
GLFWwindow* window1;
GLFWwindow* window2;
IplImage *image;
static GLuint texName;

void initTexture(IplImage* Image);
void applyTexture(int img_width, int img_height);
void loadImage(IplImage*, GLFWwindow* window);

int main(int argc, char* argv[])
{

    if (!glfwInit())
        exit(EXIT_FAILURE);

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

    int count;
    GLFWmonitor** monitors = glfwGetMonitors(&count);
    window1 = glfwCreateWindow(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, "Simple example1", monitors[0], NULL);
    window2 = glfwCreateWindow(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, "Simple example2", monitors[1], NULL);

    capture = cvCaptureFromAVI("../VideoTexture/movie.mov");
    assert(capture);
    // Initialize OpenGL
    glfwMakeContextCurrent(window1);


    while (!glfwWindowShouldClose(window1))
    {
            image = cvQueryFrame(capture);
    if(!cvGrabFrame(capture)){              // capture a frame 
        printf("Could not grab a frame\n\7");
        exit(0);
    }


        glfwMakeContextCurrent(window1);
        loadImage(image, window1);
        glfwMakeContextCurrent(window2);
        loadImage(image, window2);

    }


    return 0;


}

void initTexture(IplImage *Image)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);
    glEnable(GL_DEPTH_TEST);

    glGenTextures(1, &texName);
    glBindTexture(GL_TEXTURE_2D, texName);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glTexImage2D(GL_TEXTURE_2D, 0, 3, Image->width, Image->height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->imageData);
}

void applyTexture(int img_width, int img_height)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    glBindTexture(GL_TEXTURE_2D, texName);
    glBegin(GL_QUADS);
    glTexCoord2f(0, 0); glVertex3f(VIEWPORT_WIDTH /2, VIEWPORT_HEIGHT/2, 0);
    glTexCoord2f(0, 1); glVertex3f(VIEWPORT_WIDTH /2, VIEWPORT_HEIGHT/2+img_height, 0);
    glTexCoord2f(1, 1); glVertex3f(VIEWPORT_WIDTH /2+img_width, VIEWPORT_HEIGHT/2+img_height, 0);
    glTexCoord2f(1, 0); glVertex3f(VIEWPORT_WIDTH /2+img_width, VIEWPORT_HEIGHT/2, 0);
    glEnd();
    glFlush();
    glDisable(GL_TEXTURE_2D);
}

void loadImage(IplImage *Image, GLFWwindow* window)
{
    initTexture(Image);
    glViewport(0, 0, VIEWPORT_WIDTH , VIEWPORT_HEIGHT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, VIEWPORT_WIDTH , 0, VIEWPORT_HEIGHT, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    applyTexture(Image->width,Image->height);
    glfwSwapBuffers(window);
    glfwPollEvents();
}

Solved: 解决了:

Adding the following two lines solved this problem. 添加以下两行解决了这个问题。

glPixelStorei (GL_UNPACK_ALIGNMENT,  Image->align);
glPixelStorei (GL_UNPACK_ROW_LENGTH, Image->widthStep / Image->nChannels);

You need to set the pixel unpack/pack alignment to 1 when you send/read RGB image to/from GL. 向GL发送/读取RGB图像时,需要将像素解包/包对齐设置为1 By default GL is going to read your image data as if each row were aligned to a 4-byte boundary, and clearly with tightly packed (8-bit) RGB that is not the case. 默认情况下,GL将读取您的图像数据,就好像每一行都与4字节边界对齐一样,并且显然是紧凑的(8位)RGB,而不是这种情况。

This should fix at least part of your problem: 这应该至少解决部分问题:

glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glTexImage2D  (GL_TEXTURE_2D, 0, 3, Image->width, Image->height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->imageData);


Update: 更新:

The IplImage data structure provides all of the fields that you need in order to do this portably: IplImage数据结构提供了所需的所有字段,以便可移植地执行此操作:

glPixelStorei (GL_UNPACK_ALIGNMENT,  Image->align);
glPixelStorei (GL_UNPACK_ROW_LENGTH, Image->widthStep / Image->nChannels);
glTexImage2D  (GL_TEXTURE_2D, 0, 3,  Image->width, Image->height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->imageData);

The fundamental issue is the same, however. 然而,根本问题是一样的。 It comes down to differences in image data alignment between the two machines. 它归结为两台机器之间图像数据对齐的差异。

As for your image being upside down, have a look at the origin field of the IplImage struct. 至于您的图像是颠倒的,请查看IplImage结构的origin字段。 You need to compensate for that yourself. 你需要自己补偿。 GL does not have the ability to flip images during pixel transfer, unfortunately. 不幸的是,GL不具备在像素传输期间翻转图像的能力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM