我想知道如何将cv :: Mat绘制到QGLWidget中。我找到了here方法并试图实现它。但是我的小部件是黑色的。
这是我的小部件的代码:
h file
#ifndef GLVIEWER_H
#define GLVIEWER_H
#include <QtOpenGL/QGLWidget>
#include <QtOpenGL/QtOpenGL>
#include <opencv2/core/core.hpp>
class GLViewer : public QGLWidget {
Q_OBJECT
public:
GLViewer(QWidget *parent = NULL);
void setNewFrame(cv::Mat newframe);
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
cv::Mat frame;
};
#endif // GLVIEWER_H
cpp文件
#include "glviewer.h"
#include <iostream>
#include <QtGui/QMouseEvent>
GLViewer::GLViewer(QWidget *parent) : QGLWidget(parent) {
setMouseTracking(true);
frame = cv::Mat::ones(25, 50, CV_8UC3) * 255;
}
void GLViewer::setNewFrame(cv::Mat newframe) {
frame = newframe;
paintGL();
}
void GLViewer::initializeGL() {
std::cout << "initializeGL" << std::endl;
glViewport(0,0,this->width(), this->height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-this->width()/2, this->width()/2, this->height()/2, -this->height()/2, -1, 1);
}
void GLViewer::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
// glMatrixMode(GL_PROJECTION);
// glLoadIdentity();
// gluOrtho2D(0, w, 0, h); // set origin to bottom left corner
// glMatrixMode(GL_MODELVIEW);
// glLoadIdentity();
}
void GLViewer::paintGL() {
//std::cout << "paint" << std::endl;
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1.0f, 0, 0, 1.0f);
glDrawPixels(frame.rows, frame.cols,
GL_RGB,
GL_UNSIGNED_BYTE,
frame.data);
}
因为我用'cv :: Mat :: ones(25,50,CV_8UC3)* 255初始化了cv :: Mat;'我希望看到一个小蓝色矩形但是......没有发生任何事情,全黑小工具
任何人都可以指出我的解决方案吗?
我试图将背景更改为红色,现在事情是红色的..这是输出:
背景是正确的但是蓝色矩形..即使它看起来像一个矩形也不是蓝色..发生了什么?我试图反转frame.cols和frame.cols,GL_BGR而不是GL_RGB和一些数据类型的随机试验(GL_UNSIGNED_SHORT等),但没有任何结果得到更好的结果..
答案 0 :(得分:2)
您的resizeGL()
正在消除您在initializeGL()
,特别是glOrtho()
电话中所做的矩阵设置。
尝试将矩阵设置移至paintGL()
:
...
void GLViewer::initializeGL()
{
std::cout << "initializeGL" << std::endl;
glViewport(0,0,width(), height());
}
void GLViewer::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void GLViewer::paintGL() {
std::cout << "paint" << std::endl;
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-width()/2.0, width()/2.0, height()/2.0, -height()/2.0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRasterPos2i(width()/2.0,-height()/2.0);
// also try glRasterPos2i(0,0)
glPixelZoom(-1.0f,-1.0f);
glDrawPixels
(
frame.rows, frame.cols,
GL_RGB,
GL_UNSIGNED_BYTE,
frame.data
);
}
...
编辑:尝试在glPixelStore( GL_UNPACK_ALIGNMENT, 1 )
来电之前发出glDrawPixels()
。或者切换为GL_RGBA
和四分量cv::Mat
格式。
答案 1 :(得分:2)
glDrawPixels
不是明智的选择。在OpenGL中,2D像素绘图速度惊人。你真正想要做的是将矩阵加载到纹理中,然后绘制一个带有纹理的图元。
但是对于您的简单用例:
我建议您使用QGLWidget,但仍然需要QPainter来绘制内容。它将完全加速,但你不必处理所有这些转换等等。!
代码相当简单。看一下: https://sourceforge.net/p/gerbil/svn/HEAD/tree/trunk/gerbil-gui/scaledview.cpp (自动缩放内容的小部件示例)
要从Mat转换为QImage,请参阅: https://sourceforge.net/p/gerbil/svn/HEAD/tree/trunk/common/qtopencv.cpp
转换QImage&lt; - &gt; QPixmap可以通过从另一个构造一个来隐含地完成。请注意,它基本上只将图像数据存储在图形卡上作为纹理。
转换cv :: Mat到QImage是一个“冗余”数据副本。然而它真的可以忽略不计,试试吧!