使用 vector<Mat> 时避免内存泄漏
Avoiding memory leaks while using vector<Mat>
我正在尝试编写一个使用 opencv 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();
但是我似乎仍然有内存泄漏 谁能告诉我为什么会这样?
我认为如果 mat 对象的引用计数 = 0 那么内存应该自动释放
您很少需要显式调用 release
,因为 OpenCV Mat
objects 会自动处理内部存储器。
还要注意 Mat
复制只是复制创建一个新的 header 指向相同的数据。如果原始 Mat
超出范围,您将得到一个无效矩阵。因此,当您将图像推入矢量时,请使用深拷贝 (clone()
) 以避免将图像推入矢量变得无效。
既然你提到了:
I have a large 3D image stored in a Mat object. I am running over it using for loops. creating a 2D mat called "image" putting the slices into image, pushing back image to vector images. releasing the image. And later doing a for loop on the images vector releasing all the matrices one by one.
您可以使用以下代码将所有切片存储到向量中。要释放矢量中的图像,只需 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;
}
请尝试这段代码,这基本上就是您所做的:
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;
}
第一次调用 testFunction 后,内存将为 "leaked",因此应用程序在我的设备上多消耗 4 KB 的内存。但没有更多 "leaks" 在为我打电话后...
所以这看起来你的代码没问题,"memory leak" 与矩阵创建和发布无关,但可能与 openCV 库或 C++ 中发生的一些 "global" 事情有关以进行优化未来的函数调用或内存分配。
我在迭代 openCV mat 时遇到了同样的问题。内存消耗可以达到1.1G,然后通过警告没有内存而停止。在我的程序中,有宏 #define new new(FILE, LINE), crashed with some std lib.所以我删除了所有关于 new/delete 的重载运算符。调试的时候,没有报错。但是当它运行时,我得到了“Debug Assertion Failed! Expression: _pFirstBlock == pHead
”。按照说明
Debug Assertion Error in OpenCV
我将设置从 MT(发布)/MTd(调试)更改为
Project Properties >> Configuration Properties >> C/C++ >>
代码生成并将运行时库更改为:
Multi-threaded 调试 DLL (/MDd),如果您正在构建代码的调试版本。
Multi-threaded DLL(/MD),如果您正在构建代码的发布版本。
内存泄漏消失了。内存消耗为38M。
我正在尝试编写一个使用 opencv 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();
但是我似乎仍然有内存泄漏 谁能告诉我为什么会这样? 我认为如果 mat 对象的引用计数 = 0 那么内存应该自动释放
您很少需要显式调用 release
,因为 OpenCV Mat
objects 会自动处理内部存储器。
还要注意 Mat
复制只是复制创建一个新的 header 指向相同的数据。如果原始 Mat
超出范围,您将得到一个无效矩阵。因此,当您将图像推入矢量时,请使用深拷贝 (clone()
) 以避免将图像推入矢量变得无效。
既然你提到了:
I have a large 3D image stored in a Mat object. I am running over it using for loops. creating a 2D mat called "image" putting the slices into image, pushing back image to vector images. releasing the image. And later doing a for loop on the images vector releasing all the matrices one by one.
您可以使用以下代码将所有切片存储到向量中。要释放矢量中的图像,只需 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;
}
请尝试这段代码,这基本上就是您所做的:
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;
}
第一次调用 testFunction 后,内存将为 "leaked",因此应用程序在我的设备上多消耗 4 KB 的内存。但没有更多 "leaks" 在为我打电话后...
所以这看起来你的代码没问题,"memory leak" 与矩阵创建和发布无关,但可能与 openCV 库或 C++ 中发生的一些 "global" 事情有关以进行优化未来的函数调用或内存分配。
我在迭代 openCV mat 时遇到了同样的问题。内存消耗可以达到1.1G,然后通过警告没有内存而停止。在我的程序中,有宏 #define new new(FILE, LINE), crashed with some std lib.所以我删除了所有关于 new/delete 的重载运算符。调试的时候,没有报错。但是当它运行时,我得到了“Debug Assertion Failed! Expression: _pFirstBlock == pHead
”。按照说明
Debug Assertion Error in OpenCV
我将设置从 MT(发布)/MTd(调试)更改为
Project Properties >> Configuration Properties >> C/C++ >>
代码生成并将运行时库更改为:
Multi-threaded 调试 DLL (/MDd),如果您正在构建代码的调试版本。 Multi-threaded DLL(/MD),如果您正在构建代码的发布版本。
内存泄漏消失了。内存消耗为38M。