首页 > 解决方案 > 在 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();
        }
    }

如果有人有解决方案来加快速度并可能解决内存问题,我将不胜感激。

标签: c#emgucv

解决方案


这是一个使用 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 毫秒。


推荐阅读