IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

[OpenGL] Histogramme 3D d'une image


Sujet :

Qt

  1. #1
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut [OpenGL] Histogramme 3D d'une image
    Bonjour à tous,

    Je me suis lancé dans l'élaboration d'un petit projet mêlant Qt et OpenGL.
    Pour cela, je suis parti de l'exemple Hello GL de Qt5.

    Le but étant de lire une image et de représenter un histogramme en fonction de la couleur des pixels.

    Plus on tend vers le rouge et plus le pixel sera haut, plus il est bleu plus il est bas.

    Jusqu'à là pas de problème, j'arrive à afficher mon histogramme avec les axes XYZ en (0,0,0).

    Mais j'ai quelque soucis d'affichage :

    1- comme vous pouvez le voir sur le screenshot, il y a deux bandes verticale qui n'affiche que la couleur de fond.
    Si je bouge mon histogramme et qu'il traverse ces zones là, cette partie de l'histogramme n'est plus visible. Comme s'il y avait un near clip/farclip sur les bords de ma caméra...


    2-J'ai mis en place un compteur FPS, ce qui provoque à lui seul deux problèmes :
    + L'histogramme disparait mais l'axe XYZ est toujours là
    + L'affichage des FPS n'est rafraîchit que quand la fenêtre est cachée puis remise à l'avant.

    Voici mon code :
    +Les fonctions liés à OpenGL
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    void GLWidget::initializeGL()
    {
        glShadeModel(GL_SMOOTH);
        qglClearColor(m_qtPurple.dark());
        glClearDepth(1.0f);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
        glDepthFunc(GL_LEQUAL);
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        //glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glEnable(GL_MULTISAMPLE);
        static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 };
        glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
    }
    void GLWidget::paintGL()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
        glTranslatef(0.0, 0.0, -10.0);
        QMatrix4x4 projection;
        projection.perspective(30.0, 1.0*width()/height(), 1.0,10.0);
        glRotatef(m_xRot / 16.0, 1.0, 0.0, 0.0);
        glRotatef(m_yRot / 16.0, 0.0, 1.0, 0.0);
        glRotatef(m_zRot / 16.0, 0.0, 0.0, 1.0);
        //--------------------------------------
        DrawImage();
        DrawAxis();
        ComputeFPS();
    }
    void GLWidget::resizeGL(int width, int height)
    {
        int side = qMin(width, height);
        glViewport((width - side) / 2, (height - side) / 2, side+10, side+10);
     
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    /*#ifdef QT_OPENGL_ES_1
        glOrthof(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
    #else
        glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
    #endif*/
     
        //NEAR & FAR CLIP
        float nearClip = 0.1f;
        float farClip  = 100.0f;
        float yFOV	= 100.0f;
        float yMax = nearClip * tan(yFOV*M_PI/360.0f);
        float aspect = width/height;
        float xMin = -yMax * aspect;
        float xMax = yMax *aspect;
     
        glFrustum(xMin, xMax, -yMax, yMax, nearClip, farClip);
        glMatrixMode(GL_MODELVIEW);
     
        m_width = width;
        m_height = height;
    }
    + Mes fonctions
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
     
    //On compte sur une seconde le nombre de fois que l'on passe dans la fonction
    //Ca nous donne un FPS approximatif
    void GLWidget::ComputeFPS()
    {
        if(m_second == 0)
        {
            m_second = m_time.currentTime().second();
            return;
        }
        // Measure speed
        QTime  time = time.currentTime();
        m_frameCount++;
        qglColor(Qt::white);
        if ( time.second() - m_second >= 1.0 )
        {
            QString fps;
            fps.setNum(m_frameCount);
            renderText(m_width - 60, 20, fps, QFont("Arial", 12, QFont::Bold, false) );
            m_fps = fps;
            m_frameCount = 0;
            m_second += 1.0;
        }
        else
            renderText(m_width - 60, 20, m_fps, QFont("Arial", 12, QFont::Bold, false) );
    }
    //Trace les axes XYZ
    void GLWidget::DrawAxis()
    {
        glBegin(GL_LINES);
          glColor3d(1,0,0);
          glVertex3i(0,0,0);glVertex3i(0,50,0);
          glColor3d(0,1,0);
          glVertex3i(0,0,0);glVertex3i(50,0,0);
          glColor3d(0,0,1);
          glVertex3i(0,0,0);glVertex3i(0,0,50);
        glEnd();
    }
    //On ajoute les composantes RGB pour trouver la hauteur du pixel
    //La formule est bancale mais sert seulement de test provisoire
    float GLWidget::ComputeHeight(QColor rgb)
    {
        if (rgb.red() == 0 &&  rgb.green() == 0 && rgb.blue() == 0)
            return 0.0;
        float ret;
        ret = rgb.red()*4 + rgb.green() * 2 + rgb.blue();
        if (ret < 0)
            return 2.0;
        else if (ret > 1785)
            return 10.0;
        else
            return ret * 10 / 1785;
    }
    //Affiche l'image
    void GLWidget::DrawImage()
    {
        QImage Texture;
        if(!Texture.load("image.bmp"))
            return;
        Texture = Texture.scaled(75,75,Qt::KeepAspectRatio);
        glPointSize(4.0f);
        glBegin(GL_POINTS);
        glBegin(GL_LINE_STRIP);
        for (float i = 0; i<Texture.width();  i = i + 1.0)
            for(float j = 0; j<Texture.height(); j= j + 1.0)
            {
                QColor rgb = Texture.pixel(i,j);
                glColor3f(rgb.red(), rgb.green(), rgb.blue());
                glVertex3f(i, ComputeHeight(rgb), j);
            }
        glEnd();
        glEnd();
    }
    Pour le premier problème, j'ai essayé de passer de la représentation orthographique à la perspective, ça m'a permis de rallonger le farclip trop proche de base, mais n'a pas enlevé les deux barres verticales. Est ce que OpenGL ES ne pourrait pas être la cause de ce problème?

    Pour le second problème, j'ai essayé d'utiliser updateGL mais cela faisait planter mon programme, il bouclait sans fin et windows tuait mon processus.
    Pour mon histogramme qui disparaît lorsque je calcule mes FPS, je n'ai pas encore trouvé la raison...

    J'espère que vous saurez m'éclairer sur l'un de mes problèmes, je reviendrai vers vous si je trouve la réponse par moi même.
    Merci de votre aide,
    Clément.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 887
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 887
    Points : 219 339
    Points
    219 339
    Billets dans le blog
    123
    Par défaut
    Bonjour,

    Houlà, il semble qu'il y ai plein de problème.

    + L'affichage des FPS n'est rafraîchit que quand la fenêtre est cachée puis remise à l'avant.
    Il faut rajouter un QTimer, qui s'active toutes les N ms (souvent, 16 pour avoir 50 FPS), afin de forcer le réaffichage de la fenêtre (update ou repain, je ne sais plus).

    J'ai mis en place un compteur FPS, ce qui provoque à lui seul deux problèmes :
    + L'histogramme disparait mais l'axe XYZ est toujours là
    Un possible problème sur les états d'OpenGL (notamment les matrices utilisée).

    Après, mon soucis, c'est de comprendre comment vous faites votre histogramme ?
    Faites vous un rendu dans une texture pour récupérer l'image ?
    Dans la capture, que voit on, je crois avoir compris que vous rajoutiez les cadres rouges, mais que voit on au centre ?

  3. #3
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Mon premier problème est résolut, c'était le glViewport qui était mal paramétré, voici comment je l'ai modifié :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    glViewport(0, 0, width, height);

  4. #4
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Il faut rajouter un QTimer, qui s'active toutes les N ms (souvent, 16 pour avoir 50 FPS), afin de forcer le réaffichage de la fenêtre (update ou repain, je ne sais plus).
    Je n'ai pas compris le but du QTimer pour rafraîchir l'affichage...

    Citation Envoyé par LittleWhite Voir le message
    Un possible problème sur les états d'OpenGL (notamment les matrices utilisée).
    C'est à dire?

    Citation Envoyé par LittleWhite Voir le message
    Après, mon soucis, c'est de comprendre comment vous faites votre histogramme ?
    Faites vous un rendu dans une texture pour récupérer l'image ?
    Dans la capture, que voit on, je crois avoir compris que vous rajoutiez les cadres rouges, mais que voit on au centre ?
    Sur la capture d'écran j'ai rajouté les rectangle pour montrer les zones qui n'affichaient pas la 3D, j'ai réglé le problème grâce au glViewport. Pour ce qui est du reste du screenshot, au centre c'est bien évidement l'histogramme 3D de mon image. Comme je l'ai dis, je récupère chaque pixel de l'image, je calcule sa hauteur et ensuite j'affiche l'histogramme sous forme de maillage.

  5. #5
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 887
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 887
    Points : 219 339
    Points
    219 339
    Billets dans le blog
    123
    Par défaut
    Le QTimer va forcer OpenGL (et Qt) à réafficher l'image (en appelant updateGL, ou paintGL, je ne sais plus).

    OpenGL est constitué de plusieurs états (si oui ou non le depth buffer est activé, quelle est la couleur de fond, ...), si ceux la sont mal configurés, il se peut que vous ne voyez rien à l'écran).

  6. #6
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Le QTimer va forcer OpenGL (et Qt) à réafficher l'image (en appelant updateGL, ou paintGL, je ne sais plus).

    OpenGL est constitué de plusieurs états (si oui ou non le depth buffer est activé, quelle est la couleur de fond, ...), si ceux la sont mal configurés, il se peut que vous ne voyez rien à l'écran).
    J'ai un peu modifié ma fonction ComputeFPS pour forcer le rafraîchissement mais soit je m'y suis mal pris soit ça n'a pas marché...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    void GLWidget::ComputeFPS()
    {
        m_time.start();
        if(m_second == 0)
        {
            m_second = m_time.currentTime().second();
            return;
        }
        // Measure speed
        int  second = m_time.currentTime().second();
        m_frameCount++;
        qglColor(Qt::white);
        if ( second - m_second >= 1.0 )
        {
            QString fps;
            fps.setNum(m_frameCount);
            renderText(20, 20, fps, QFont("Arial", 12, QFont::Bold, false) );
            m_fps = fps;
            m_frameCount = 0;
            m_second += 1.0;
        }
        else
            renderText(20, 20, m_fps, QFont("Arial", 12, QFont::Bold, false) );
    }

  7. #7
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 887
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 887
    Points : 219 339
    Points
    219 339
    Billets dans le blog
    123
    Par défaut
    Vous avez fait un start, mais avez vous fait un connect qui va bien ?

  8. #8
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2010
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2010
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Vous avez fait un start, mais avez vous fait un connect qui va bien ?
    Non je n'avais pas mis le connect, mais maintenant j'ai une p#*:!#1 d'erreur sur mon connect :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    connect(&m_time, SIGNAL(timeout()), this, SLOT(ComputeFPS()));
    Erreur : candidate expects 3 arguments, 4 provided
    connect(&m_time, SIGNAL(timeout()), this, SLOT(ComputeFPS()));


    Sachant que j'ai bien déclaré "ComputeFPS" en tant que slot. je ne vois pas ce que j'ai fais de mal...

    Aide par pitié!

  9. #9
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 887
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 887
    Points : 219 339
    Points
    219 339
    Billets dans le blog
    123
    Par défaut
    Dans le .h, il faut rajouter Q_OBJECT après l'accolade ouvrante de la définition de votre classe.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 47
    Points : 71
    Points
    71
    Par défaut
    Le connect à 3 arguments semble être celui des sockets.

    Si l'appel ne se trouve pas dans une classe qui hérite de QObject (ce qui semble un peu bizarre, puisqu'il devrait se trouver dans le constructeur de GLWidget), vous devez qualifier complètement en utilisant "QObject::connect" au lieu de juste "connect".

Discussions similaires

  1. [Débutant] histogramme logarithmique d'une image
    Par amal1410 dans le forum Images
    Réponses: 1
    Dernier message: 16/05/2013, 20h24
  2. histogramme vertical d'une image
    Par matrix2008 dans le forum Images
    Réponses: 5
    Dernier message: 13/12/2012, 10h49
  3. histogramme cumulé d'une image
    Par arsonlupo dans le forum Images
    Réponses: 1
    Dernier message: 02/06/2009, 20h01
  4. Réponses: 4
    Dernier message: 03/05/2005, 09h03
  5. Réponses: 3
    Dernier message: 27/01/2005, 10h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo