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

C++ Discussion :

Gestion de la mémoire


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2013
    Messages : 24
    Par défaut Gestion de la mémoire
    Bonsoir a tous ,
    j'utilise c++ avec raspberry pi 2 pour realiser un programme de detection faciale , j'ai trouvé un exemple ici https://github.com/Itseez/opencv/blo...facedetect.cpp

    j'ai utilisé gprof pour connaitre le temps d'execution de mon programme donc voila son output
    Nom : flat_profile1.png
Affichages : 701
Taille : 175,3 Ko

    le probleme c'est que la methode release prend environ 66% de temps d'execution et la methode detectAndDraw prend 33% cette derniere methode detecte un visage capturé depuis la caméra => le total est de 99%

    donc je cherche une méthode pour réduite un peu le temps d'execution de ces deux méthodes sachant qu'elle tourne dans une boucle infinie afin d'augmenter les performances de mon programme surtout qu'en executant le programmme sur la carte pi 2 overclocked a 1GHZ mais ca reste encore un peu lent

    j'ai voulu faire une gestion manuelle de la mémoire => voici le nouveau code (ca fait longtemps que j'ai pas programmé en C++)

    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
    for(;;)
            {
                    IplImage *iplImg = null ;
                    iplImg = new IplImage ;
                    *iplImg = cvQueryFrame( capture);
                frame = cv::cvarrToMat(iplImg);
                if( frame.empty() )
                    break;
                if( iplImg->origin == IPL_ORIGIN_TL )
                    frame.copyTo( frameCopy );
                else
                    flip( frame, frameCopy, 0 );
                delete iplImg;
                iplImg = NULL;
                detectAndDraw( frameCopy, cascade, nestedCascade, scale, tryflip );
    
                if( waitKey( 10 ) >= 0 )
                    goto _cleanup_;           // la seule methode de sortir du programme est de cliquer sur ESC
            }
    Voila pour les methode préfixée de cv ==> c'est du a l'utilisation de opencv c'est une bibliotheque qui fournit plusieurs fonctions utiles pour le traitement d'images .

    le programme se compile bien mais a l'executions j'obtiens une erreur :

    *** glibc detected *** ./facedetect : free() : invalid pointer

    c'est sur que j'ai commis une betise ici je pense merci de me l'indiquer
    bonne soirée

  2. #2
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 255
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    iplImg = new IplImage ;
    *iplImg = cvQueryFrame( capture);
    Pourquoi sur la deuxième ligne tu utilises le symbole pointeur ?
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  3. #3
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

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

    Tout d'abord, sors ton allocation de ta boucle et tu gagneras en temps d’exécution. Mais dans tout les exemple que j'ai vu tu ne dois faire aucune allocation....
    Ensuite, ne fait pas for(;;) mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    IplImage* frame;
    while(waitKey(30) != keycode.KEY_ESCAPE))
    {
         frame = cvQueryFrame(capture);
         ...
    }

  4. #4
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2013
    Messages : 24
    Par défaut
    Citation Envoyé par chrtophe Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    iplImg = new IplImage ;
    *iplImg = cvQueryFrame( capture);
    Pourquoi sur la deuxième ligne tu utilises le symbole pointeur ?
    ui c'est iplImg = cvQueryFrame( capture); mais ca n'a pas résolu le probleme

    Citation Envoyé par Astraya Voir le message
    Salut,

    Tout d'abord, sors ton allocation de ta boucle et tu gagneras en temps d’exécution. Mais dans tout les exemple que j'ai vu tu ne dois faire aucune allocation....
    Ensuite, ne fait pas for(;;) mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    IplImage* frame;
    while(waitKey(30) != keycode.KEY_ESCAPE))
    {
         frame = cvQueryFrame(capture);
         ...
    }

    merci j'ai fait ce que tu m'a suggéré mais ca n'a pas accelerer le temps d'execution .... mais ce que je veux réaliser est un management manuel de la mémoire

  5. #5
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Au départ, ce que tu veux, c’est surtout que ça fonctionne plus vite, non ?

    Là le soucis vient du fait que tu alloues vraisemblablement beaucoup trop de cv::Mat. Donc il faut regarder pourquoi, où est-ce qu’ils sont alloués, avant de dire « je veux faire une gestion manuelle ». La gestion manuelle est normalement une solution de dernier recours, on lui préfère toujours une gestion « assistée » (au moyen de RAII) qui ne présente normalement qu’un surcoût négligeable.

    Dans tous les cas, juste remplacer tes objets par des pointeurs et des news n’arrangera strictement rien à ton problème de perf, à part éventuellement introduire des bugs.

  6. #6
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Tu n'auras jamais mieux que la valeur présente dans waitKey(30). Car cette fonction fait afficher une frame toute les 30 millisecondes. Donc tu peux faire ce que tu veux dans ta boucle tu n'auras jamais moins de 30 millisecondes par frame.

  7. #7
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2013
    Messages : 24
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Au départ, ce que tu veux, c’est surtout que ça fonctionne plus vite, non ?

    Là le soucis vient du fait que tu alloues vraisemblablement beaucoup trop de cv::Mat. Donc il faut regarder pourquoi, où est-ce qu’ils sont alloués, avant de dire « je veux faire une gestion manuelle ». La gestion manuelle est normalement une solution de dernier recours, on lui préfère toujours une gestion « assistée » (au moyen de RAII) qui ne présente normalement qu’un surcoût négligeable.

    Dans tous les cas, juste remplacer tes objets par des pointeurs et des news n’arrangera strictement rien à ton problème de perf, à part éventuellement introduire des bugs.
    merci svp veuillez voir le lien que j'ai mis il s'agit du code complet ... pour resumer je ne peux pas allouer moins d'objet Mat car il s'agit d'une boucle infinie qui permet de detecter le visage depuis la camera de raspberry en straming c-ad que le traitement s'effectuer pour chaque frame capturée de la caméra ...
    la seule methode pour interrompre le programme est d'appuier sur ESC. merci

    Citation Envoyé par Astraya Voir le message
    Tu n'auras jamais mieux que la valeur présente dans waitKey(30). Car cette fonction fait afficher une frame toute les 30 millisecondes. Donc tu peux faire ce que tu veux dans ta boucle tu n'auras jamais moins de 30 millisecondes par frame.

    voulez vous dire que le temps min sera de 30ms mais dans mon cas chaque frame capturée prend environs 500ms de traitement , ce temps va augmenter puisque je désire detecter les visages de plusieurs personnes en meme temps ... donc je pense que 10ms que j'ai n'a rien d'influence puisque ca prend environs 500ms a chaque fois
    merci

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Une toute petite question au passage : Vu que tu utilises OpenCV et que tu travailles -- a priori -- en C++, pourquoi n'utilises tu pas le binding C++ de openCV, plutôt que de te faire ch...er à utiliser l'implémentation C

    En effet, il suffit de lire la documentation de OpenCV pour se rendre compte que cvQueryFrame est le pendant C de VideoCapture::read qui prend... une référence sur un objet de type Mat.

    Cela te permettrait d'avoir un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Mat mat(idth, height, type);
    videoCapture capture(/*...*/)
    for(;;){
        if(capture.read(mat){
            /* la lecture s'est bien passée */
        }else{
            throw ReadErrorException; /* à définir par toi meme */
        }
        /* ... */
    }
    et cela te simplifierait grandement la vie

    D'ailleurs, une fois que tu as suivi ce genre de réflexion, tu te rend compte que la logique reste la même en mode C : une fois les dimensions de l'image détectées, elles ne risquent absolument plus de changer d'un passage dans la boucle à l'autre.

    Tu dois donc pouvoir sortir la création (et la destruction) de ton iplImage de la boucle, pour qu'elle soit créée "une bonne fois pour toutes", sous une forme proche de
    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
     
     
    IplImage *iplImg = new IplImage ; //inutile de passer par null, si c'est pour allouer directement la mémoire nécessaire ;)
    for(;;){
        *iplImg = cvQueryFrame( capture);
        frame = cv::cvarrToMat(iplImg);
        if( frame.empty() )
            break;
        if( iplImg->origin == IPL_ORIGIN_TL )
            frame.copyTo( frameCopy );
        else
            flip( frame, frameCopy, 0 );
        detectAndDraw( frameCopy, cascade, nestedCascade, scale, tryflip );
        if( waitKey( 10 ) >= 0 )
            goto _cleanup_;           // la seule methode de sortir du programme est de cliquer sur ESC
    }
    _cleanup_:
    delete iplImg;
    iplImg = NULL;
    Note que, comme nous sommes en C++, nous préférerons sans doute utiliser une classe de pointeur qui nous assure que, quoi qu'il arrive, la mémoire allouée au pointeur sera correctement libérée. J'ai nommé : std::unique_ptr. Le code pourrait donc avantageusement être modifié sous la forme de
    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
     
     
    std::unique_ptr<IplImage> iplImg (new IplImage(parametres utiles */)) ; // C++11
    /* OU  --  OU  --  OU (C++14)
    auto iplImg  = std::make_unique<IplImage>(/* param utiles */);
    for(;;){
        *(iplImg.get()) = cvQueryFrame( capture);
        frame = cv::cvarrToMat(iplImg.get());
        if( frame.empty() )
            break;
        if( iplImg->origin == IPL_ORIGIN_TL )
            frame.copyTo( frameCopy );
        else
            flip( frame, frameCopy, 0 );
        detectAndDraw( frameCopy, cascade, nestedCascade, scale, tryflip );
        if( waitKey( 10 ) >= 0 )
            goto _cleanup_;           // la seule methode de sortir du programme est de cliquer sur ESC
    }
    _cleanup_:
    /* plus rien à faire ici en ce qui concerne iplImg */
    NOTA : je n'ai jamais utilisé OpenCV, mais je me base sur la documentation que j'ai lue en diagonale
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 17
    Dernier message: 02/02/2006, 12h03
  2. gestion de la mémoire
    Par moldavi dans le forum C++
    Réponses: 17
    Dernier message: 04/02/2005, 23h18
  3. Réponses: 11
    Dernier message: 26/12/2004, 22h50
  4. Gestion de la mémoire entre plusieurs DLL
    Par Laurent Gomila dans le forum C++
    Réponses: 7
    Dernier message: 27/07/2004, 15h28
  5. Gestion des variables - mémoire ?
    Par RIVOLLET dans le forum Langage
    Réponses: 4
    Dernier message: 26/10/2002, 12h44

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