将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 (...) {}
}