内存管理对于图像类至关重要。在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}};
答案 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
分配的数据会丢失。
使用memcpy
从myImage.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。)