将Opencv Mat转换为.net位图时内存泄漏
要将将Opencv Mat转换为.net位图时内存泄漏,.net,winforms,visual-c++,memory-management,memory-leaks,.net,Winforms,Visual C++,Memory Management,Memory Leaks,要将Mat转换为BitMap,我使用了下面的代码 run方法中需要进行一些修改,以保留当前位图直到下一个位图到达?Bitmap需要显式处理,因为它不仅使用托管资源,还使用非托管资源。在这里我引用了,它很好地解释了为什么如果不调用Dispose()method,GC将不会帮助您 位图类不可避免地是一个您必须停止忽略IDisposable存在的类。它是一个围绕GDI+对象的小包装类。GDI+是非托管代码。位图占用非托管内存。当位图较大时,会显示很多信息 NET垃圾收集器确保非托管系统资源与终结器线程
Mat
转换为BitMap
,我使用了下面的代码
run
方法中需要进行一些修改,以保留当前位图直到下一个位图到达?Bitmap
需要显式处理,因为它不仅使用托管资源,还使用非托管资源。在这里我引用了,它很好地解释了为什么如果不调用Dispose()
method,GC将不会帮助您
位图类不可避免地是一个您必须停止忽略IDisposable存在的类。它是一个围绕GDI+对象的小包装类。GDI+是非托管代码。位图占用非托管内存。当位图较大时,会显示很多信息
NET垃圾收集器确保非托管系统资源与终结器线程一起释放。问题是,只有当您创建足够数量的托管对象以触发垃圾回收时,它才会启动。这对Bitmap类来说不太好,在垃圾收集堆的第0代填满之前,您可以创建数千个位图。在到达那里之前,非托管内存将用完
需要管理您使用的位图的生存期。当不再使用Dispose()方法时调用它
在这种特殊情况下,当图像仍在PictureBox中使用时,无法对其进行处理。您可以使用“交换”新图像与旧图像,然后处置旧图像。因为PictureBox不再使用旧图像,所以它还可以。我怀疑它是否在该函数的调用者中,在您处理完从该函数返回的
位图之后,它是否被处理掉了?@kennyzx,感谢您的回复。你是对的!我不得不释放位图,我想.net
会自动处理它。我已经更新了这个问题,你能回答吗?这行是不是this->pictureBox1->Invoke(d,bmpimg)代码>意味着this->pictureBox1->Invoke(spd,bmpimg)代码>?没错!现在编辑。。此问题有解决方法吗?有。
System::Drawing::Bitmap^ MatToBitmap(const cv::Mat& img)
{
PixelFormat fmt(PixelFormat::Format24bppRgb);
Bitmap ^bmpimg = gcnew Bitmap(img.cols, img.rows, fmt); //unfortunately making this variable global didn't help
BitmapData ^data = bmpimg->LockBits(System::Drawing::Rectangle(0, 0, img.cols, img.rows), ImageLockMode::WriteOnly, fmt);
byte *dstData = reinterpret_cast<byte*>(data->Scan0.ToPointer());
unsigned char *srcData = img.data;
for (int row = 0; row < data->Height; ++row)
memcpy(reinterpret_cast<void*>(&dstData[row*data->Stride]), reinterpret_cast<void*>(&srcData[row*img.step]), img.cols*img.channels());
bmpimg->UnlockBits(data);
return bmpimg;
}
private: delegate Void SetPicDelegate(System::Drawing::Image ^pic);
SetPicDelegate^ spd;
System::Threading::Thread ^user_Thread;
private: Void Main()
{
user_Thread= gcnew System::Threading::Thread(gcnew ThreadStart(this, &MainClass::run));
user_Thread->Start();
}
private: void run()
{
while(true)
{
cv::Mat img; //opencv variable to hold image
///code to grab image from webcam using opencv
Bitmap ^bmpimg;
spd = gcnew SetPicDelegate(this, &MainClass::DisplayPic);
bmpimg = MatToBitmap(img);
this->pictureBox1->Invoke(spd, bmpimg);
delete bmpimg;
//above line helps control of memory usage, but image will not be displayed
//perhaps it will be displayed and immediately removed!
}
}
private: Void DisplayPic(System::Drawing::Image ^pic)
{
try { this->pictureBox1->Image = pic; }catch (...) {}
}