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 :

Problème avec QTimer


Sujet :

Qt

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 130
    Par défaut Problème avec QTimer
    Bonjour,

    j'ai un problème avec QTimer, il me fait totalement planter mon programme lorsque je l'utilise conjointement avec une autre librairie (openCV).

    j'ai déclaré dans ma classe (dérivée de QLabel avec un Q_OBJECT) un QTimer (m_timer)
    ensuite dans le démarrage de mon appli, je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    m_timer.start(100);
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(captureLoop()));
    dans captureLoop() (public slots)
    j'ai une fonction d'une autre librairie qui récupère une image
    et appelle une autre méthode de ma classe qui détecte un visage sur l'image et retourne la position du visage. La détection s'effectue via une fonction de ma seconde librairie.

    Sauf que dès qu'il arrive à la détection (la fonction de l'autre librairie en particulier : cvtColor), le programme me met un segmentation fault. Sans rentrer dans la fonction (mode debbugeur)

    Si je désactive la détection, tout fonctionne avec le Timer de Qt.

    Vous allez surement me dire : "ben le problème viens de la fonction de détection de ton autre librairie"

    Eh bien non, car si je supprime le timer de Qt et que j'appelle ma méthode manuellement, tout fonctionne (mais pas de boucle possible).

    J'ai l'impression que c'est le méta code crée par Qt pour les slots personnalisés qui pose problème...

    Voici l'erreur généré par C::B : Segmentation Fault in icvBGRx2Gray_8u_CnC1R () (C:\Test\bin\Debug\libcv200.dll)

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Par défaut
    Salut,

    "ben le problème viens de la fonction de détection de ton autre librairie"

    Non, en fait, segmentation fault veut dire que tu as un accès mémoire invalide. Et je pense que celui vient pas de QTimer, mais plutôt de l'appel successif de ta fonction de détection. En gros, je suis quasiment sûr que si dans ton constructeur tu appelles 3 fois ta fonction à la suite, tu auras la même erreur. Une de tes variables ne doit pas être correctement initialisé / écrasé entre deux appels de ta fonction (probablement une cvImage, ou ta cvCapture).

    Si tu nous mettait un peu de code, on pourrait sans doute t'aider un peu plus. Ou alors, tu peux mettre des tests sur tes variables
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if(maVariable!=0)
    //je continue
    else
    qDebug()<<"maVariable est incorrecte";
     
    //etc.
    G.

    PS :
    m_timer.start(100);
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(captureLoop()));
    Il est souvent préférable de faire le connect avant le start().

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 130
    Par défaut
    Lancement de l'application version qui marche pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int MaClasse::run()
    {
     // initialisations de capture / cascade ....
     if( capture.isOpened() )
     {
        connect(&m_timer, SIGNAL(timeout()), this, SLOT(captureLoop()));
        m_timer.start(100);
     }
      return 0;
    }
    Lancement de l'application version qui marche (une seule image car plus de boucle) mais s'affiche et plante pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int MaClasse::run()
    {
     // initialisations ....
     if( capture.isOpened() )
     {
        captureLoop();
     }
     return 0;
    }
    CaptureLoop :
    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
    void MaClasse::captureLoop()
    {
    ostringstream score_str;
    Cercle c;
    // Capture la frame on la charge dans une matrice Mat
    capture >> frame;
     
    if( frame.empty() )
    	break;
     
    flip( frame, frame_copy, 1 );
     
    if(compteur>50 || compteur<1)
    {
    	compteur=0;
    	position_pt = giveRandomposition();
    	createRandomCreature(creature);
    	creature->setPosition(position_pt, ((double)NBCASES/(double)nb_cases));
    }
    compteur++;
     
    // Detection de visage
    if( detect_faces )
    {
    	// Appel de la fonction pour détecter et afficher les visages
    c = detect_and_draw_faces(2); // c'est dans cette fonction qui ma fait planter mon programme !!!!!!!
     
    	if(collisionCercle(creature->getPtGauche(), creature->getPtDroite(), c ))
    	{
    		 creature->updateScore(score);
    		 //score++;
    		 cout << "Collision - Score : " << score << endl;
    		 position_pt = giveRandomposition();
    		 createRandomCreature(creature);
    		 creature->setPosition(position_pt, ((double)NBCASES/(double)nb_cases));
    	}
    }
     
     
    // On affiche une grille
    if( show_grid )
    	draw_grid();
     
    creature->draw(frame_copy);
    score_str.str("");
    score_str << "Score : " << score;
    putText( frame_copy, score_str.str(), Point(6,12), CV_FONT_HERSHEY_SIMPLEX, 0.40, Scalar(0, 255, 0) );
     
    QImage test = Mat2QImage(frame_copy); // convertit Mat en QImage
    this->setPixmap(QPixmap::fromImage(test));
    this->update();
    }
    Méthode de détection :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Cercle MaClasse::detect_and_draw_faces( double scale )
    {
        Point pt1, pt2, centre;
        int i;
        Cercle c1 = { 0, Point(0,0) };
        double diametre_cercle;
     
        vector<Rect> faces;
        Mat gray, smallFrame( cvRound (frame_copy.rows/scale), cvRound(frame_copy.cols/scale), CV_8UC1 );
     
        cvtColor( frame_copy, gray, CV_BGR2GRAY ); // ça plante à cette fonction !!!!!!!!!!!!!!
        resize( gray, smallFrame, smallFrame.size(), 0, 0, INTER_LINEAR );
        // ............
    }

    Toutes les variables non initialisées au début de captureLoop() sont des membres privées de ma classe.

    Le problème c'est que le segmentation fault apparait aussi en mode débugger pas à pas (donc logiquement je n'ai pas encore fait plusieurs appels successifs vu que c'est le premier passage)...

    je ne lance pas dans le constructeur mais dans une méthode que j'ai nommé run.

    Toutes les variables sont biens initialisés vu que ça fonctionne lorsque que la boucle est effectuée avec openCV au lieu de celle du QTimer.
    Comment tester des variables de type Mat (matrice openCV) dans le if ?

    Le code de détection est celui fournit dans les exemples de la librairie...

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Par défaut
    Et si tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int MaClasse::run()
    {
     // initialisations ....
     if( capture.isOpened() )
     {
        captureLoop();
        captureLoop();
        captureLoop();
        captureLoop();
     }
     return 0;
    }
    Ca marche correctement ?

    Sinon, en lisant la doc de cv:cvtColor, j'ai vu qu'il y aavait pas mal de prérequis avant d'appeler cette fonction, notamment sur la taille de l'image d'entrée et la table de conversion. http://opencv.willowgarage.com/docum...ormations.htmlJe n'ai pas pris le temps de lire, mais peut être que tu y trouveras qqchose d'intéressant.

    G.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 130
    Par défaut
    Oui ça fonctionne correctement, l'image s'affiche, pas d'erreur.

    si je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    namedWindow( "result", CV_WINDOW_AUTOSIZE);
    while(key != 'q')
    {
          captureLoop();
          key = waitKey( 10 );
    }
    Tout fonctionne (détection + affichage dans Qt), mais cela m'oblige à ouvrir une seconde fenetre (via namedWindow) de openCV qui me sert à rien. Mais qui est indispensable car sinon la fonction waitKey n'est pas utilisable...

    J'ai l'impression que c'est plutôt la mise en thread/fork de QTimer qui pose problème non ?

    EDIT : en mode debugger les images ne s'affiche pas dans les captureLoop() successif, il les affichent uniquement quand il execute app.exec();

  6. #6
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2007
    Messages
    774
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Mai 2007
    Messages : 774
    Par défaut
    Ok. Une dernière chose, dans ta fonction captureLoop(),
    est ce que tu peux remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if( frame.empty() )
    	break;
     
    // par
    if( frame.empty() ){
    qDebug()<<"empty frame";
    return;
    }
    Et ressayer avec le QTimer ?

    Sinon, QTimer n'effectue pas ta fonction dans un autre thread / autre processus, c'est différent. Ta fonction ne sera jamais effectué en parallèle. Si elle est déjà en cours et que le timer arrive au timeout, rien ne se passe.

    G.

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

Discussions similaires

  1. Problème avec QTimer
    Par crazy_inf dans le forum Qt
    Réponses: 1
    Dernier message: 06/04/2010, 10h51
  2. [QThread] Problème avec QTimer et QThread
    Par scary dans le forum Multithreading
    Réponses: 7
    Dernier message: 15/12/2009, 18h00
  3. Qt Problème avec un QTimer
    Par U118gs dans le forum Qt
    Réponses: 3
    Dernier message: 22/08/2008, 09h28
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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