实现功能:


  1. 播放视频
  2. 提取每一帧图片并保存
  3. 显示视频播放的时间
    videowrite 视频保存的方法还未调试成功,等待后续再继续研究!


    //----------------------------------------------------------------------------
    // Copyright (C) 2004-2019 by EMGU Corporation. All rights reserved.
    //----------------------------------------------------------------------------

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using Emgu.CV;
    using Emgu.CV.CvEnum;
    using Emgu.CV.Structure;
    using Emgu.Util;

    using System.Threading;

    namespace CameraCapture
    {
    public partial class CameraCapture : Form
    {
    private VideoCapture _capture = null;
    private bool _captureInProgress;
    private Mat _frame, _frame1;
    private Mat _grayFrame;
    private Mat _smallGrayFrame;
    private Mat _smoothedGrayFrame;
    private Mat _cannyFrame;
    private double FrameRate;
    private int cam,count;
    Bitmap bmp;
    //VideoWriter _Wvideo;

    //private Image<Bgr, byte> frame = new Image<Bgr, byte>("你好.jpg");
    //参考链接 https://blog.csdn.net/cuoban/article/details/50555953
    public CameraCapture()
    {
    InitializeComponent();
    Control.CheckForIllegalCrossThreadCalls = false;//加入这句话,不过治标不治本
    //使用显卡处理图像数据效率会很多,如果你的设备支持,最好打开,使用CvInvoke.HaveOpenCLCompatibleGpuDevice能返回是否支持.
    // 配置CvInvoke.UseOpenCL能让OpenCV 启用或者停用 GPU运算
    //CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;
    CvInvoke.UseOpenCL = false;
    count = 0;
    try
    {
    //构造一个摄像头实例,如果调用本地摄像机则括号里面为空
    _capture = new VideoCapture(@"C:\Users\Administrator\Desktop\video\vtest.avi");
    _capture.ImageGrabbed += ProcessFrame;//图像捕捉事件
    double TotalFrames = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
    _capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 96);
    _capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 128);//FrameWidth=3视频流的帧宽度(只对摄像头有效)
    // FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS);
    FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);//帧率
    // MessageBox.Show(FrameRate.ToString());
    cam = 0;
    }
    catch (NullReferenceException excpt)
    {
    MessageBox.Show(excpt.Message);
    }
    _frame = new Mat();
    _frame1 = new Mat();
    _grayFrame = new Mat();
    _smallGrayFrame = new Mat();
    _smoothedGrayFrame = new Mat();
    _cannyFrame = new Mat();



    }

    private void ProcessFrame(object sender, EventArgs arg)
    {

    /* if (_capture != null && _capture.Ptr != IntPtr.Zero)
    // if (_capture != null)
    {
    _capture.Retrieve(_frame, 0); //_capture.RetrieveBgrFrame(); 老版本写法 得到捕捉到的帧数据。
    // _frame1 = _capture.QueryFrame();
    // pictureBox1.Image = _frame1.ToBitmap();

    CvInvoke.CvtColor(_frame, _grayFrame, ColorConversion.Bgr2Gray);

    CvInvoke.PyrDown(_grayFrame, _smallGrayFrame);
    //进行高斯向下采样,执行高斯金字塔分解步骤向下采样。固定原图像,
    //删除指定行和列(可以全为奇数行和列,或者偶数行和列...),从而减小图像的宽度和高度。

    CvInvoke.PyrUp(_smallGrayFrame, _smoothedGrayFrame);
    //执行高斯金字塔分解向上采样,首先透过注入固定行和列0像素值,在通过插值算法,对插入行列进行插值,这样用于放大原图像的四倍。
    //参数解析:IInputArraysrc:输入图像,即原图像。IOutputArraydst:输出图像,采样后得到的图像。

    CvInvoke.Canny(_smoothedGrayFrame, _cannyFrame, 100, 60);
    //多级边缘检测算法

    captureImageBox.Image = _frame;
    grayscaleImageBox.Image = _grayFrame;
    smoothedGrayscaleImageBox.Image = _smoothedGrayFrame;
    cannyImageBox.Image = _cannyFrame;*/
    try
    {
    Double Framesno = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosFrames);
    _capture.Retrieve(_frame, 0);
    if (_frame != null)
    {
    //pictureBox1.Image = _frame.Bitmap;
    captureImageBox.Image = _frame;
    Thread.Sleep((int)(1000.0 / FrameRate));

    //保存图片
    bmp = new Bitmap(_frame.Bitmap);
    bmp.Save(@"D:\image\"+count+".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
    bmp.Dispose();
    count++;

    // _Wvideo = new VideoWriter(@"D:\image\1.avi", -1,10,new Size(_frame.Cols, _frame.Rows),true);
    if (cam == 0)
    {
    int Video_seek = (int)(Framesno);
    double time_index = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosMsec);
    label5.Text = "Time: " + TimeSpan.FromMilliseconds(time_index).ToString().Substring(0, 8);
    // double framenumber = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
    // Frame_lbl.Text = "Frame: " + framenumber.ToString();

    }
    if (cam == 1)
    {
    //Frame_lbl.Text = "Frame: " + (webcam_frm_cnt++).ToString();
    }
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.Message.ToString());
    }


    }

    private void captureButtonClick(object sender, EventArgs e)
    {
    if (_capture != null)
    {
    if (_captureInProgress)
    { //stop the capture
    captureButton.Text = "Start Capture";
    _capture.Pause();
    }
    else
    {
    //start the capture
    captureButton.Text = "Stop";
    _capture.Start();
    }

    _captureInProgress = !_captureInProgress;
    }
    }
    //Dispose意为释放,释放组件所占用的内存。
    //C#特性,为提高运行效率,自动会释放已使用过且不再需要使用的组件来减少程序的CPU使用率。
    //默认会在程序运行一段时间后自动加载该Dispose方法,或者可以显式的自行调用此方法。
    private void ReleaseData()
    {
    if (_capture != null)

    _capture.Dispose();

    }

    private void FlipHorizontalButtonClick(object sender, EventArgs e)
    {
    // 得到和设置Capture类是否进行水平翻转。

    if (_capture != null) _capture.FlipHorizontal = !_capture.FlipHorizontal;
    }

    private void FlipVerticalButtonClick(object sender, EventArgs e)
    {
    if (_capture != null) _capture.FlipVertical = !_capture.FlipVertical;
    }
    }
    }

    要显示视频播放的时间可以以下两种方式:

    Emgucv视频操作--进阶1_帧率


    1. 初始化代码中加: Control.CheckForIllegalCrossThreadCalls = false;//加入这句话,不过治标不治本 视频播放还可以用
    2. 使用委托:SetText("Time: " + TimeSpan.FromMilliseconds(time_index).ToString().Substring(0, 8));



    private delegate void SetTextDelegate(string value);
    private void SetText(string value)
    {
    if (this.InvokeRequired)
    {
    SetTextDelegate d = new SetTextDelegate(SetText);
    object arg = (object)value;//要传入的参数值
    this.Invoke(d, arg);//这里参数不对。

    }
    else
    {
    this.label5.Text = value;
    }
    }

    QueryFrame() 去实现



      //----------------------------------------------------------------------------
      // Copyright (C) 2004-2019 by EMGU Corporation. All rights reserved.
      //----------------------------------------------------------------------------

      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Text;
      using System.Windows.Forms;
      using Emgu.CV;
      using Emgu.CV.CvEnum;
      using Emgu.CV.Structure;
      using Emgu.Util;

      using System.Threading;

      namespace WindowsFormsApplication40
      {
      public partial class Form1 : Form
      {
      private VideoCapture _capture = null;
      private Mat _frame;
      private double FrameRate;

      //private Image<Bgr, byte> frame = new Image<Bgr, byte>("你好.jpg");
      //参考链接 https://blog.csdn.net/cuoban/article/details/50555953
      public Form1()
      {
      InitializeComponent();
      //使用显卡处理图像数据效率会很多,如果你的设备支持,最好打开,使用CvInvoke.HaveOpenCLCompatibleGpuDevice能返回是否支持.
      // 配置CvInvoke.UseOpenCL能让OpenCV 启用或者停用 GPU运算
      //CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;
      CvInvoke.UseOpenCL = false;
      try
      {
      Application.Idle += Application_Idle;
      //构造一个摄像头实例,如果调用本地摄像机则括号里面为空
      //Application.Idle += new EventHandler(Application_Idle);//也可以
      _capture = new VideoCapture(@"C:\Users\Administrator\Desktop\video\vtest.avi");
      double TotalFrames = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
      FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);//帧率


      }
      catch (NullReferenceException excpt)
      {
      MessageBox.Show(excpt.Message);
      }



      }

      private void Application_Idle(object sender, EventArgs e)
      {
      try
      {

      _frame = _capture.QueryFrame();
      if (_frame != null)
      {
      System.Threading.Thread.Sleep((int)(1000.0 / FrameRate - 5));
      pictureBox1.Image = _frame.Bitmap;

      GC.Collect();
      }
      }
      catch (Exception ex)
      {
      MessageBox.Show(ex.Message.ToString());
      }


      }


      //Dispose意为释放,释放组件所占用的内存。
      //C#特性,为提高运行效率,自动会释放已使用过且不再需要使用的组件来减少程序的CPU使用率。
      //默认会在程序运行一段时间后自动加载该Dispose方法,或者可以显式的自行调用此方法。
      private void ReleaseData()
      {
      if (_capture != null)

      _capture.Dispose();

      }


      }
      }

      项目拓展:

      点击按钮选择需要播放的视频进行播放


        //----------------------------------------------------------------------------
        // Copyright (C) 2004-2019 by EMGU Corporation. All rights reserved.
        //----------------------------------------------------------------------------

        using System;
        using System.Collections.Generic;
        using System.ComponentModel;
        using System.Data;
        using System.Drawing;
        using System.Text;
        using System.Windows.Forms;
        using Emgu.CV;
        using Emgu.CV.CvEnum;
        using Emgu.CV.Structure;
        using Emgu.Util;

        using System.Threading;

        namespace WindowsFormsApplication40
        {
        public partial class Form1 : Form
        {
        private VideoCapture _capture = null;
        private Mat _frame;
        private double FrameRate;

        //private Image<Bgr, byte> frame = new Image<Bgr, byte>("你好.jpg");
        //参考链接 https://blog.csdn.net/cuoban/article/details/50555953
        public Form1()
        {
        InitializeComponent();
        //使用显卡处理图像数据效率会很多,如果你的设备支持,最好打开,使用CvInvoke.HaveOpenCLCompatibleGpuDevice能返回是否支持.
        // 配置CvInvoke.UseOpenCL能让OpenCV 启用或者停用 GPU运算
        //CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;
        CvInvoke.UseOpenCL = false;
        try
        {
        // Application.Idle += Application_Idle;
        //Application.Idle += new EventHandler(Application_Idle);
        //构造一个摄像头实例,如果调用本地摄像机则括号里面为空
        // _capture = new VideoCapture(@"C:\Users\Administrator\Desktop\video\vtest.avi");
        // double TotalFrames = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
        //FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);//帧率


        }
        catch (NullReferenceException excpt)
        {
        MessageBox.Show(excpt.Message);
        }



        }

        private void Application_Idle(object sender, EventArgs e)
        {
        try
        {

        _frame = _capture.QueryFrame();
        if (_frame != null)
        {
        System.Threading.Thread.Sleep((int)(1000.0 / FrameRate - 5));
        pictureBox1.Image = _frame.Bitmap;

        double time_index = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosMsec);
        label1.Text = "Time: " + TimeSpan.FromMilliseconds(time_index).ToString().Substring(0, 8);
        GC.Collect();
        }
        }
        catch (Exception ex)
        {
        MessageBox.Show(ex.Message.ToString());
        }


        }


        //Dispose意为释放,释放组件所占用的内存。
        //C#特性,为提高运行效率,自动会释放已使用过且不再需要使用的组件来减少程序的CPU使用率。
        //默认会在程序运行一段时间后自动加载该Dispose方法,或者可以显式的自行调用此方法。
        private void ReleaseData()
        {
        if (_capture != null)

        _capture.Dispose();

        }

        private void button1_Click(object sender, EventArgs e)
        {
        OpenFileDialog op = new OpenFileDialog();
        if(op.ShowDialog() == DialogResult.OK)
        {
        try
        {

        _capture = new VideoCapture(op.FileName);
        double TotalFrames = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
        FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);//帧率
        Application.Idle += new EventHandler(Application_Idle);

        }
        catch (Exception ex)
        {
        MessageBox.Show(ex.Message.ToString());
        }


        }
        }
        }
        }

        Emgucv视频操作--进阶1_帧率_02