简体   繁体   中英

C# Why is my video frame rate slower using OpenCV VideoCapture?

I am trying to read a video (.mp4) from a file and showing it on a Imagebox on forms. When I time the total time it played, it's actually more than actual video length. For example, if video is actually 10 seconds, it played for 12-13 seconds. Why is that? The framerate for my video is 31fps

I tried to make sure fps variable has the correct framerate already.

private void Play_Video(string filePath)
{
    VideoCapture cameraCapture = new VideoCapture(filePath);

    var stopwatch = new Stopwatch();
    stopwatch.Start();
    while (true)
    {
        Mat m = new Mat();
        cameraCapture.Read(m);
        if (!m.IsEmpty)
        {
            imageBox1.Image = m;
            double fps = cameraCapture.GetCaptureProperty(CapProp.Fps);
            Thread.Sleep(1000 / Convert.ToInt32(fps));
        }
        else
        {
            break;
        }
    }
    stopwatch.Stop();
    double elapsed_time = stopwatch.ElapsedMilliseconds * 0.001;
    // My elapsed_time here shows about 13 seconds, when the actual length of video is 10 seconds. Why?
}

NEW EDIT: I updated retrieval of frames in a separate function as to not cause delay during render, but there is still a few seconds delay. For example 30 seconds video plays for 32-33 seconds. My updated code:

private void Play_Video(List<Mat> frames, double fps, Emgu.CV.UI.ImageBox imageBox)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();

    for (int i = 0; i < frames.Count; i++)
    {
        imageBox.Image = frames[i];
        Thread.Sleep(1000 / Convert.ToInt32(fps));
    }
    stopwatch.Stop();
    double elapsed_time = stopwatch.ElapsedMilliseconds * 0.001;
}

This was the only way I could get the exact fps because using thread.sleep takes 10-15 ms to cycle on and off. I had same problem with Task.Delay. This seems to work perfectly, if anyone has a better solution I would love to see it.

    private void PlayVideo()
    {
        double framecount = video.Get(Emgu.CV.CvEnum.CapProp.FrameCount);
        double fps = video.Get(Emgu.CV.CvEnum.CapProp.Fps);

        video.Set(Emgu.CV.CvEnum.CapProp.PosFrames, (double)(framecount * (double)(savePercent / 100)));
        int ms = Convert.ToInt32(((double)1000 / fps));

        while (disablePreviewTimer == false)
        {
            DateTime dt = DateTime.Now;
            Emgu.CV.Mat img = video.QueryFrame();
            if (img == null)
            {
                disablePreviewTimer = true;
                break;
            }
            else
            {
                Emgu.CV.Util.VectorOfByte vb = new Emgu.CV.Util.VectorOfByte();
                Emgu.CV.CvInvoke.Resize(img, img, PreviewSize);
                Emgu.CV.CvInvoke.Imencode(".jpg", img, vb);

                pictureBox5.Image = Image.FromStream(new MemoryStream(vb.ToArray()));
                Application.DoEvents();

                while ((DateTime.Now - dt).TotalMilliseconds < ms)
                {
                    Application.DoEvents();
                }

                label6.Text = ((int)(DateTime.Now - dt).TotalMilliseconds).ToString();
            }
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM