Opencv Mat内存管理

时间:2014-04-23 15:17:20

标签: c++ opencv image-processing

内存管理对于图像类至关重要。在opencv中,图像类是cv::Mat,它具有精细的内存管理方案。假设我已经拥有自己的图像类SelfImage

class SelfImage
{
  public:
    int width_;
    int height_;
    unsigned char *pPixel_;    
};

一开始,我会将所有图像像素内容放到这个类中:

SelfImage myImage;
myImage.width_ = 300;
myImage.height_ = 200;
myImage.pPixel_ = new [300*200];
for(int i=0; i<300*200; i++)
      myImage.pPixel_[i] = i%200;

然后我的问题是如何以非常有效的方式将此类转换为cv::Mat,我有一个解决方案:

  cv::Mat mat;
    mat.create( myImage.height_, myImage.width_, CV_8UC1);
    mat.data = myImage.pPixel_;

我不知道这是否是一个很好的解决方案。如果cv::Mat::create函数也将分配内存,则上述代码存在内存泄漏的危险。有什么想法吗?

修改   我必须说清楚,如果我可以使用cv::Mat::create方法但是与SelfImage类共享内存会很好。原因是定义了一个函数来执行图像类转换作业{{ 1}};

4 个答案:

答案 0 :(得分:6)

cv::Mat has a constructor您可以在其中指定用户数据:

Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)

文档说明了data参数:

  

指向用户数据的指针。采用数据和步骤的矩阵构造函数   参数不分配矩阵数据。相反,他们只是初始化   指向指定数据的矩阵标头,这意味着   没有数据被复制。此操作非常有效,可以用于   使用OpenCV函数处理外部数据。外部数据不是   自动解除分配,所以你应该照顾它。

答案 1 :(得分:1)

Mat::create()分配数据(total()*elemSize()个字节)并将分配数据的内部引用计数器初始化为1(除非Mat已存在且指定的大小/类型相同在create()方法中。

是的,您的代码会产生内存泄漏,因为移动Mat::create()指针时Mat::data分配的数据会丢失。

使用memcpymyImage.pPixel_mat.data(在致电create()之后),应该(在我看来)这样做的正确方法。这似乎效率低下,但好的一面是Mat析构函数将处理数据释放。

答案 2 :(得分:1)

您只需使用

即可
Mat mat = Mat(myImage.height_, myImage.width_, CV_8UC1, myImage.pPixel_);

这样就不会复制任何数据。当然,作为价格,你应该注意释放记忆。

来自doc

  

[...]相反,它们只是初始化指向指定数据的矩阵标头,这意味着不会复制任何数据。此操作非常有效,可用于使用OpenCV函数处理外部数据。外部数据不会自动解除分配,因此您应该处理它。

答案 3 :(得分:1)

这取决于您是否要复制数据。

根据您的建议,您似乎想要共享数据。在这种情况下,这是最好的解决方案:

cv::Mat mat(myImage.height_, myImage.width_, CV_8U, myImage.pPixel_);

mat在释放时不会释放内存,你必须这样做。

如果您要复制数据,请创建正常的cv::Mat并稍后执行std::copy(或建议使用memcpy作为@KeillRandor。)