我正在尝试从磁盘打开一个视频文件并尝试使用openCV包装器播放它:Visual Studio c#中的Emgu CV。我使用Emgu CV提供的imagebox在表单上显示我的视频。我使用以下代码计算显示下一帧视频的等待时间:
await Task.Delay(Convert.ToInt32( 1000.0 / FPS));
问题是视频播放速度比计算公式慢。 我打开29.97 FPS视频文件,公式应该返回(1000/30)= 33。但是当我播放视频时,我可以立即看到视频播放速度低于33 FPS。如果我通过右键单击图像框来转到我的图像框属性,它表示FPS是21,我猜是实际的FPS视频正在播放。 发生了什么事?
这是我的代码。它非常基础:
public partial class Form1 : Form
{
VideoCapture videoCapture;
double FPS;
double totalFrames;
int currentFrameNo;
public Form1()
{
InitializeComponent();
}
private void btnOpen_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
videoCapture = new VideoCapture(ofd.FileName);
FPS = videoCapture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);
totalFrames = videoCapture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
currentFrameNo = 0;
}
}
private async void btnPlay_Click(object sender, EventArgs e)
{
while (currentFrameNo<totalFrames)
{
imageBox1.Image = videoCapture.QueryFrame();
currentFrameNo += 1;
await Task.Delay(Convert.ToInt32( 1000.0 / FPS));
}
}
}
我想要的是一场流畅的比赛。应该改变什么? 对不好的语言感到抱歉。
答案 0 :(得分:0)
正如其他评论所暗示的那样 - 问题是无论循环处理时间是多少都会增加一个恒定的延迟。
更好的解决方案是使用Timer(大致!),如下所示:
bool playingVideo = false;
Timer frameTimer = new Timer(this.GrabFrame, null, 0, 1000 / 33);
private void btnPlay_Click(object sender, EventArgs e)
{
playingVideo = true;
}
private void GrabFrame(object sender, EventArgs e)
{
if(playingVideo)
{
while (currentFrameNo<totalFrames)
{
imageBox1.Image = videoCapture.QueryFrame();
currentFrameNo += 1;
}
}
}
这样,无论捕获时间如何,都将每隔33ms请求帧