【发布时间】:2023-04-09 10:47:01
【问题描述】:
要将Mat 转换为BitMap,我使用了here 的以下代码
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;
}
首先我从网络摄像头(Opencv)中抓取图像,然后将Mat 传递给上述方法,然后在winform(C++/Cli)中显示BitMap。
我为视频中的每一帧调用上述方法。发生这种情况时,我注意到内存消耗呈指数增长(在 Visual Studio 的诊断工具中)
在几秒钟内我得到 OutOfMemoryException(当内存使用量超过 2 GB 时,只有 250mb 就足够了)
上述方法执行完毕后如何释放所有资源
有人可以指出这个问题吗?
谢谢
更新:我不得不释放/删除Bitmap,一旦我释放Bitmap,内存使用量保持不变(大约177mb)但不会显示图像。所有方法都是从用户定义的线程调用的,所以我必须使用委托然后调用 UI 组件(PictureBox 来显示图片)。以下是完整代码
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 (...) {}
}
run 方法需要进行一些修改,以保留当前位图直到下一个到达?
【问题讨论】:
-
我怀疑它在这个函数的调用者中,在你处理完这个函数返回的
Bitmap之后,它被处理掉了吗? -
@kennyzx,感谢您的回复。你是对的!我不得不释放
Bitmap,我以为.net会自动处理它。我更新了问题,你能回答吗? -
这条线
this->pictureBox1->Invoke(d, bmpimg);是不是应该是this->pictureBox1->Invoke(spd, bmpimg);? -
没错!现在编辑..这个问题的任何解决方法?
标签: .net winforms visual-c++ memory-management memory-leaks