Emgu CV doesn't get all frames from video

2.5k Views Asked by At

I want to get and save all the frames from a ~30 second (30fps) video.

The program VirtualDub shows me that my movie has 930 frames, but my program saves only 474. My code is as follows:

string name = @"D:\movie-01-no.avi";
Capture _capture = new Capture(name);
int frame = 0;
while (_capture.Grab())
{
    frame++;
    Image<Bgr, byte> image = _capture.RetrieveBgrFrame();
    Bitmap bmp = new Bitmap(image.ToBitmap());
    bmp.Save(@"D:\" + frame + ".bmp");
    bmp.Dispose();
}

or

string name = @"D:\movie-01-no.avi";

Capture _capture = new Capture(name);
int frame = 0;
bool Reading = true;

while (Reading)
{
    frame++;
    Image<Bgr, Byte> image = _capture.QueryFrame();
    if (image != null)
    {
        Bitmap bmp = new Bitmap(image.ToBitmap());
        bmp.Save(@"D:\" + frame + ".bmp");
        bmp.Dispose();
    }
    else
    {
        Reading = false;
    }
}

In both cases it doesn't save 930 frames. Why? How I can fix it?

2

There are 2 best solutions below

0
On

I have found a solution. This program works correct. In description of video is information that video has 30 FPS. VirtualDub shows also 30 FPS. But VirtualDub duplicated frames to get a value of frames from description. Video has 15 FPS, but ViurualDub duplicated every second frames and it seems like 30 FPS. If you use standard camera to record video you have to know that when frames in video are dark your camera records 15 FPS. Camera records 30 FPS in bright places. I've checked this in Lumix camera and built-in web camera in laptop Acer.

0
On

I've had a hard time finding any documentation on Capture under Egmu CV V3.0.0

After performing some trail & error testing, I found that it appears both Grab and QueryFrame each process a frame, effectively making Grab() drop a frame each loop. This code appears to give the desired result:

video = new Capture(filename);
bool reading;

int nframes = (int)video.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
nframes++;

Mat frame;
Image<Bgr, byte> image;

int i = 0;

reading = true;

while (reading)
{
    frame = video.QueryFrame();
    if (frame != null)
    {
        image = frame.ToImage<Bgr, byte>();

        mainPic.Image = image.ToBitmap();

        image.Dispose();
        frame.Dispose();
    }
    else
    {
        reading = false;
    }
    i++;
}