qt - 将 OpenCV IplImage 渲染到 QGLWidget

标签 qt opengl opencv qglwidget

我在渲染 OpenGL 场景时遇到问题。

背景是我想在预览窗口中显示来自视频捕获设备的帧。我正在使用 OpenCV 和 Qt。为了测试我正在从我的 MacBook 网络摄像头捕获。预览窗口为 200x200,捕获的帧为 640x480。我不担心保持纵横比。

来自 IplImage 结构的其他信息:

  • Debug: channels: 3
  • Debug: depth: 8
  • Debug: dataOrder: 0
  • Debug: align: 4. Alignment of image rows 4 or 8
  • Debug: origin: 0. 0=top left, 1=bottom left
  • Debug: widthStep: 2560.
  • Debug: colorModel: RGB

所以这张图片显示了当前的状态。

Current capture http://clinsoftsolutions.com/fgvc4.png

我开始使用 glDrawPixels,但效果不佳。我得到了输出,但没有缩放。

目前我正在尝试使用纹理,这是我用于 GL 交互的代码

void VideoCaptureWidget::initializeGL()
{
    qDebug("initializeGL called");
    qglClearColor(QColor::fromRgb(0,0,0));      // set clear colur to black
    glDisable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, this->width(), this->height(), 0.0f, 0.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_TEXTURE_2D);
    glGenTextures(3, &m_texture);
    glBindTexture(GL_TEXTURE_2D, m_texture);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glBindTexture(GL_TEXTURE_2D,m_texture);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,this->width(),this->height(),0,GL_BGR,GL_UNSIGNED_BYTE,NULL);
    glDisable(GL_TEXTURE_2D);
}


void VideoCaptureWidget::paintGL()
{    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_DEPTH_TEST);

    glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0f,this->width(),this->height(),0.0f,0.0f,1.0f);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,m_texture);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,m_image->width,m_image->height,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,m_image->imageData);
    glBegin(GL_QUADS);
    glTexCoord2i(0,1); glVertex2i(0,this->height());
    glTexCoord2i(0,0); glVertex2i(0,0);
    glTexCoord2i(1,0); glVertex2i(this->width(),0);
    glTexCoord2i(1,1); glVertex2i(this->width(),this->height());
    glEnd();
    glFlush();

}

void VideoCaptureWidget::resizeGL(int width,int height)
{
    qDebug("reszieGL called");

    glViewport(0,0,this->width(),this->height());
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0f,this->width(),this->height(),0.0f,0.0f,1.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
 }

图像是在定时器槽中捕获的,m_image 是一个_IplImage 指针

void VideoCaptureWidget::_captureFrame() {
    m_image = cvQueryFrame(m_capture);
    if(!m_image) {
        qDebug("VideoCaptureWidget::_captureFrame(): Error capturing a frame...");
    }

    //Draw the scene
    glDraw();
}

我真的希望有人以前见过这种扭曲的图像并知道问题出在哪里。

最佳答案

另一种方法是将 BGR 帧转换为 RGBA,然后使用 glTexImage2D() 将它们上传到 GPU。我在my repository上传了一个完整的demo , 检查 cvQTcameraGL .

相关代码如下:

// Note: trying to retrieve more frames than the camera can give you
// will make the output video blink a lot.
cv_capture >> cv_frame;
if (cv_frame.empty())
{
    std::cout << "GLWidget::paintGL: !!! Failed to retrieve frame" << std::endl;
    return;
}
cv::cvtColor(cv_frame, cv_frame, CV_BGR2RGBA);

glEnable(GL_TEXTURE_RECTANGLE_ARB);

// Typical texture generation using data from the bitmap
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texture);

// Transfer image data to the GPU
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0,
             GL_RGBA, cv_frame.cols, cv_frame.rows, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, cv_frame.data);
if (glGetError() != GL_NO_ERROR)
{
    std::cout << "GLWidget::paintGL: !!! Failed glTexImage2D" << std::endl;
}

关于qt - 将 OpenCV IplImage 渲染到 QGLWidget,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15705627/

相关文章:

c++ - Meego Nokia N950 是否支持 C++ QML 绑定(bind)?

c++ - Qt/C++ 中的 ComboBox 默认值

c++ - 在布局中的 QLabel 上设置文本,不会调整大小

javascript - 那个过滤器叫什么?

python - 为什么cv2.imwrite方法为mnist测试图像数据集写一个黑色正方形?

c++ - QHBoxLayout 小部件对齐仅影响第一个小部件

c++ - 如何使用opengl使点闪烁?

opengl - GLSL 顶点着色器查找表问题

opencv - 感兴趣区域和霍夫线检测可确保扭曲线的准确性

c++ - 从 imshow() 和 namedWindow() 捕获 opencv 异常