使用 EmguCV QueryGrayFrame() 处理视频时如何解决此内存不足异常
How to fix this Out OF Memory Exception when Processing a video using EmguCV QueryGrayFrame()
我已经研究了一段时间了,但我仍然找不到问题的根源。
首先请注意,所有视频均为 15 秒,总共 450 帧。框架稍后将调整为 50x50。
使用 EmguCv,我使用以下例程获取视频的所有帧:
public void PopulateAllFrames()
{
int FramesCount = 0;
try
{
FramesCount = (int)capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
for (int i = 0; i < FramesCount; i++)
{
var frame = capture.QueryGrayFrame(); // Error here
var resized = frame.Resize(ImageWidth, ImageHeight, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
AllFrames.Add(resized.Copy());
}
capture.Dispose();
GC.Collect();
}
catch (Exception ex)
{ }
}
当我通过单击按钮加载任何视频时,以上内容工作正常:
private void SelectAVideo_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog OpenFile = new OpenFileDialog();
if (OpenFile.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
OriginalVideo = new MyVideo(OpenFile.FileName, true);
OriginalVideo.PopulateAllFrames();
}
catch (Exception ex)
{}
}
但是当我加载包含 25 个视频的目录时,某些视频 不起作用。传过来的视频每次都是相同的视频,"errored"个视频也每次都是一样的:
private void LoadDirectory_Click(object sender, EventArgs e)
{
try
{
using (var fbd = new FolderBrowserDialog())
{
DialogResult result = fbd.ShowDialog();
if (result == DialogResult.OK && fbd.SelectedPath != null)
{
AllVideos = new List<MyVideo>();
AllVideosFileNames = Directory.GetFiles(fbd.SelectedPath).ToList();
for (int i = 0; i < AllVideosFileNames.Count(); i++) // loop the rest of the videos, start from the 5th video and till the end
{
MyVideo CurrentVideo = new MyVideo(AllVideosFileNames[i], false);
CurrentVideo.PopulateAllFrames();
AllVideos.Add(CurrentVideo);
}
}
catch (Exception ex)
{ }
}
每当我点击 QueryGrayFrame()
时,我每次执行时都会在同一组视频上得到 OutOfMemoryException
,即使我只加载了 10 个视频。并且没有模式(意味着错误不会只在最后 10 个索引上弹出......等等)。知道视频真的很小,如果我单独加载这些视频中的任何一个,它就可以正常工作。
我该如何解决这个问题?
如评论中所述,我只需要 .Dispose()
我的变量,因为我的视频很小,所以我没有想到这一点。事实证明,他们仍然占用了大量内存。所以这样做解决了问题:
for (int i = 0; i < FramesCount; i++)
{
var frame = capture.QueryGrayFrame(); // Error here
var resized = frame.Resize(ImageWidth, ImageHeight, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
AllFrames.Add(resized.Copy());
frame.Dispose();
resized.Dispose();
}
我已经研究了一段时间了,但我仍然找不到问题的根源。
首先请注意,所有视频均为 15 秒,总共 450 帧。框架稍后将调整为 50x50。
使用 EmguCv,我使用以下例程获取视频的所有帧:
public void PopulateAllFrames()
{
int FramesCount = 0;
try
{
FramesCount = (int)capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);
for (int i = 0; i < FramesCount; i++)
{
var frame = capture.QueryGrayFrame(); // Error here
var resized = frame.Resize(ImageWidth, ImageHeight, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
AllFrames.Add(resized.Copy());
}
capture.Dispose();
GC.Collect();
}
catch (Exception ex)
{ }
}
当我通过单击按钮加载任何视频时,以上内容工作正常:
private void SelectAVideo_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog OpenFile = new OpenFileDialog();
if (OpenFile.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
OriginalVideo = new MyVideo(OpenFile.FileName, true);
OriginalVideo.PopulateAllFrames();
}
catch (Exception ex)
{}
}
但是当我加载包含 25 个视频的目录时,某些视频 不起作用。传过来的视频每次都是相同的视频,"errored"个视频也每次都是一样的:
private void LoadDirectory_Click(object sender, EventArgs e)
{
try
{
using (var fbd = new FolderBrowserDialog())
{
DialogResult result = fbd.ShowDialog();
if (result == DialogResult.OK && fbd.SelectedPath != null)
{
AllVideos = new List<MyVideo>();
AllVideosFileNames = Directory.GetFiles(fbd.SelectedPath).ToList();
for (int i = 0; i < AllVideosFileNames.Count(); i++) // loop the rest of the videos, start from the 5th video and till the end
{
MyVideo CurrentVideo = new MyVideo(AllVideosFileNames[i], false);
CurrentVideo.PopulateAllFrames();
AllVideos.Add(CurrentVideo);
}
}
catch (Exception ex)
{ }
}
每当我点击 QueryGrayFrame()
时,我每次执行时都会在同一组视频上得到 OutOfMemoryException
,即使我只加载了 10 个视频。并且没有模式(意味着错误不会只在最后 10 个索引上弹出......等等)。知道视频真的很小,如果我单独加载这些视频中的任何一个,它就可以正常工作。
我该如何解决这个问题?
如评论中所述,我只需要 .Dispose()
我的变量,因为我的视频很小,所以我没有想到这一点。事实证明,他们仍然占用了大量内存。所以这样做解决了问题:
for (int i = 0; i < FramesCount; i++)
{
var frame = capture.QueryGrayFrame(); // Error here
var resized = frame.Resize(ImageWidth, ImageHeight, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
AllFrames.Add(resized.Copy());
frame.Dispose();
resized.Dispose();
}