2015-12-23 3 views
1

Я пытаюсь написать код, который использует OpenCV Mat объекты он идет что-то вроде этогоизбежать утечки памяти при использовании вектора <Mat>

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(); 

Я, однако до сих пор, кажется, есть утечка памяти может кто-нибудь сказать мне, почему это так ? Я подумал, что если RefCount объекта мат = 0, то память должна быть автоматически освобождаться

+0

@Miki изображения, которые я помещал в img, имеют один и тот же тип и размеры, но разные изображения. Представьте, что вы делаете что-то вроде imread (FileName) на каждой итерации. –

+0

ah wait .. ваш код выглядит сломанным, почему вы вызываете 'img.release()' в цикле? – Micka

+0

Да, в петле. так как я также создаю его в цикле. –

ответ

1

Вам редко нужно позвонить release явно, так как OpenCV Mat объекты берут автоматически заботиться о внутренней памяти.

Также обратите внимание, что копия только копий создает новый заголовок, указывающий на те же данные. Если исходный Mat выходит за рамки, вы остаетесь с недопустимой матрицей. Поэтому, когда вы вставляете изображение в вектор, используйте глубокую копию (clone()), чтобы избежать изменения изображения в вектор.

Поскольку вы упомянули:

У меня есть большой 3D изображение, хранящееся в объекте Mat. Я бегу над ним, используя для циклов. создавая двумерный мат, называемый «изображением», помещая фрагменты в изображение, отталкивая обратное изображение к векторным изображениям. освобождая изображение. А позже сделайте цикл for на вектор-изображение, освобождая все матрицы по одному.

Вы можете хранить все фрагменты в векторе со следующим кодом. Чтобы освободить изображения в векторе, просто clear вектор.

#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; 
} 
+0

Использование глубокой копии очень дорогое с точки зрения времени, я знаю, что она создает новый заголовок, указывающий на те же данные , Поэтому, чтобы фактически освободить все данные, я думал о явном выпуске всех заголовков. В документации здесь говорится, что если заголовок матрицы указывает на внешний набор данных (см. Mat :: Mat()), опорный счетчик равен NULL, и в этом случае метод не имеет никакого эффекта. Я не уверен, что это значит. http://docs.opencv.org/2.4/modules/core/doc/basic_structures.html?highlight=mat#void%20Mat::release%28%29 –

+0

Если вы выделили данные извне и просто создали заголовок Matrix на верхняя часть, освобождение матрицы оставит исходные данные без изменений. Вам также необходимо явно освободить данные orignal. – Miki

+1

Будет гораздо легче ответить правильно, если вы точно покажете, что хотите, и откуда берутся ваши данные. – Miki

1

Пожалуйста, попробуйте этот код, который является в основном то, что вы делаете:

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; 
} 

После первого вызова функции теста, память будет «утечка», так что приложение потребляет 4 КБ больше памяти на моем устройство. Но не больше «утечек» после дополнительных звонков для меня ...

Так выглядит, что ваш код в порядке, а «утечка памяти» не связана с созданием и выпуском матрицы, но, возможно, для некоторых «глобальных», вещи, происходящие в библиотеке openCV или C++, для оптимизации будущих вызовов функций или распределения памяти.

+1

Спасибо за помощь. Оказывается, я отлично справлялся с матрицами и их заголовками, но из-за некоторых отливок у меня возникали утечки памяти. Использование ((raw_t_real32 *) img.data) [i] кастинг для доступа к данным объекта mat, если сам img - за считанные 8-разрядные матрицы без знака - очень плохая практика. С этого момента я буду использовать cv :: Mat :: at. –

1

Я столкнулся с такими же проблемами, когда итерация openCV mat. Потребление памяти может составлять 1,1 ГБ, а затем оно останавливается предупреждением о том, что нет памяти. В моей программе есть макрос #define new new (FILE, LINE), разбился с какой-то std lib. Поэтому я удалил всех операторов перегрузки о новом/удалить. При отладке он не имеет ошибки. Но когда он работает, я получил «Debug Assertion Failed! Expression: _pFirstBlock == pHead». После инструкции Debug Assertion Error in OpenCV Я изменил настройки от MT (Release)/MTd (Debug) для

Project Properties >> Configuration Properties >> C/C++ >> генерации кода и изменения Runtime библиотеки для:

многопоточных Debug DLL (/ MDD), если вы строят отладочную версию вашего кода. Многопоточная DLL (/ MD), если вы создаете версию Release вашего кода.

Утечка памяти исчезла. Потребление памяти составляет 38M.

Смежные вопросы