OpenCvSharp视频采集与融合场景下内存泄漏问题如何解决
内存泄漏问题原因
- 未释放OpenCvSharp的Mat对象:
capture.Read(image)和capture2.Read(image2)每次读取生成的image、image2都是非托管的Mat资源,你没有主动释放,这是最核心的泄漏来源。 SetImageOpacity方法导致Bitmap泄漏:代码中先给bitimg赋值了从image2.Data创建的Bitmap,紧接着又用SetImageOpacity的返回值覆盖了bitimg,原有的Bitmap没有被Dispose,直接丢失引用造成泄漏。- 跨线程操作控件引发的资源泄漏:你在后台线程直接给
pictureBox.Image赋值,只有Dispose操作做了Invoke,不符合WinForm控件的线程安全要求,很容易出现旧Image资源没有被正确释放的问题。 - 资源释放顺序错误:你先Dispose了上一轮的
result,再替换pictureBox的Image,实际应该先把pictureBox的Image替换为新的result,再释放旧的Image资源,避免控件正在使用的资源被提前释放,也避免旧资源泄漏。
修复方案
- 每次循环结束后主动释放
image和image2两个Mat对象,调用Release()方法或者用using包裹Mat的创建。 - 调整
SetImageOpacity的调用逻辑,临时存储生成的半透明Bitmap,用完后同时释放原始的image2对应的Bitmap和半透明Bitmap。 - 所有对pictureBox的操作都放到Invoke里,保证在UI线程执行,调整Image替换和释放的顺序。
- 移除无意义的Thread.Sleep调用,避免不必要的线程等待。
修复后代码参考:
while (videoStreamFlag) { if(startFlag) { Mat image = null; Mat image2 = null; Bitmap baseBitmp = null; Bitmap opacityBmp = null; Bitmap result = null; try { image = new Mat(); image2 = new Mat(); capture2.Read(image2); capture.Read(image); if (image.Empty() || image2.Empty()) { videoStreamFlag = false; break; } // 创建底图 baseBitmp = new Bitmap(image.Width, image.Height, ((image.Width * 3 + 3) / 4) * 4, PixelFormat.Format24bppRgb, image.Data); result = new Bitmap(baseBitmp.Width, baseBitmp.Height); using (var g = Graphics.FromImage(result)) { g.DrawImageUnscaled(baseBitmp, 0, 0); baseBitmp.Dispose(); // 底图用完立刻释放 // 创建前景图 baseBitmp = new Bitmap(image2.Width, image2.Height, ((image2.Width * 3 + 3) / 4) * 4, PixelFormat.Format24bppRgb, image2.Data); opacityBmp = SetImageOpacity(baseBitmp, Opacity / 100f); baseBitmp.Dispose(); // 原始前景图用完释放 g.DrawImageUnscaled(opacityBmp, 0, 0); opacityBmp.Dispose(); // 半透明前景图用完释放 } // UI操作全部放到UI线程执行 panel.Invoke(new MethodInvoker(() => { var oldImg = pictureBox.Image; pictureBox.Image = result; oldImg?.Dispose(); // 替换后再释放旧图片 })); result = null; // 已经交给pictureBox,不用再手动释放 } catch (Exception ex) { Console.WriteLine("[ERROR!!!]VideoBlending Error...{0}", ex.Message); videoStreamFlag = false; // 异常时释放所有未释放的资源 result?.Dispose(); } finally { // 确保非托管资源一定释放 image?.Release(); image?.Dispose(); image2?.Release(); image2?.Dispose(); baseBitmp?.Dispose(); opacityBmp?.Dispose(); } } }
内容的提问来源于stack exchange,提问作者Oguzhan Öztürk
相关产品推荐
相关产品推荐

