J'essaie d'écrire un code qui utilise des objets opencv Mat, cela ressemble à quelque chose comme ça

Mat img;
vector<Mat> images;
for (i = 1; i < 5; i++)
{
  img.create(h,w,type) // h,w and type are given correctly
  // input an image from somewhere to img correctly. 
  images.push_back(img);
  img.release()
}
for (i = 1; i < 5; i++)
  images[i].release();

Cependant, je semble toujours avoir des fuites de mémoire. Quelqu'un peut-il me dire pourquoi? Je pensais que si le refcount d'un objet mat = 0 alors la mémoire devrait être automatiquement désallouée

1
Vahagn Tumanyan 23 déc. 2015 à 14:12

3 réponses

Meilleure réponse

Vous avez rarement besoin d'appeler release explicitement, car les objets OpenCV Mat prennent automatiquement en charge la mémoire interne.

Veillez également à ce que Mat copy just copies crée un nouvel en-tête pointant vers les mêmes données. Si l'original Mat sort de la portée, vous vous retrouvez avec une matrice invalide. Ainsi, lorsque vous poussez l'image dans le vecteur, utilisez une copie profonde (clone()) pour éviter que l'image dans le vecteur ne devienne invalide.

Lorsque je teste dans le navigateur, il ne montre que la poignée de redimensionnement en bas de l'éditeur, les barres d'outils ne sont pas chargées du tout. Je ne sais pas s'il y a quelque chose en dehors des étapes fournies par les instructions de sunnernote. Veuillez m'aider car je suis en stock ici, je ne veux pas utiliser un autre éditeur. Merci d'être passé.

J'ai une grande image 3D stockée dans un objet Mat. Je cours dessus en utilisant des boucles for. création d'un tapis 2D appelé "image" mettant les tranches en image, repoussant l'image en images vectorielles. libérer l'image. Et plus tard, faire une boucle for sur le vecteur d'images libérant toutes les matrices une par une.

Vous pouvez stocker toutes les tranches dans le vecteur avec le code suivant. Pour libérer les images dans le vecteur, il suffit de clear le vecteur.

#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;

int main() 
{
    // Init the multidimensional image
    int sizes[] = { 10, 7, 5 };
    Mat data(3, sizes, CV_32F);
    randu(data, Scalar(0, 0, 0), Scalar(1,1,1));

    // Put slices into images
    vector<Mat> images;
    for (int z = 0; z < data.size[2]; ++z)
    {
        // Create the slice
        Range ranges[] = { Range::all(), Range::all(), Range(z, z + 1) };
        Mat slice(data(ranges).clone()); // with clone slice is continuous, but still 3d
        Mat slice2d(2, &data.size[0], data.type(), slice.data); // make the slice a 2d image

        // Clone the slice into the vector, or it becomes invalid when slice goes of of scope.
        images.push_back(slice2d.clone());
    }

    // You can deallocate the multidimensional matrix now, if needed
    data.release();

    // Work with slices....

    // Release the vector of slices
    images.clear();

    return 0;
}
1
Miki 23 déc. 2015 à 11:51

J'ai rencontré les mêmes problèmes lors de l'itération du tapis openCV. La consommation de mémoire peut être de 1,1G, puis il s'est arrêté en avertissant qu'aucune mémoire. Dans mon programme, il y a la macro #define new new ( FILE , LINE ), plantée avec une bibliothèque std. J'ai donc supprimé tous les opérateurs de surcharge à propos de nouveau / suppression. Lors du débogage, il n'y a aucune erreur. Mais quand il s'exécute, j'ai "Debug Assertion Failed! Expression: _pFirstBlock == pHead". Suivre les instructions Erreur d'assertion de débogage dans OpenCV J'ai changé le paramètre de MT (Release) / MTd (Debug) à

Project Properties >> Configuration Properties >> C/C++ >> Génération de code et modification de la bibliothèque d'exécution en:

DLL de débogage multithread (/ MDd), si vous créez la version de débogage de votre code. DLL multithread (/ MD), si vous créez la version Release de votre code.

La fuite de mémoire a disparu. La consommation de mémoire est de 38M .

1
Elangovan 21 févr. 2018 à 13:50

Veuillez essayer ce code, qui est essentiellement ce que vous faites:

void testFunction()
{
    // image width/height => 80MB images
    int size = 5000;

    cv::Mat img = cv::Mat(size, size, CV_8UC3);

    std::vector<cv::Mat> images;
    for (int i = 0; i < 5; i++)
    {
      // since image size is the same for i==0 as the initial image, no new data will be allocated in the first iteration.
      img.create(size+i,size+i,img.type()); // h,w and type are given correctly

      // input an image from somewhere to img correctly. 
      images.push_back(img);
      // release the created image.
      img.release();
    }

    // instead of manual releasing, a images.clear() would have been enough here.
    for(int i = 0; i < images.size(); i++)
      images[i].release();

    images.clear();
}

int main()
{
    cv::namedWindow("bla");
    cv::waitKey(0);

    for(unsigned int i=0; i<100; ++i)
    {
        testFunction();
        std::cout << "another iteration finished" << std::endl;
        cv::waitKey(0);
    }

    std::cout << "end of main" << std::endl;
    cv::waitKey(0);
    return 0;
}

Après le premier appel de testFunction, la mémoire sera "perdue" de sorte que l'application consomme 4 Ko de mémoire en plus sur mon appareil. Mais pas plus de "fuites" après des appels supplémentaires pour moi ...

Donc, cela semble que votre code est correct et que la "fuite de mémoire" n'est pas liée à la création et à la libération de cette matrice, mais peut-être à des choses "globales" qui se produisent dans la bibliothèque openCV ou C ++ pour optimiser les futurs appels de fonctions ou allocations de mémoire.

1
Micka 23 déc. 2015 à 12:26