cv :: Mat内存即使在调用release()之后也不会释放? [英] cv::Mat memory is not released even after calling release()?

查看:741
本文介绍了cv :: Mat内存即使在调用release()之后也不会释放?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一种方法,其中的图像描述符(例如 OpenCV SIFT VLFeat密集SI FT)计算一组图像(保存在std::vector<std::string> files中).通过ComputeDescriptors(image, descriptorMatrix)调用描述符,在描述符中使用从中计算出的描述符填充descriptorMatrix.

I've written a method where an image descriptor (like OpenCV SIFT or VLFeat Dense SIFT) computes the descriptors for a set of images (save in std::vector<std::string> files). The descriptor is called through ComputeDescriptors(image, descriptorMatrix) where it fills descriptorMatrix with the descriptors computed from.

然后我随机选择samples(通常是50个)描述符,并将sampledDescriptors矩阵推入返回的std::vector<cv::Mat1f> descriptors中.

Then I randomly pick samples (usually 50) descriptors and push the sampledDescriptors matrix in the returned std::vector<cv::Mat1f> descriptors.

这是代码:

void SIFTDescriptor::ComputeDescriptorsRange(const std::vector<std::string> &files, std::vector<cv::Mat1f> &descriptors){
    cv::Mat1f imgDescriptors;
    cv::Mat img;
    for(int i=0 ; i<files.size() ; i++){
        std::cout<<"Describing "<<files[i]<<std::endl;
        img = cv::imread(files[i], cv::IMREAD_GRAYSCALE);
        if(!img.data)
            //throw error
        //resoze dim is a class member
        if(resizeDim>0)
            ImgUtility::resize(img,resizeDim);
        ComputeDescriptors(img,imgDescriptors);
        if(samples > 0 && samples < imgDescriptors.rows){
            std::cout<<"Sampling "<<imgDescriptors.rows<<" descriptors..."<<std::endl;
            cv::Mat1f sampledDescripotrs;
            std::vector<int> v(imgDescriptors.rows);
            std::iota (std::begin(v), std::end(v), 0); //fill v with 0 ... imgDescriptors.rows
            std::random_device rd;
            std::mt19937 g(rd());
            std::shuffle(v.begin(), v.end(), g);
            for(int j=0 ; j<samples; j++){
                sampledDescripotrs.push_back(imgDescriptors.row(v[j]));
            }
            descriptors.push_back(sampledDescripotrs);
            sampledDescripotrs.release();
        }
        else
            descriptors.push_back(imgDescriptors); //copy of a smart pointer, not expensive
        imgDescriptors.release();
        std::cout<<"descriptors["<<i<<"]="<<descriptors[i].rows<<std::endl;
        std::cout<<descriptors[i]<<std::endl;
    }

这样做是为了提高内存效率,尤其是对于密集的描述符,例如 VLFeat Dense SIFT 其中提取了数千个描述符.拥有成千上万张图像,我们将立即耗尽内存.取而代之的是,使用这种解决方案,我们每个图像仅保留50个描述符(对于我的训练来说足够了).

This is done to be memory efficient, especially for dense descriptors such as VLFeat Dense SIFT where thousands of descriptors are extracted. With thousands of images we would run out of memory in no time. Instead, using this solution, we keep only 50 descriptors per image (which is enough for my training).

但是,出于某些奇怪的原因,使用OpenCV SIFT不会占用大量内存,但是使用VLFeat Dense SIFT可以使内存增长得很快,即使在两种情况下samples都相等!

However, for some weird reason, there is no big memory usage using OpenCV SIFT, but using VLFeat Dense SIFT the memory grows pretty fast, even if samples is equal in both cases!

我唯一的解释是,即使使用imgDescriptors,每个循环中的imgDescriptors所使用的内存也不会被释放(由于cv::Mat1f应该是一个智能指针,因此在c处进行自身分配,因此这是不必要的)循环结束),但我不知道这怎么可能.

My only explanation is that the memory used by imgDescriptors at each loop is not freed, even using imgDescriptors (which is should be not necessary anyway since cv::Mat1f should be kinda smart pointer and so deallocate itself at the end of the loop), but I don't understand how's this possible.

这是VLFeat中密集SIFT的ComputeDescriptor代码:

This is the ComputeDescriptor code for dense SIFT in VLFeat:

void DSIFTVLFeat::ComputeDescriptors(cv::Mat &img, cv::Mat1f &descriptors){
    descriptors.release();

    // transform image in cv::Mat to float vector
    cv::Mat imgFloat;
    img.convertTo(imgFloat, CV_32F, 1.0/255.0);
    if(!imgFloat.isContinuous())
        throw std::runtime_error("imgFloat is not continous");

    for(int i=binSize; i<=maxBinSize; i+=2){
        VlDsiftFilter *dsift = vl_dsift_new_basic (img.rows, img.cols, step, i);
        vl_dsift_process (dsift, imgFloat.ptr<float>());
        cv::Mat scaleDescs(vl_dsift_get_keypoint_num(dsift), 128, CV_32F, (void*) vl_dsift_get_descriptors(dsift));
        descriptors.push_back(scaleDescs);
        scaleDescs.release();
        free(dsift);
    }
}

推荐答案

我自己发现了问题:显然free(dsift)不会取消分配已创建的描述符,所以我将它们堆叠在堆上而没有释放它们.

I found out by myself the problem: apparently free(dsift) doesn't de-allocate the created descriptors, so I was stacking them on the heap without releasing them.

致电:vl_sift_delete(dsift)似乎已经解决了问题.

Calling: vl_sift_delete(dsift) instead seems to have solved the problem.

这篇关于cv :: Mat内存即使在调用release()之后也不会释放?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆