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

OpenCV Discussion :

Erreur de désallocation de mémoire


Sujet :

OpenCV

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 53
    Points : 37
    Points
    37
    Par défaut Erreur de désallocation de mémoire
    Bonjour,
    J'ai écrit un petit code qui me permet de lire une vidéo à partir d'un fichier et qui calcule la différence entre deux images qui se suivent. Mais ce programme présente un défaut énorme:il bouffe la mémoire. et donc, j'ai pensé à détruire les variables temporaires, mais j'obtiens un message d'erreur au moment de l'exécution(pas de problème au moment de la compilation): "Unknown error code -49(Deallocation error) ..."
    Voci mon code
    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
     
     
    #include <iostream>
    #include <cv.h>
    #include <cxcore.h>
    #include <highgui.h>
    #include <cmath>
    using namespace std;
    double calcul(IplImage* ImTemp1, IplImage* ImTemp2);
    int main()
    {
       	CvCapture* input_video=NULL;
    	input_video = cvCaptureFromFile("video.avi");
    	int FrameNumber = static_cast<int> (cvGetCaptureProperty (input_video, CV_CAP_PROP_FRAME_COUNT));
    	printf("%d\n",FrameNumber);
     
    	IplImage* ImTemp1=NULL;
    	cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES,0);
        ImTemp1=cvQueryFrame(input_video);
     
     
    	    for (int i=0;i<FrameNumber-1;i++)
            {
                double somme;
                IplImage* ImTemp2=NULL;
                cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES,i+1);
                ImTemp2=cvQueryFrame(input_video);
                cvNamedWindow("F1",1);
                cvShowImage("F1",ImTemp2);
                cvWaitKey(1);
                ImTemp1=cvCloneImage(ImTemp2);
                cvReleaseImage(&ImTemp2);
                somme=calcul(ImTemp1,ImTemp2);
            }
     
        cvReleaseCapture(&input_video);
        return 0;
    }
    double calcul(IplImage* ImTemp1, IplImage* ImTemp2)
    {
        double res=(double)ImTemp1->width*(double)ImTemp1->height;
        CvScalar scalaire1;
        CvScalar scalaire2;
        double somme = 0;
        for (int x=0; x<ImTemp1->width; x++)
            {
                for (int y=0; y<ImTemp1->height; y++)
                {
                    scalaire1=cvGet2D(ImTemp1,y,x);
                    scalaire2=cvGet2D(ImTemp2,y,x);
                    somme = somme + std::abs((double)scalaire1.val[0]- (double)scalaire2.val[0]);
                }
            }
            return somme/res;
    }
    Si je met la ligne " cvReleaseImage(&ImTemp2);" en commentaire le programme marche bien je retrouve le problème de mémoire.

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 53
    Points : 37
    Points
    37
    Par défaut
    J'ai trouvé l'erreur: c'est simple: il faut mettre la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    somme=calcul(ImTemp1,ImTemp2);
    avant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ImTemp1=cvCloneImage(ImTemp2);
    Mais le problème maintenant est que la boucle ne boucle pas Il affiche la première image et il sort.

  3. #3
    Membre actif Avatar de gassi64
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2008
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2008
    Messages : 255
    Points : 230
    Points
    230
    Par défaut
    Pourquoi crées tu une nouvelle structure ImTemp2 dans le for?
    Tu pourrais la créé plutot avant le for, l'utiliser dans le for, et faire le release a la sortie du for...
    Pourquoi ça ne boucle plus par contre je ne sais pas, ta essayé un affichage au lieu d'une fenetre pour l'image traitée du for?

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 53
    Points : 37
    Points
    37
    Par défaut
    Si je je crée ImTemp2 en dehors de la boucle, je ne résout pas le problème de mémoire. Le problème vient de cvCloneImage c'est pourquoi j'ai pensé à créer une variable temporaire à l'intérieur de la boucle et de la libérer à la fin. Mais la boucle ne fonctionne pas.
    En faite j'ai testé plusieurs combinaisons:
    si je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    //double somme=calcul(ImTemp1,ImTemp2);
    ImTemp1=cvCloneImage(ImTemp2);
    //cvReleaseImage(&ImTemp2);
    pb de mémoire
    si je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //double somme=calcul(ImTemp1,ImTemp2);
    ImTemp1=cvCloneImage(ImTemp2);
    cvReleaseImage(&ImTemp2);
    pb de déallocation
    si je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     double somme=calcul(ImTemp1,ImTemp2);
    ImTemp1=cvCloneImage(ImTemp2);
    //cvReleaseImage(&ImTemp2);
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    double somme=calcul(ImTemp1,ImTemp2);
     ImTemp1=cvCloneImage(ImTemp2);
     cvReleaseImage(&ImTemp2);
    la boucle ne fonctionne pas.

  5. #5
    Membre régulier Avatar de hunta_kirua
    Profil pro
    Inscrit en
    Février 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 110
    Points : 123
    Points
    123
    Par défaut
    Bonjour,

    Il me semble (à vérifier) que cvQueryFrame sert uniquement de moyen pour accéder à la vidéo c'est-à-dire que l'IplImage* n'est pas vraiment créé, il ne faut donc pas le libérer par cvReleaseImage puisque le fichier vidéo le sera avec cvReleaseCapture et du coup (aussi à vérifier) cvSetCaptureProperty ne te donne qu'un "pointeur" sur la vidéo et sans cvCloneImage, tu dois avoir 2 fois la même image.

    Essaie un truc du style :


    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
    int main()
    {
       	CvCapture* input_video=NULL;
    	input_video = cvCaptureFromFile("video.avi");
    	int FrameNumber = static_cast<int> (cvGetCaptureProperty (input_video, CV_CAP_PROP_FRAME_COUNT));
    	printf("%d\n",FrameNumber);
     
    	IplImage* ImTemp1=NULL;
    	IplImage* ImTemp2=NULL;
     
    	    for (int i=0;i<FrameNumber-1;i++)
            {
                double somme;
    	    cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES,i);
    	    ImTemp1=cvCloneImage(cvQueryFrame(input_video));
                cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES,i+1);
                ImTemp2=cvCloneImage(cvQueryFrame(input_video));
                cvNamedWindow("F1",1);
                cvShowImage("F1",ImTemp2);
                cvWaitKey(1);
                somme=calcul(ImTemp1,ImTemp2);
     
    	    cvReleaseImage(&ImTemp1);
    	    cvReleaseImage(&ImTemp2);
            }
     
        cvReleaseCapture(&input_video);
        return 0;
    }
    Edit : pour limiter les accès au fichier, voir pour faire un truc du style :

    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
    IplImage* ImTemp1=NULL;
    	IplImage* ImTemp2=NULL;
     
    	cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES,0);
    	ImTemp1=cvCloneImage(cvQueryFrame(input_video));
     
    	    for (int i=0;i<FrameNumber-1;i++)
            {
                double somme;
     
                cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES,i+1);
                ImTemp2=cvCloneImage(cvQueryFrame(input_video));
                ...........
    		cvReleaseImage(&ImTemp1);
    		ImTemp1=ImTemp2;
     
            }
     
       cvReleaseImage(& ImTemp2);
        cvReleaseCapture(&input_video);
    A+,

    Hunta
    newbie un jour, newbie toujours
    n'oubliez pas le

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 53
    Points : 37
    Points
    37
    Par défaut
    Merci hunta_kirua
    C'est bon:
    En ajoutant cvCloneImage à cvQueryFrame j'arrive à résoudre les problèmes d'allocations et de mémoire
    Par contre, je comprend pas toujours à résoudre le pb de la boucle

  7. #7
    Membre régulier Avatar de hunta_kirua
    Profil pro
    Inscrit en
    Février 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 110
    Points : 123
    Points
    123
    Par défaut
    Re,

    C'est quoi exactement ton "problème dans la boucle" ?

    A+,

    Hunta
    newbie un jour, newbie toujours
    n'oubliez pas le

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 53
    Points : 37
    Points
    37
    Par défaut
    le probleme c'est que la boucle ne fonctionne pas, c'est à dire que le traitement ne se fait que pour i=0. puis il sort(sans message d'erreur)
    Voici le code
    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
     
    #include <iostream>
    #include <cv.h>
    #include <cxcore.h>
    #include <highgui.h>
    #include <cmath>
    using namespace std;
    void calcul(IplImage* ImTemp1, IplImage* ImTemp2,double somme);
    int main()
    {
       	CvCapture* input_video=NULL;
    	input_video = cvCaptureFromFile("video.avi");
    	int FrameNumber = static_cast<int> (cvGetCaptureProperty (input_video, CV_CAP_PROP_FRAME_COUNT));
    	printf("%d\n",FrameNumber);
     
    	IplImage* ImTemp1=NULL;
    	IplImage* ImTemp2=NULL;
     
    	cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES,0);
        ImTemp1=cvCloneImage(cvQueryFrame(input_video));
     
    	    for (int i=0;i<FrameNumber-1;i++)
            {
                cvSetCaptureProperty(input_video, CV_CAP_PROP_POS_FRAMES,i+1);
                ImTemp2=cvCloneImage(cvQueryFrame(input_video));
                double somme=0;
                calcul(ImTemp1,ImTemp2,somme);
                cvReleaseImage(&ImTemp1);
                ImTemp1=cvCloneImage(ImTemp2);
                cvNamedWindow("F1",1);
                cvShowImage("F1",ImTemp1);
                cvWaitKey(1);
                cvReleaseImage(&ImTemp2);
            }
        cvReleaseCapture(&input_video);
        cvReleaseImage(&ImTemp1);
        return 0;
    }
    void calcul(IplImage* ImTemp1, IplImage* ImTemp2,double somme)
    {
        double res=(double)ImTemp1->width*(double)ImTemp1->height;
        CvScalar scalaire1;
        CvScalar scalaire2;
        for (int x=0; x<ImTemp1->width; x++)
            {
                for (int y=0; y<ImTemp1->height; y++)
                {
                    scalaire1=cvGet2D(ImTemp1,y,x);
                    scalaire2=cvGet2D(ImTemp2,y,x);
                    somme = somme + std::abs((double)scalaire1.val[0]- (double)scalaire2.val[0])/res;
                }
            }
    }
    et si je met en commentaire la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    calcul(ImTemp1,ImTemp2,somme);
    la boucle fonctionne (Mais bon, je ne fait qu'afficher la vidéo et je ne fait pas donc le traitement voulu).

  9. #9
    Membre régulier Avatar de hunta_kirua
    Profil pro
    Inscrit en
    Février 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 110
    Points : 123
    Points
    123
    Par défaut
    Re,

    Eh bien écoute à part un problème au niveau des paramètres de ta fonction calcul ( double &somme), je ne vois pas de problème.

    Je teste ton code.

    Edit : J'ai testé ton code et affiché le résultat dans la console. Le calcul se fait bien (ma video contient 43 images) donc je ne sais pas trop quoi en penser . Essaie avec une autre vidéo pour voir car je ne vois pas le problème...

    Edit 2: supprime les fichiers de compilation et reconstruit complètement ton projet. J'ai parfois des problèmes avec vc++ qui se résolve ainsi (ah... l'informatique et sa magie ).

    A+,

    Hunta
    newbie un jour, newbie toujours
    n'oubliez pas le

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 53
    Points : 37
    Points
    37
    Par défaut
    j'ai essayé avec une autre vidéo ça marche j'ai essayé après avec une troisième vidéo et ça marche pas

  11. #11
    Membre régulier Avatar de hunta_kirua
    Profil pro
    Inscrit en
    Février 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 110
    Points : 123
    Points
    123
    Par défaut
    Re,

    Ca pourrait être un problème de format. Essaie de voir le type d'avi (non compressé, compressé (et avec quoi)). Perso, j'utilise des avi non compressés, c'est pas le plus économique en place mais bon...

    A+,

    Hunta
    newbie un jour, newbie toujours
    n'oubliez pas le

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

Discussions similaires

  1. [WD11] Erreur de lecture emplacement mémoire
    Par roseau dans le forum WinDev
    Réponses: 1
    Dernier message: 02/05/2008, 22h53
  2. erreur d'allocation de mémoire?
    Par ulnar dans le forum C
    Réponses: 17
    Dernier message: 18/05/2007, 09h36
  3. désallocation de mémoire
    Par Tex-Twil dans le forum C
    Réponses: 12
    Dernier message: 19/10/2006, 10h09
  4. allocation/désallocation de mémoire
    Par kinta dans le forum C++
    Réponses: 2
    Dernier message: 10/02/2006, 09h52
  5. Désallocation de mémoire ...
    Par Mike888 dans le forum C
    Réponses: 9
    Dernier message: 18/01/2006, 10h42

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