我在渲染OpenGL场景时遇到了麻烦。
背景是我想在预览窗口中显示来自视频捕获设备的帧。我正在使用OpenCV和Qt。并测试我从我的MacBook网络摄像头捕获。预览窗口为200x200,捕获的帧为640x480。我并不担心保持宽高比。
来自IplImage结构的其他信息:
- 调试:渠道:3
- 调试:深度:8
- Debug:dataOrder:0
- 调试:对齐:4。图像行4或8的对齐
- 调试:原点:0。0 =左上角,1 =左下角
- 调试:widthStep:2560。
- 调试: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();
}
我真的希望有人会在此之前看到这种扭曲的形象并知道问题是什么。
答案 0 :(得分:1)
另一种方法是将 BGR 帧转换为 RGBA ,然后使用glTexImage2D()
将其上传到GPU。我在my repository上传了一个完整的演示,请检查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;
}
答案 1 :(得分:0)
更多思考和查看图像我认为它必须是字节/通道对齐问题。所以更多的谷歌搜索指向了
的方向glPixelStorei with GL_UNPACK_ALIGNMENT and then also GL_UNPACK_ROW_LENGTH
现在最终的代码是:
glPixelStorei(GL_UNPACK_ALIGNMENT, 4 );
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image->widthStep/m_image->nChannels);
这需要在glTexImage2D调用之上添加。
这是图像数据的奇怪格式。但这是您从内置网络摄像头的Apple iSight获得的输出。希望这有助于其他人。