ja nie wiem, czy to może być przydatna teraz po 3 miesiącach. Ale mam ten sam rodzaj aplikacji, w której muszę manipulować strumieniem obrazów za pomocą OpenCV i wyświetlać go w interfejsie QT. Po dość szybkim przeszukiwaniu, natknąłem się na bardzo pomysłowe rozwiązanie. Użyj glDrawPixels OpenGL, aby narysować nieprzetworzone dane obrazu bezpośrednio w interfejsie Qt. Najlepsza część, nie musisz pisać żadnego dodatkowego kodu konwersji. Tylko podstawowy kod dla opengl do ustawienia rzutni i współrzędnych. Sprawdź kod, który ma funkcję, która przyjmuje wskaźnik IplImage * i używa tych danych do narysowania obrazu. Konieczne może być dostosowanie parametrów (szczególnie zmiennych WIDTH i HEIGHT) do wyświetlenia obrazu o określonym rozmiarze. I tak, nie wiem, jakiego systemu budowy używasz. Użyłem cmake i musiałem ustawić zależności dla OpenGL, chociaż używam biblioteki OpenGL Qt.
Zaimplementowałem klasowy QIplImage, który pochodzi z QGLWidget i zastępuje jego metodę paintGL, aby narysować dane pikseli w ramce.
//File qiplimage.h
class QIplImage : public QGLWidget
{
Q_OBJECT
public:
QIplImage(QWidget *parent = 0,char *name=0);
~QIplImage();
void paintGL();
void initializeGL();
void resizeGL(int,int);
bool drawing;
public slots:
void setImage(IplImage);
private:
Ui::QIplImage ui;
IplImage* original;
GLenum format;
GLuint texture;
QColor bgColor;
char* name;
bool hidden;
int startX,startY,endX,endY;
QList<QPointF*> slopes;
QWidget* parent;
int mouseX,mouseY;
};
//End of file qiplimage.h
//file qiplimage.cpp
#include "qiplimage.h"
#include <Globals.h>
QIplImage::QIplImage(QWidget *parent) :
QGLWidget(parent)
{
}
QIplImage::QIplImage(QWidget *parent,char* name): QGLWidget(parent)
{
ui.setupUi(this);
//This is required if you need to transmit IplImage over
// signals and slots.(That's what I am doing in my application
qRegisterMetaType<IplImage>("IplImage");
resize(384,288);
this->name=name;
this->parent=parent;
hidden=false;
bgColor= QColor::fromRgb(0xe0,0xdf,0xe0);
original=cvCreateImage(cvSize(this->width(),this->height()),IPL_DEPTH_8U,3);
cvZero(original);
switch(original->nChannels) {
case 1:
format = GL_LUMINANCE;
break;
case 2:
format = GL_LUMINANCE_ALPHA;
break;
case 3:
format = GL_BGR;
break;
default:
return;
}
drawing=false;
setMouseTracking(true);
mouseX=0;mouseY=0;
initializeGL();
}
void QIplImage::initializeGL()
{
qglClearColor(bgColor);
//glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
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,&texture);
glBindTexture(GL_TEXTURE_2D,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,texture); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,this->width(),this->height(),0,GL_BGR,GL_UNSIGNED_BYTE,NULL);
glDisable(GL_TEXTURE_2D);
}
void QIplImage::setImage(IplImage image){
original=ℑ
//cvShowImage(name,original);
updateGL();
}
void QIplImage::paintGL(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
if(!hidden){
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,texture);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,original->width,original->height,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,original->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 QIplImage::resizeGL(int width,int height){
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();
}
Nadzieję, że pomaga.
Rzecz BGR jest irytująca; teraz obejdziemy go, prosząc OpenCV o przechowywanie obrazów w formacie BGR (co odpowiada Qt's RGB, niestety Qt nie ma formatu BGR). Oznacza to, że musimy uważać na niektóre z procedur OpenCV, ale nie powinno to stanowić problemu. Zajrzę też do opcji tekstury OpenGL. Dzięki! – Calvin
FWIW, ponieważ nie wiem, czy jest wydajny: metoda QImage :: rgbSwapped przekształca RGB na BGR, zobacz http://qt-project.org/doc/qt-5.0/qtgui/qimage.html#rgbSwapped. Nauczyłem się tego z kodu źródłowego tego projektu: http://code.google.com/p/qt-opencv-multithreaded/ –
@JongBorLeem to nie RGB/BGR, ale problem polega na tym, że interfejsy API używają wyświetlacza BGRA (w tym QImage), podczas gdy API przetwarzania obrazu używa BGR - musisz przejść cały obraz i skopiować go, uzupełniając dodatkowy bajt "A" –