简单的 Emgucv 网络摄像头提要似乎存在内存泄漏
Simple Emgucv webcam feed appears to be memory leaking
以下代码是我在一个更大的项目中从网络摄像头检索帧的方法:
Imports Emgu.CV
Imports Emgu.CV.CvEnum
Imports Emgu.CV.Structure
Imports Emgu.CV.UI
Imports Emgu.CV.Util
Public Class Form1
Dim img As Mat
Dim cam As VideoCapture
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
cam = New VideoCapture(0)
Catch ex As Exception
'show error via message box
MessageBox.Show("unable To read from webcam, error: " + Environment.NewLine + Environment.NewLine +
ex.Message + Environment.NewLine + Environment.NewLine +
"Try another")
Return
End Try
AddHandler Application.Idle, New EventHandler(AddressOf Me.ProcessFrame)
End Sub
Sub ProcessFrame(sender As Object, arg As EventArgs)
img = cam.QueryFrame()
ImageBox1.Image = img
End Sub
End Class
基本上它从网络摄像头抓取一个帧并将其插入到表单的图像框中。当 运行 代码时,我的内存消耗如下所示:
https://i.imgur.com/PRGULG9.png
据我所知,有些东西没有得到妥善处理,但我无法弄清楚它是什么。网络摄像头的 MP 越多,内存峰值就越高。加载本地视频文件时也是如此。
正如您在链接图像中看到的,内存消耗仅通过垃圾收集器 (GC) 减少,垃圾收集器 (GC) 基于固定时间周期执行(因此振荡)。
您的代码在不释放捕获设备的情况下进入 ProcessFrame()。我建议使用 [VideoCapture].release() 作为详细 here 来解决问题。如果您需要一致的帧率,则无法避免这些内存峰值。
读取帧是视频处理中最慢的部分之一。您的最小示例不足以帮助解决内存泄漏问题(如果确实存在的话)。确保您没有在循环中重复创建视频捕捉对象。
Mat
class 实现 IDisposable
。在显示新图像之前在旧图像上调用 Dispose()
可能有助于最大程度地减少尖峰,但正如 Lucas K 提到的那样,在 GC 运行之前并不能保证所有内容都被完全释放。
img = cam.QueryFrame()
'Dispose of the old image (if one exists).
If ImageBox1.Image IsNot Nothing Then ImageBox1.Image.Dispose()
ImageBox1.Image = img
一般来说,您应该在使用完 IDisposable
后对所有实现 IDisposable
的 类 调用 Dispose()
(或者在适用的情况下将它们包装在 Using
blocks 中) .
以下代码是我在一个更大的项目中从网络摄像头检索帧的方法:
Imports Emgu.CV
Imports Emgu.CV.CvEnum
Imports Emgu.CV.Structure
Imports Emgu.CV.UI
Imports Emgu.CV.Util
Public Class Form1
Dim img As Mat
Dim cam As VideoCapture
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
cam = New VideoCapture(0)
Catch ex As Exception
'show error via message box
MessageBox.Show("unable To read from webcam, error: " + Environment.NewLine + Environment.NewLine +
ex.Message + Environment.NewLine + Environment.NewLine +
"Try another")
Return
End Try
AddHandler Application.Idle, New EventHandler(AddressOf Me.ProcessFrame)
End Sub
Sub ProcessFrame(sender As Object, arg As EventArgs)
img = cam.QueryFrame()
ImageBox1.Image = img
End Sub
End Class
基本上它从网络摄像头抓取一个帧并将其插入到表单的图像框中。当 运行 代码时,我的内存消耗如下所示:
https://i.imgur.com/PRGULG9.png
据我所知,有些东西没有得到妥善处理,但我无法弄清楚它是什么。网络摄像头的 MP 越多,内存峰值就越高。加载本地视频文件时也是如此。
正如您在链接图像中看到的,内存消耗仅通过垃圾收集器 (GC) 减少,垃圾收集器 (GC) 基于固定时间周期执行(因此振荡)。 您的代码在不释放捕获设备的情况下进入 ProcessFrame()。我建议使用 [VideoCapture].release() 作为详细 here 来解决问题。如果您需要一致的帧率,则无法避免这些内存峰值。
读取帧是视频处理中最慢的部分之一。您的最小示例不足以帮助解决内存泄漏问题(如果确实存在的话)。确保您没有在循环中重复创建视频捕捉对象。
Mat
class 实现 IDisposable
。在显示新图像之前在旧图像上调用 Dispose()
可能有助于最大程度地减少尖峰,但正如 Lucas K 提到的那样,在 GC 运行之前并不能保证所有内容都被完全释放。
img = cam.QueryFrame()
'Dispose of the old image (if one exists).
If ImageBox1.Image IsNot Nothing Then ImageBox1.Image.Dispose()
ImageBox1.Image = img
一般来说,您应该在使用完 IDisposable
后对所有实现 IDisposable
的 类 调用 Dispose()
(或者在适用的情况下将它们包装在 Using
blocks 中) .