c# - 在 C# 中将所有视频帧提取为图像的最快方法是什么?
问题描述
我创建了一个应用程序来从视频中提取每一帧。它还不完美,并且有很多问题。问题之一是需要多长时间。提取 3 分钟视频的帧花了整整 2 小时,原始视频是 4 分钟,但在视频快完成后它给了我一个内存错误:
'OpenCV:分配 2764800 字节失败'
所以,完成任务需要很长时间,并且有一些错误我正在使用 Emgu.CV 和 MediaToolkit
这是我的代码:
using Emgu.CV;
using MediaToolkit;
using MediaToolkit.Model;
string file;
private void CreateFrames()
{
int i = 0;
VideoCapture _video = new VideoCapture(file);
var videoInfo = new MediaFile { Filename = file };
using (var engine = new Engine()) { engine.GetMetadata(videoInfo); }
while (i <= videoInfo.Metadata.Duration.Milliseconds * videoInfo.Metadata.VideoData.Fps)
{
Mat m = new Mat();
_video.Read(m);
_video.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosFrames, i);
preview.Image = _video.QueryFrame().ToBitmap();
Bitmap bitmap = _video.QueryFrame().ToBitmap();
bitmap.Save(String.Format(@"C:\\frames\\videoframe-{0}.png", i),
ImageFormat.Png);
i++;
}
}
private async void browse_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog.ShowDialog();
if (result == DialogResult.OK)
{
file = openFileDialog.FileName;
var videoInfo = new MediaFile { Filename = file };
using (var engine = new Engine()) { engine.GetMetadata(videoInfo); }
label1.Text = videoInfo.Metadata.VideoData.Fps + " \n" +
videoInfo.Metadata.Duration.ToString();
// must be run on a second thread else it will not work and it will freeze
Task getframes = new Task(CreateFrames);
getframes.Start();
}
}
如果有人有解决方案来加快速度并可能解决内存问题,我将不胜感激。
解决方案
这是一个使用 just 的实现Emgu.CV
(我不熟悉MediaToolKit
)。
using (var video = new VideoCapture(file))
using (var img = new Mat())
{
while (video.Grab())
{
video.Retrieve(img);
var filename = Path.Combine(outputDirectory, $"{i}.png");
CvInvoke.Imwrite(filename, img);
i++;
}
}
mp4
我在全高清视频上对此进行了测试。不知道确切的编解码器。使用我的 CPU (i7-8700k),每帧大约需要 65 毫秒。但是请考虑您是否需要使用该png
格式,因为它的编码速度很慢。如果您不想要任何压缩损失并且您的硬盘足够快且足够大bmp
,则每帧只需 13 毫秒。jpg
需要 40 毫秒。
推荐阅读
- ffmpeg - FFmpeg drawtext 和使用 sendcmd/zmq 的实时坐标
- html - 引导程序 4:添加行或添加 col-12 之间的区别?
- c# - 从快速操作和重构中提取缺少的接口
- java - Android 片段中的 Mapbox SDK
- rest - REST 响应为 {}
- php - 如何检查您是否在分页单篇文章的最后一页?
- html - 如何动态分隔表格(以 div 开始,以其他 div 结束)
- c# - 使用 Powershell (New-ScriptBlockCallback) 的 Httplistener 异步处理 - 仍然阻塞
- regex - 正则表达式匹配所有内容,直到第一次出现 Golang 风格的字符串
- laravel - Laravel 5.8 图片上传失败