To convert Mat
to BitMap
, i used below code from 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;
}
First i grab image from webcam(Opencv) then pass Mat
to above method, then display the BitMap
in winform(C++/Cli).
i call above method for every frame in a video. while this happens, i noticed that memory consumption increases exponentially (in Visual Studio's Diagnostic tool)
in few seconds i get OutOfMemoryException
(when memory usage crosses 2 GB, where as only 250mb is sufficient)
how to release all resources in above method after it finishes execution
can anybody point the issue?
Thanks
Update: i had to dispose/delete Bitmap
, once i release Bitmap
, memory usage remains constant(around 177mb) but image will not be displayed. all methods are called from user-defined thread, so i had to to use delegate then invoke UI component (PictureBox to display pic). below is the full code
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 (...) {}
}
Some modification needed in run
method, to retain current Bitmap until next one arrives?