【问题标题】:Do I need to release IplImage after conversion to Mat?转换为 Mat 后是否需要释放 IplImage?
【发布时间】:2015-11-05 12:36:18
【问题描述】:

我在代码中的几个地方执行以下操作;

cv::Mat cv_proc_image = ...
IplImage ipl_img = cv_proc_image;
cvSmooth(&ipl_img, &ipl_img, smooth_type, smooth_param1);
cv_proc_image = cv::cvarrToMat(&ipl_img);

并且我观察到在包含此操作的更改后内存膨胀。你觉得,我应该在最后一次赋值后释放 IplImages 分配的内存吗?

【问题讨论】:

  • 什么是 cv_proc_image?
  • 它是 cv::Mat 取自函数参数
  • 你不应该首先使用旧的 C 语法
  • 如果你展示了 smooth_typesmooth_param1 是什么,我可以在我的回答中提供一个小例子来展示如何使用 C++ 语法
  • @Micka 没有新的内存分配。检查更新的答案;D

标签: c++ opencv memory-management memory-leaks


【解决方案1】:

一开始就不应该使用旧的 C 语法。您应该使用 C++ 语法。另请注意cvSmooth:

该功能现已过时。使用 GaussianBlur()、blur()、medianBlur() 或lateralFilter()。


更新

当您执行IplImage ipl_img = mat_img; 时,您只是在创建一个新标头,没有数据副本。所以这不会耗尽你的记忆。让我用一个小例子来展示它:

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

int main()
{
    // Your (green) mat
    Mat mat_img(10, 10, CV_8UC3, Scalar(0,255,0));

    // To IplImage
    IplImage ipl_img = mat_img;

mat_imgipl_img 是相等的。不涉及副本。

    // It's created only a new header, on the same data

    // In fact, changing ipl_img changes also mat_img
    cvSet2D(&ipl_img, 1, 2, Scalar(255,0,0)); 

两张图片都变成了这样:

    // Same here, changing ipl_img changes also mat_img
    cvSmooth(&ipl_img, &ipl_img);

    return 0;
}

即使经过平滑处理,它们也是相等的:

结论

所以回答你原来的问题:,你不需要发布IplImage,因为不涉及副本。您只是在创建新标题,但指向相同的数据。您的内存泄漏在其他地方。

您甚至不需要使用cvarrToMat,因为IplImage 的更改与Mat 相同。

【讨论】:

  • 这不是讨论的最佳地点,但值得注意的是,操作员没有提及他使用的 OpenCV 版本或这是否是遗留代码。作为一个社区,我们需要注意旧系统的开发人员可能仍然会提出问题。现在我不知道这是否仍然不是正确的答案,但它实际上并没有回答问题。
  • 我部分同意你的看法。显然OP不在C环境中,否则他无法使用Mat。所以它是C++。出于同样的原因,该版本相当新。无论如何,我把 cmets 留给了这个问题,如果他必须使用 C,那么我期待他的回应。此外,在发布的代码中,他只是使用旧语法调用单个函数,然后返回新语法。这表明对函数使用新语法也将解决问题(我的其他评论是关于给出一个完整的例子)。所以我认为这确实回答了这个问题,至少正如它所说的那样现在 @GPPK
  • 告诉我的!我倾向于同意。
  • @GPPK 因为我部分同意你,我也回答了主要问题。感谢您首先指出这一点。
  • 您认为这可能是原因吗? cv::resize(img, img, cv::Size(new_width, new_height));
【解决方案2】:

来自 Opencv 文档:

>     When copyData=false , the conversion is done really fast (in O(1) time) and the newly created matrix header will have refcount=0 , which
> means that no reference counting is done for the matrix data. In this
> case, you have to preserve the data until the new header is
> destructed. Otherwise, when copyData=true , the new buffer is
> allocated and managed as if you created a new matrix from scratch and
> copied the data there. That is, cvarrToMat(arr, true) is equivalent to
> cvarrToMat(arr, false).clone() (assuming that COI is not set). The
> function provides a uniform way of supporting CvArr paradigm in the
> code that is migrated to use new-style data structures internally. The
> reverse transformation, from Mat to CvMat or IplImage can be done by a
> simple assignment:

在您的情况下,您没有设置“copyData”,因此默认情况下为 false:

Mat cvarrToMat(const CvArr* arr, bool copyData=false, bool allowND=true, int coiMode=0 )

所以,你必须自己释放它。

编辑: 我不熟悉旧的 OpenCV 风格.. lplimage 在超出范围时会自行释放吗?如果这样做,则不会发生泄漏

【讨论】:

  • IplImage 在超出范围时不会释放。问题是,IplImage ipl_img = cv_proc_image; 是否分配了新内存,或者cv_proc_image 的数据指针是否在 IplImage 内部某处使用。如果那里分配了新的内存,那么他必须手动释放它。
猜你喜欢
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-02
相关资源
最近更新 更多