winforms 使用雅阁时,出现参数无效异常,如何解决?

lqfhib0f  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(127)

我想从mp4视频文件中提取所有帧并将其显示在PictureBox上。
原始代码来自这个Q&A:
How to time the presentation and extraction of frames from a video file?
单击行上的开始按钮后发生异常:

var frame = videoReader.ReadVideoFrame();

信息

System.ArgumentException
  HResult=0x80070057
  Message=Parameter is not valid.
  Source=System.Drawing
  StackTrace:
   at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
   at Accord.Video.FFMPEG.VideoFileReader.DecodeVideoFrame(BitmapData bitmapData)
   at Accord.Video.FFMPEG.VideoFileReader.readVideoFrame(Int32 frameIndex, BitmapData output)
   at Accord.Video.FFMPEG.VideoFileReader.ReadVideoFrame()
   at Extract_Frames.Form1.<GetVideoFramesAsync>d__15.MoveNext() in D:\Csharp Projects\Extract Frames\Form1.cs:line 114
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Extract_Frames.Form1.<buttonStart_Click>d__17.MoveNext() in D:\Csharp Projects\Extract Frames\Form1.cs:line 151

完整代码

using Accord.IO;
using Accord.Video;
using Accord.Video.FFMPEG;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Extract_Frames
{
    public partial class Form1 : Form
    {
        Bitmap frame = null;
        Graphics frameGraphics = null;
        bool isVideoRunning = false;
        IProgress<Bitmap> videoProgress = null;
        private CancellationTokenSource cts = null;
        private readonly object syncRoot = new object();
        private static long pause = 0;
        private int frameRate = 0;
        private List<Bitmap> frames = new List<Bitmap>();
        string fileName;

        public Form1()
        {
            InitializeComponent();
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void StopPlayback(bool cancel)
        {
            lock (syncRoot)
            {
                if (cancel) cts?.Cancel();
                cts?.Dispose();
                cts = null;
            }
        }

        int counter =1;
        private void Updater(Bitmap videoFrame)
        {
            frames.Add(videoFrame);

            label1.Text = "Current Frame Number : " + counter;
            trackBar1.Value = counter;
            counter++;

            //Size size = new Size(videoFrame.Width, videoFrame.Height);
            //pictureBox1.ClientSize = size;
            using (videoFrame) frameGraphics.DrawImage(videoFrame, Point.Empty);

            pictureBox1.Invalidate();
        }

        private async Task GetVideoFramesAsync(IProgress<Bitmap> updater, string fileName, int intervalMs, CancellationToken token = default)
        {
            using (var videoReader = new VideoFileReader())
            {
                if (token.IsCancellationRequested) return;
                videoReader.Open(fileName);

                videoReader.ReadVideoFrame(1);
                trackBar1.Value = 1;

                label1.Text = "Current Frame Number : " + counter.ToString();

                while (true)
                {
                    if (Interlocked.Read(ref pause) == 0)
                    {
                        var frame = videoReader.ReadVideoFrame();

                        if (token.IsCancellationRequested || frame is null) break;
                        updater.Report(frame);
                    }
                    await Task.Delay(frameRate).ConfigureAwait(false);
                }
            }
        }

        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            frameRate = trackBar2.Value / 25;
        }

        private async void buttonStart_Click(object sender, EventArgs e)
        {
            string fileName = textBox1.Text;

            if (isVideoRunning) return;
            isVideoRunning = true;

            using (var videoReader = new VideoFileReader())
            {
                videoReader.Open(fileName);
                frame = new Bitmap(videoReader.Width + 2, videoReader.Height + 2);
                trackBar1.Maximum = (int)videoReader.FrameCount;
            }

            videoProgress = new Progress<Bitmap>((bitmap) => Updater(bitmap));
            cts = new CancellationTokenSource();
            pictureBox1.Image = frame;
            try
            {
                frameGraphics = Graphics.FromImage(frame);
                // Set the fame rate to 25 frames per second
                //int frameRate = 1000 / 25;
                await GetVideoFramesAsync(videoProgress, fileName, frameRate, cts.Token);
            }
            finally
            {
                frameGraphics?.Dispose();
                StopPlayback(false);
                isVideoRunning = false;
            }
        }

        private void buttonPause_Click(object sender, EventArgs e)
        {
            if (pause == 0)
            {
                buttonPause.Text = "Resume";
                Interlocked.Increment(ref pause);
            }
            else
            {
                Interlocked.Decrement(ref pause);
                buttonPause.Text = "Pause";
            }
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            StopPlayback(true);
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (isVideoRunning) StopPlayback(true);
            pictureBox1.Image?.Dispose();
            base.OnFormClosing(e);
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            ControlPaint.DrawBorder(e.Graphics, pictureBox1.ClientRectangle, Color.Red, ButtonBorderStyle.Solid);
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            pictureBox1.Image = frames[trackBar1.Value];
        }

        private void button1_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.InitialDirectory = "c:\\";
                openFileDialog.Filter = "video files (*.mp4)|*.mp4|All files (*.*)|*.*";
                openFileDialog.FilterIndex = 2;
                openFileDialog.RestoreDirectory = true;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    //Get the path of specified file
                    textBox1.Text = openFileDialog.FileName;
                }
            }
        }
    }
}
gblwokeq

gblwokeq1#

你可以使用一个叫做Emgu CV的库来实现这一点,但由于EmguCV使用名为Mat的容器来存储图像的位图,因此您需要定义一个Mat列表,并循环遍历视频中的帧,然后将它们添加到列表中。第一步是安装名为Emgu.cv.runtime.windows的Nuget包然后将下面的代码放入触发阅读过程的事件处理程序中。

//at the top of your Form1.cs file import the Emgu Cv library
using Emgu.CV;
using Emgu.CV.Structure;

//the code below goes to the button handler for reading the frames

//declare the path to the video
string videoPath = "video.mp4";
//list to hold the frames read from the video
List<Mat> frames = new List<Mat>();
//open the video with emgu cv video capture class
var video = new VideoCapture(videoPath);
//useful line for reading the frame rate from the video
var frameRate = (int)new VideoCapture(videoPath).Get(Emgu.CV.CvEnum.CapProp.Fps);
while (video. Grab())
 {
  //read a frame and add to the list
  var mat = new Mat();
  video.Read(mat);
  //add the frame to the list
  frames.Add(mat);
}
//do something with the frames, for example access the frame at index 0 and display in the picture box
var first_mat = frames[0];
if(first_mat!=null){
   var outputFile = "1.png";
   //there is no direct way to get a bitmap from a Mat so save to a file and 
   //use the file as an image location
   first_mat.Save(outputFile);
   pictureBox.ImageLocation = outputFile;
}

相关问题