好的,我一直在尝试使用网络摄像头拍摄视频。我有一个Lumenera Infinity 2显微镜,我试图从中提取饲料,并希望能够在进入时修改饲料。由于我找不到使用Video Source Player的方法,我决定改为拉出每个帧(相机的最大15fps)作为位图,以便我可以在那里进行修改。
问题是:我有一个巨大的内存泄漏。当我使用videoSourcePlayer运行视频时,它使用大约30兆的徘徊。当我将帧拉成位图时,它会在几秒钟内打破1 gig的内存。
我想念的是什么?我认为自动垃圾收集会在旧框架无法访问时挖出旧框架。我应该尝试强制在位图上进行垃圾回收吗?或者它完全是另一回事,而且我还是错过了它。
FilterInfoCollection captureDevices;
VideoCaptureDevice cam;
Bitmap bitmap;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
captureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (captureDevices.Count == 0)
throw new ApplicationException();
CameraSelectComboBox.Items.Clear();
foreach (FilterInfo device in captureDevices)
{
CameraSelectComboBox.Items.Add(device.Name);
}
CameraSelectComboBox.SelectedIndex = 0;
CameraSelectComboBox.Enabled = true;
}
catch (ApplicationException)
{
CameraSelectComboBox.Enabled = false;
}
}
private void connectButton_Click(object sender, EventArgs e)
{
cam = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
cam.NewFrame -= Handle_New_Frame; //Just to avoid the possibility of a second event handler being put on
cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
videoSourcePlayer1.Visible = false;
cam.Start();
//videoPictureBox1.Visible = false;
//videoSourcePlayer1.VideoSource = new VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
//videoSourcePlayer1.Start();
}
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
bitmap = (Bitmap)eventArgs.Frame.Clone();
videoPictureBox1.Image = bitmap;
}
答案 0 :(得分:2)
我认为这是一个可以改进的领域:
cam = new
VideoCaptureDevice(captureDevices[CameraSelectComboBox.SelectedIndex].MonikerString);
cam.NewFrame -= Handle_New_Frame; // you're pointing to the new instance of VCD, so this will have no effect.
cam.NewFrame += new AForge.Video.NewFrameEventHandler(Handle_New_Frame);
videoSourcePlayer1.Visible = false;
cam.Start();
每次按下连接按钮时,该代码块都会丢失内存。
你几乎需要在主要级别引用VCD。因此,在Form1类级别定义成员变量:
private VideoCaptureDevice _cameraContext;
在connect事件处理程序中,执行以下操作:
if (_camerContext != null)
{
_cameraContext.NewFrame -= Handle_New_Frame;
}
_cameraContext = new VideoCaptureDevice(blah blah blah);
_cameraContext.NewFrame += Handle_New_Frame;
videoSourcePlayer1.Visible = false;
_cameraContext.Start();
顺便说一句,我假设你是.NET 3.5或更高版本,因此是新的委托分配语法。
答案 1 :(得分:2)
试试这个:
private void Handle_New_Frame(object sender, NewFrameEventArgs eventArgs)
{
if(bitmap != null)
bitmap.Dispose();
bitmap = new Bitmap(eventArgs.Frame);
if(videoPictureBox1.Image != null)
this.Invoke(new MethodInvoker(delegate() {videoPictureBox1.Image.Dispose();}));
videoPictureBox1.Image = bitmap;
}
它解决了我在Aforge和PictureBoxes中遇到的一些内存泄漏,但VideoSourcePlayer在内存消耗方面要好得多。