OpenCV + OpenGL + Qt

Я разрабатываю собственное приложение дополненной реальности. Я уже обнаружил 4 угла для узоров, с которыми работаю. После обнаружения 4 углов в правильном порядке я передаю их в cvFindExtrinsicCameraParams2. Я получаю хорошие результаты для вращения и перевода объекта относительно кадра камеры. Теперь мне нужно поместить эту информацию (вектор вращения и вектор перемещения) в OpenGL, чтобы что-то нарисовать. Естественно, я использую cvRodrigues2 для получения матрицы вращения из вектора вращения. В дополнение к этому я смотрю камеру с QGlWidget таким образом:

GLWidget.h

#ifndef _GLWIDGET_H
#define _GLWIDGET_H

#include <QtOpenGL/QGLWidget>
#include <cv.h>
#include <cxcore.h>

class GLWidget : public QGLWidget {

    Q_OBJECT // must include this if you use Qt signals/slots

public:
    GLWidget(QWidget *parent = NULL);
    IplImage *img;
    void setImage(IplImage *imagen);
protected:
    void initializeGL();
    void resizeGL(int w, int h);
    void paintGL();
};

#endif  /* _GLWIDGET_H */

GLWidget.cpp

#include <QtGui/QMouseEvent>
#include "GLWidget.h"

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) {
    this->img = 0;
}

void GLWidget::initializeGL() {
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_COLOR_MATERIAL);
    glEnable(GL_BLEND);
    glEnable(GL_POLYGON_SMOOTH);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(0, 0, 0, 0);
}

void GLWidget::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
//    gluPerspective(52.0f, 1.3333f, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

}

void GLWidget::paintGL() {

    if(this->img)
    {
        glClear (GL_COLOR_BUFFER_BIT);
        glClearColor(0.0,0.0,0.0,1.0);
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        gluOrtho2D(0.0,img->width, 0.0, img->width);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        glDrawPixels(img->width,img->height,GL_RGB,GL_UNSIGNED_BYTE,img->imageData);
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
    }
}
void GLWidget::setImage(IplImage *imagen)
{
    this->img = imagen;
    this->updateGL();
}

Итак, в качестве дополнительной заметки в конструкторе моего MainWindow у меня есть что-то вроде:

windowGL = new GLWidget();
windowGL.setParent(this);

Чтобы поместить окно GL внутри MainWindow. Также я создал новую переменную внутри GLViewer.h с именем:

double modelViewMatrix[16] = {0.0};

Итак, для отображения 3D-объекта я создал внутри GLViewer такой метод:

void GlViewer::setModelView(double cameraMatrix[]){
    for(int i=0;i<16;i++){
    this->modelViewMatrix[i] = cameraMatrix[i];
    }
    this->updateGL();
}

После этого я добавляю в метод GLViewer::paintGL() что-то вроде этого после рисования изображения с помощью glDrawPixels() и, очевидно, после извлечения матриц:

    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixd(this->modelViewMatrix);
    glPushMatrix();
    glColor3f(1,0,0);

    glPushAttrib(GL_COLOR_BUFFER_BIT | GL_POLYGON_BIT | GL_ENABLE_BIT) ;
    glDisable(GL_LIGHTING) ;
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) ;
    glLineWidth(3);

    glBegin(GL_LINES) ;
            glColor3f(1,0,0) ;
            glVertex3f(0,0,0) ;
            glVertex3f(100,0,0);

            glColor3f(0,1,0) ;
            glVertex3f(0,0,0) ;
            glVertex3f(0,100,0);

            glColor3f(0,0,1) ;
            glVertex3f(0,0,0) ;
            glVertex3f(0,0,100);
    glEnd() ;

    glLineWidth(1) ;
    glPopAttrib() ;
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

Итак, для modelViewMatrix я принимаю во внимание, что я должен упорядочивать столбцы вместо строк или транспонировать, что хотите... Итак, естественно, в качестве последнего шага я вызываю созданную функцию GLWidget::setModelView после Я преобразовал внутреннюю и внешнюю камеру в массив:

windowGL.setModelView(convertedFromIntrExtr);

Однако я ничего не вижу... Я попробовал код, и я получаю этот рабочий рисунок осей, но без проекционной матрицы... Однако, когда я использую glutPerspective() (очевидно, после glMatrixMode(GL_PROJECTION)) я просто могу ничего не вижу... поэтому я не знаю, есть ли у кого-то рабочий код на Qt с дополненной реальностью без использования ARToolkit, потому что, как я уже сказал, я получаю внешние параметры камеры для своих... Итак, если у кого-то есть рабочий код, в котором вы получаете внешние параметры камеры и переводите их в проекцию openGL и матрицы просмотра моделей... хм, это было бы очень полезно... это потому, что я нашел этот пример:

http://old.uvr.gist.ac.kr/wlee/web/techReports/ar/Camera%20Models.html

Я выполнил все шаги, чтобы добиться этого преобразования между двумя моделями камер без успеха ... Я буду очень признателен, если у кого-то есть рабочий код ... спасибо !!!


person daleotar    schedule 29.05.2011    source источник
comment
Вы не должны использовать glDrawPixels, так как обычно он очень медленный. Вместо этого вы должны визуализировать текстурированный объект, а ваше изображение будет текстурой. См. opengl.org/resources/faq/technical/performance.htm. . Обязательно отключите буфер глубины (или очистите его впоследствии) при рисовании фона.   -  person ypnos    schedule 29.05.2011
comment
да, я пробовал это, на самом деле я тоже получаю хорошие результаты с текстурой ... однако дело в том, что у меня есть матрица вращения (что хорошо) и вектор перемещения (который не масштабируется), потому что openGL кажется принимать только значения GL_MODELVIEW для положения камеры между -1 и 1... Я имею в виду, что openGL принимает для оси X -1 как левую сторону и +1 для правой стороны... для оси Y принимает -1 для нижнего и +1 для верхнего... Так что дело в том, если кто-нибудь знает, как это масштабировать, потому что я не знаю   -  person daleotar    schedule 30.05.2011
comment
glMatrixMode(GL_TEXTURE); может быть одним из способов, а то, как вы объявляете свои текстурные координаты, может быть другим. То есть преобразуйте свои координаты вручную, а затем нажмите преобразованную координату.   -  person EnabrenTane    schedule 01.06.2011


Ответы (1)


Я работал с CV для оценки эго-позы на The Artvertiser, и этот материал может вскружить вам голову.

Во-первых, вам нужно выяснить, почему вы ничего не видите. Это может быть по ряду причин, наиболее вероятной из которых является инверсия направления взгляда камеры (путаница рук), поэтому геометрия фактически находится «позади» камеры в пространстве OpenGL. Но первыми отладочными вещами, которые я бы попробовал, были бы:

  • нарисуйте наземную сетку, зациклив от -1 до 1 с шагом 0,1f в измерениях x и z, рисуя glLines для определения части плоскости y (предполагая правостороннюю систему координат с y = вверх/вниз: x справа, y вверх, z указывает на вас с экрана) (таким образом вы можете почувствовать масштаб мира и ориентацию, которую дает вам матрица вашей камеры)
  • геометрия "позади" камеры (улавливайте нажатия клавиш, чтобы перемещать камеру вперед и назад, и немного перемещайтесь, чтобы посмотреть, сможете ли вы найти геометрию)
  • масштаб геометрии слишком большой/слишком маленький (перехватывайте нажатия клавиш, чтобы настроить глобальный масштаб с помощью glScalef сразу после настройки камеры)
  • геометрия за пределами плоскости отсечения (отрегулировать плоскость отсечения)

Также: это выглядит немного подозрительно: this->modelViewMatrix[i] = cameraMatrix[i]; Пробовали ли вы сначала инвертировать cameraMatrix?

person damian    schedule 10.06.2011
comment
Нет, кажется, понял, просто я предполагал, что ось Z камеры отрицательная, а положительная... - person daleotar; 20.06.2011