Emgu CV 是 OpenCV 的 .NET 封装,Emgu Capture 是用于视频捕获和处理的组件。当视频以超快速度播放时,通常是由于帧率控制不当导致的。
using Emgu.CV;
using Emgu.CV.Structure;
using System;
using System.Threading;
// 正确控制帧率的示例
public void PlayVideoWithFrameRate(string videoPath)
{
using (Capture capture = new Capture(videoPath))
{
double fps = capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);
int delay = (int)(1000 / fps); // 计算每帧应延迟的毫秒数
while (true)
{
using (Mat frame = capture.QueryFrame())
{
if (frame == null) break;
// 显示帧
CvInvoke.Imshow("Video", frame);
// 按帧率延迟
int key = CvInvoke.WaitKey(delay);
if (key == 27) break; // ESC键退出
}
}
}
CvInvoke.DestroyAllWindows();
}
对于更精确的帧率控制:
using System.Diagnostics;
// 使用高精度计时器
public void PlayVideoWithPreciseTiming(string videoPath)
{
using (Capture capture = new Capture(videoPath))
{
double fps = capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);
double frameInterval = 1000 / fps; // 毫秒
Stopwatch sw = new Stopwatch();
while (true)
{
sw.Restart();
using (Mat frame = capture.QueryFrame())
{
if (frame == null) break;
CvInvoke.Imshow("Video", frame);
int remainingTime = (int)(frameInterval - sw.ElapsedMilliseconds);
if (remainingTime > 0)
{
CvInvoke.WaitKey(remainingTime);
}
if (CvInvoke.WaitKey(1) == 27) break;
}
}
}
CvInvoke.DestroyAllWindows();
}
using System.Threading;
// 多线程处理方案
public void PlayVideoWithThread(string videoPath)
{
using (Capture capture = new Capture(videoPath))
{
double fps = capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);
int delay = (int)(1000 / fps);
bool isPlaying = true;
Thread playThread = new Thread(() =>
{
while (isPlaying)
{
using (Mat frame = capture.QueryFrame())
{
if (frame == null)
{
isPlaying = false;
break;
}
// 使用Invoke确保UI线程更新
CvInvoke.Imshow("Video", frame);
Thread.Sleep(delay);
}
}
});
playThread.Start();
while (true)
{
if (CvInvoke.WaitKey(1) == 27) // ESC键退出
{
isPlaying = false;
break;
}
}
playThread.Join();
}
CvInvoke.DestroyAllWindows();
}