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 :

affichage de beaucoup d'images


Sujet :

Qt

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 171
    Points : 75
    Points
    75
    Par défaut affichage de beaucoup d'images
    Bonjour,

    je suis en train de dévellopez une interface graphique pour contrôler des caméras (2 en ce moment) et une des principales fonctions du programme consiste à afficher les images envoyées par les caméras. Sur mon interface graphique j'ai donc 3 zones d'affichages (ie trois QLabel) : une pour chaque caméra et une commune aux deux (chaque caméra ne filme qu'une couleur).
    Les images sont acquises dans deux threads secondaires (un thread par caméra) et sont ensuite émises vers leur affichage respectif.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    //connection vers la zone d'affichage comune
    connect(cameraS[i], SIGNAL(hotImageC(QImage,int)), mergeScreen, SLOT(newImage(QImage,int)), Qt::UniqueConnection);
    //connection vers la zone d'affichage spécifique
    connect (myCamera, SIGNAL(hotImage(const QPixmap &)), this, SLOT(newImage(const QPixmap &)), Qt::UniqueConnection);
    j'ai utilisé Qt::UniqueConnection pour éviter l'engorgement de l'event loop.
    mais même malgré cela quand les deux caméras filment en même temps l'affichage finit (entre 1s et 30 sec de fluidité) et la mémoire utilisée par le programme monte en flèche.....

    Il faut savoir que chaque images a une résolution de 496*658 sen 16 bit. et que le frame rate est d'environ 17 à 24 fps.

    merci d'avance pour votre aide

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Salut.
    Il n'y as pas assez de code pour t'aider.
    Sinon, QLabel n'est absolument pas adpater à ton besion. Il faut mieux faire ton propre paint event.
    Sinon, Y as normalement une solution avec QtMultimedia, mais je ne connait pas
    http://qt.developpez.com/doc/latest/qtmultimedia/

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2004
    Messages : 33
    Points : 26
    Points
    26
    Par défaut
    Hello,


    Personellement j'ai pu tester 4 cameras à 30fps sans soucis particuliers. Les threads d'acquisitions emettant des signiaux via Qt::QueuedConnection à des Qlabel pour le display.

    Au niveau mémoire, cela fait plutôt penser à un leak dans ton code. Est-ce que la mémoire allouée dans thread d'acquisition pour récupérer les images est bin désallouée?

    ++

    Frantz

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 171
    Points : 75
    Points
    75
    Par défaut
    merci pour vos réponses.

    voila le code de la thread d'acquisition :
    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
    void camera::run()
    {
        QPixmap imPix(resX, resY);
        QImage image(resX, resY, QImage::Format_RGB16);
        QImage imageC(resX, resY, QImage::Format_ARGB32_Premultiplied);
        status = 20072;
        long first, last, pMin, pMax;
     
            while (status == 20072)
            {
     
                erreur = WaitForAcquisitionByHandle(handle);
                mutex->lock();
                SetCurrentCamera(handle);
     
    //récupération des données de l'image : imdata[resX*reY] 
     
                erreur = GetMostRecentImage16(imData, resX*resY);
                mutex->unlock();
     
                if (erreur == 20002)
                {
                    if (nbIm%50 == 0 || nbIm == 1)
                    {
                        normHisto (imData, resX, resY, &pMin, &pMax);
                    }
                    for (int j = 0 ; j<resY ; ++j )
                    {
                        for (int i = 0; i<resX ; ++i)
                        {
                            value = imData[j*resX+i];
                            value = 255*(value-pMin);
                            value = value/(pMax-pMin);
    //image noir et blanc
                            image.setPixel(i, j, qRgb(value, value, value));
    //selon la camera (identity) l'image est soit rouge soit bleu
                            if (identity == 0)
                            {
                                imageC.setPixel(i, j, qRgb(value, 0, 0));
                            }
                            else
                            {
                                imageC.setPixel(i, j, qRgb(0, value, 0));
                            }
                        }
                    }
                    imPix = QPixmap::fromImage(image);
                    emit hotImage (imPix);
                    if (mergeOn == true)
                    {
    //émission de l'image de couleur
                        emit hotImageC (imageC, identity);
                    }
                }
                mutex->lock();
                SetCurrentCamera(handle);
                GetStatus(&status);
                mutex->unlock();
            }
        }
    }
    la définition des signaux émis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	void hotImage (const QPixmap &im);
            void hotImageC (const QImage &im, int identity);
    les deux affichages respectifs des deux caméras sont trés simple : l'image émises pas le thread est transmises à un slot qui l'affiche dans un Qlabel

    pour la zone commune voici le slot auquel est connecté le signal hotImageC
    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
     
    void mergeWindow::newImage(QImage im, int color)
    {
    //les Qimages redImage greenImage et merge sont instanciées dans le //constructeur
        switch (color)
        {
        case 0 :
            redImage->fill (Qt::transparent);
            *redImage = im;
     
            break;
        case 1 :
            greenImage->fill (Qt::transparent);
            *greenImage = im;
     
            break;
        }
        mergeImage->fill(Qt::transparent);
        painter->begin(mergeImage);
            painter->setCompositionMode(QPainter::CompositionMode_DestinationOver);
        painter->drawImage(0, 0, *greenImage);
        painter->setCompositionMode(QPainter::CompositionMode_Plus);
        painter->drawImage(0, 0, *redImage);
     
        painter->end();
     
        screen->setPixmap(QPixmap::fromImage(*mergeImage));
     
    }
    @trop_wizz : j'ai aussi pensé à une fuite de mémoire mais si je supprime l'écran commun, je n'ai aucun problème. Et plus bizzarement si dans mergeWindow::newImage() je supprime juste l'affichage, ie les variables sont toujours transmises, les images mélangées etc l'augmentation de mémoire n'apparait qu'après un temps long d'acquisition : environ une minute.

    @yan merci pour le QtMultimedia je vais regarder ça.

  5. #5
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Qpixmap ne peut pas être utilisé dans un thread car il est basé sur les ressource de la GDI comme les widgets.
    Au lieu de faire des lock et unlock, regarde QMutexLocker
    et
    http://qt.developpez.com/faq/?page=T...pulation-mutex

    Sinon je n'ai rien vue qui pourrai provoquer une fuite mémoire.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 171
    Points : 75
    Points
    75
    Par défaut
    quand les images ne sont émises que vers l'écran commun, et sans être mélangées, l'affichage reste (relativement) fluide et la mémoire est stable. même topo quand les images sont envoyées sur leur écran respectif et pas sur le commun. je dois surcharger quelque chose.... mais je ne sais pas quoi.

    Par contre le mutex que j'utilise dans les threads d'acquisition est commun au deux caméras afin que les intructions ne soient pas mélangées (un boucle d'acquisition doit pouvoir bloquer momentanément l'autre). Seuleument pour qu'il soit partagé, le mutex est instancié dans la thread principale (seul un pointeur est passé thread secondaire). Ainsi quand je le lock (avec QMutexLocker merci yan ) je dois interrompre aussi l'exécution du main thread, je me trompe? Du coup la thread principale serait interompu trop souvent et ne pourrait plus suivre..... c'est crédible selon vous?
    Bonne soirée!

  7. #7
    Rédacteur

    Inscrit en
    Novembre 2006
    Messages
    1 272
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 272
    Points : 1 672
    Points
    1 672
    Par défaut
    Citation Envoyé par Zhitoune Voir le message
    Par contre le mutex que j'utilise dans les threads d'acquisition est commun au deux caméras afin que les intructions ne soient pas mélangées (un boucle d'acquisition doit pouvoir bloquer momentanément l'autre). Seuleument pour qu'il soit partagé, le mutex est instancié dans la thread principale (seul un pointeur est passé thread secondaire). Ainsi quand je le lock (avec QMutexLocker merci yan ) je dois interrompre aussi l'exécution du main thread, je me trompe? Du coup la thread principale serait interompu trop souvent et ne pourrait plus suivre..... c'est crédible selon vous?
    Bonne soirée!
    Normalement non a moins que le thread principal attend aussi la liberation de ce mutex... Mais je ne pense pas, je ne vois pas pourquoi tu ferais ça.

  8. #8
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Zhitoune Voir le message
    Ainsi quand je le lock (avec QMutexLocker merci yan ) je dois interrompre aussi l'exécution du main thread, je me trompe?
    oui. Un mutex n'as pas d'appartenance. DOnc si le thread principale ne fait pas de lock, il n'y as aucune raison qu'il se bloque.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 171
    Points : 75
    Points
    75
    Par défaut
    Merci pour vos réponses.

    donc le mutex n'est pas en cause... dommage.

    est-ce que l'émission des images pourrait être en cause : je transmets une référence sur une QImage donc si je ne me trompe pas elle n'es copié nulle part, sauf si (partage implicite oblige) la boucle d'acquisition recommence à écrire sur la QImage et là il ya une vrai duplication de l'image d'où l'augmentation de la mémoire. l'effet fait boule de neige etc etc...
    c'est crédible selon vous?

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

    Informations forums :
    Inscription : Mai 2006
    Messages : 164
    Points : 161
    Points
    161
    Par défaut
    juste une idée comme ça, as-tu essayé de transmettre directement un pointeur sur QImage dans tes emit() ?

    je ne sais pas si ça change quelquechose pour les signaux / slots Qt

  11. #11
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par atomicJo Voir le message
    juste une idée comme ça, as-tu essayé de transmettre directement un pointeur sur QImage dans tes emit() ?

    je ne sais pas si ça change quelquechose pour les signaux / slots Qt
    a eviter.
    Car l'appel du slot n'est pas directe. Donc tu peut te retrouver avec un pointeur invalide si la QImage est détruite avant l'appel du slot.
    De plus, QImage utilise le COW ce qui veut dire que la copie ne coutera rien dans ton cas
    http://qt.developpez.com/faq/?page=g...optimise-copie

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 171
    Points : 75
    Points
    75
    Par défaut
    J'ai changé la prioritée des threads d'acquisition sur LowestPriority et tout marche correctement maintenant.
    Merci pour votre aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB6] Affichage centré d'une image
    Par Sophie2097 dans le forum VB 6 et antérieur
    Réponses: 16
    Dernier message: 12/05/2006, 15h28
  2. Erreur pour l'affichage aléatoire d'une image
    Par bellebiquette dans le forum Langage
    Réponses: 3
    Dernier message: 21/04/2006, 23h45
  3. [Conception] affichage aleatoire d'une image
    Par bellebiquette dans le forum PHP & Base de données
    Réponses: 18
    Dernier message: 24/02/2006, 23h58
  4. [WD5.5] Mode d'affichage d'un champs Image
    Par Herve_63 dans le forum WinDev
    Réponses: 2
    Dernier message: 17/02/2006, 15h06
  5. [Tableaux] Ajouter l'affichage dynamique d'une image
    Par leloup84 dans le forum Langage
    Réponses: 3
    Dernier message: 16/02/2006, 10h14

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