You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C#与EmguCV 3.0的视频读取及帧流处理技术咨询

如何在EmguCV 3.0中获取视频帧流并实现暂停/停止功能

嘿,看你已经搞定了视频文件选择和Capture初始化这一步,接下来咱们一步步把帧流获取、暂停/停止功能落地~

先回顾下你已经写好的代码,方便后续衔接:

OpenFileDialog ofd1 = new OpenFileDialog(); 
ofd1.Filter = "All Videos Files |*.dat; *.wmv; *.3g2; *.3gp; *.3gp2; *.3gpp; *.amv; *.asf; *.avi; *.bin; *.cue; *.divx; *.dv; *.flv; *.gxf; *.iso; *.m1v; *.m2v; *.m2t; *.m2ts; *.m4v; *.mkv; *.mov; *.mp2; *.mp2v; *.mp4; *.mp4v; *.mpa; *.mpe; *.mpeg; *.mpeg1; *.mpeg2; *.mpeg4; *.mpg; *.mpv2; *.mts; *.nsv; *.nuv; *.ogg; *.ogm; *.ogv; *.ogx; *.ps; *.rec; *.rm; *.rmvb; *.tod; *.ts; *.tts; *.vob; *.vro; *.webm"; 
ofd1.InitialDirectory = @"C:"; 
ofd1.Title = "Please select a video file."; 
if (ofd1.ShowDialog() == DialogResult.OK) { 
    vCapture = new Capture(ofd1.FileName.ToString()); 
    Image<Bgr, byte> img = vCapture.QueryFrame(); 
}

1. 持续获取视频帧流

你现在用QueryFrame()只能拿到单帧,要实现持续的帧流获取,在WinForms项目里最稳妥的方式是用Timer控件(避免阻塞UI线程),具体步骤如下:

第一步:声明全局变量

在你的窗体类顶部声明几个全局变量,方便在多个方法里访问:

private Capture _vCapture;
private Timer _frameTimer;
private bool _isPaused = false; // 用来标记暂停状态

第二步:初始化Timer并绑定帧获取事件

修改你现有代码的if块,添加Timer的初始化逻辑:

if (ofd1.ShowDialog() == DialogResult.OK) {
    // 先释放之前的Capture资源(如果存在),避免内存泄漏
    _vCapture?.Dispose();
    _vCapture = new Capture(ofd1.FileName);
    
    // 根据视频帧率设置定时器间隔(比如30帧/秒的话,间隔就是~33ms)
    int frameInterval = (int)(1000 / _vCapture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps));
    _frameTimer = new Timer { Interval = frameInterval };
    _frameTimer.Tick += FrameTimer_Tick;
    _frameTimer.Start();
}

第三步:实现帧获取的Timer事件

在这个事件里,我们会持续调用QueryFrame()获取帧,还能处理帧的显示或后续分析:

private void FrameTimer_Tick(object sender, EventArgs e) {
    // 如果Capture为空或处于暂停状态,直接返回
    if (_vCapture == null || _isPaused) return;
    
    // 获取当前帧,用using自动释放资源
    using (Image<Bgr, byte> currentFrame = _vCapture.QueryFrame()) {
        if (currentFrame != null) {
            // 这里可以把帧显示到PictureBox(假设你有一个名为pictureBox1的控件)
            pictureBox1.Image = currentFrame.Bitmap;
            // 也可以在这里添加你的帧处理逻辑(比如图像识别、特征提取等)
        } else {
            // 视频播放完毕,停止定时器
            _frameTimer.Stop();
            MessageBox.Show("视频播放结束");
        }
    }
}

2. 实现暂停/停止功能

暂停/继续功能

添加一个按钮(比如命名为btnPause),在点击事件里切换暂停状态:

private void btnPause_Click(object sender, EventArgs e) {
    _isPaused = !_isPaused;
    // 切换按钮文字,让用户清楚当前状态
    btnPause.Text = _isPaused ? "继续" : "暂停";
}

停止功能

添加一个停止按钮(命名为btnStop),点击后释放所有资源并重置状态:

private void btnStop_Click(object sender, EventArgs e) {
    // 停止定时器
    _frameTimer?.Stop();
    // 释放Capture资源
    _vCapture?.Dispose();
    _vCapture = null;
    // 清空显示控件
    pictureBox1.Image = null;
    // 重置按钮状态
    btnPause.Text = "暂停";
    _isPaused = false;
}

额外注意事项

  • 记得在窗体关闭时释放资源,避免内存泄漏:
    protected override void OnFormClosing(FormClosingEventArgs e) {
        _frameTimer?.Stop();
        _vCapture?.Dispose();
        base.OnFormClosing(e);
    }
    
  • EmguCV 3.0的QueryFrame()会自动跳过空帧,但还是要判断currentFrame != null,避免视频播放结束时出现空引用异常。

内容的提问来源于stack exchange,提问作者Munib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:00:40