gpt4 book ai didi

c++ - cvCreateMat 内存泄漏(OpenCV)

转载 作者:行者123 更新时间:2023-11-28 06:19:02 27 4
gpt4 key购买 nike

好的;所以当我尝试使用 cvCreateMat 为我即将填充的垫子腾出空间时,我发现了一个奇怪的内存泄漏。以下是我正在尝试做的事情; adaptiveThreshold 不喜欢我把 3 channel 图像放进去,所以我想把它分成单独的 channel 。有用!但是每次我们执行这个特定的函数时,我们都会获得另外 ~3MB 的内存。由于此函数预计会运行数百次,因此这成为一个相当值得注意的问题。

代码如下:

void adaptiveColorThreshold(Mat *inputShot, int adaptiveMethod, int blockSize, int cSubtraction)
{
Mat newInputShot = (*inputShot).clone();
Mat inputBlue = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);
Mat inputGreen = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);
Mat inputRed = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);

for(int rows = 0; rows < newInputShot.rows; rows++)
{
for(int cols = 0; cols < newInputShot.cols; cols++)
{
inputBlue.data[inputBlue.step[0]*rows + inputBlue.step[1]*cols] = newInputShot.data[newInputShot.step[0]*rows + newInputShot.step[1]*cols + 0];
inputGreen.data[inputGreen.step[0]*rows + inputGreen.step[1]*cols] = newInputShot.data[newInputShot.step[0]*rows + newInputShot.step[1]*cols + 1];
inputRed.data[inputRed.step[0]*rows + inputRed.step[1]*cols] = newInputShot.data[newInputShot.step[0]*rows + newInputShot.step[1]*cols + 2];
}
}

adaptiveThreshold(inputBlue, inputBlue, 255, adaptiveMethod, THRESH_BINARY, blockSize, cSubtraction);
adaptiveThreshold(inputGreen, inputGreen, 255, adaptiveMethod, THRESH_BINARY, blockSize, cSubtraction);
adaptiveThreshold(inputRed, inputRed, 255, adaptiveMethod, THRESH_BINARY, blockSize, cSubtraction);

for(int rows = 0; rows < (*inputShot).rows; rows++)
{
for(int cols = 0; cols < (*inputShot).cols; cols++)
{
(*inputShot).data[(*inputShot).step[0]*rows + (*inputShot).step[1]*cols + 0] = inputBlue.data[inputBlue.step[0]*rows + inputBlue.step[1]*cols];
(*inputShot).data[(*inputShot).step[0]*rows + (*inputShot).step[1]*cols + 1] = inputGreen.data[inputGreen.step[0]*rows + inputGreen.step[1]*cols];
(*inputShot).data[(*inputShot).step[0]*rows + (*inputShot).step[1]*cols + 2] = inputRed.data[inputRed.step[0]*rows + inputRed.step[1]*cols];
}
}

inputBlue.release();
inputGreen.release();
inputRed.release();
newInputShot.release();

return;
}

所以一次一行地浏览它......

  • newInputShot 增加了 ~3MB
  • inputBlue 添加了 ~1MB
  • inputGreen 添加 ~1MB
  • 并且 inputRed 添加 ~1MB

到目前为止,一切顺利 - 需要内存来保存数据。 newInputShot 立即获取它的数据,但是 inputRGB 需要从 newInputShot 获取它们的数据 - 所以我们只是分配要在即将到来的 for 循环中填充的空间,它(正如预期的那样)不分配新内存,只是填充空间已经声明。

adaptiveThresholds 也不会添加任何新内存,因为它们只是应该覆盖已经存在的内存,而下一个 for 循环直接写入 inputShot;那里不需要新的内存。所以现在我们开始(手动)释放内存。

  • 释放 inputBlue 释放 0MB
  • 释放 inputGreen 释放 0MB
  • 释放 inputRed 释放 0MB
  • 释放 newInputShot 释放约 3MB

现在,根据 OpenCV 文档站点:“OpenCV handles all the memory automatically.

First of all, std::vector, Mat, and other data structures used by the functions and methods have destructors that deallocate the underlying memory buffers when needed. This means that the destructors do not always deallocate the buffers as in case of Mat. They take into account possible data sharing. A destructor decrements the reference counter associated with the matrix data buffer. The buffer is deallocated if and only if the reference counter reaches zero, that is, when no other structures refer to the same buffer. Similarly, when a Mat instance is copied, no actual data is really copied. Instead, the reference counter is incremented to memorize that there is another owner of the same data. There is also the Mat::clone method that creates a full copy of the matrix data.

引述 TLDR:相关的垫子聚集在一个 super 垫子中,当没有任何东西在使用它时,它会立即全部释放。

这就是为什么我将 newInputShot 创建为一个克隆(它不会与 inputShot 混为一谈)- 这样我就可以看到这是否发生在 inputRGB 上。好吧……不! inputRGBs 是他们自己的野兽,拒绝被释放。我知道它不是任何中间函数,因为这个片段做的是完全相同的事情:

void adaptiveColorThreshold(Mat *inputShot, int adaptiveMethod, int blockSize, int cSubtraction)
{
Mat newInputShot = (*inputShot).clone();
Mat inputBlue = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);
Mat inputGreen = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);
Mat inputRed = cvCreateMat(newInputShot.rows, newInputShot.cols, CV_8UC1);

inputBlue.release();
inputGreen.release();
inputRed.release();
newInputShot.release();

return;
}

就这么简单。分配 - 无法取消分配。那么 cvCreateMat 是怎么回事?

最佳答案

我建议不要使用 cvCreateMat 并且您也不需要克隆原始 Mat。考虑使用 split()merge()功能。他们会为你做肮脏的工作,并会返回 Mat 来为你处理内存。我现在没有安装 OpenCV,所以我无法测试任何代码,但我确定这就是您要采用的方法。

关于c++ - cvCreateMat 内存泄漏(OpenCV),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29638231/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com