Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV VideoCapture returns strange frame offset for different versions

I'm using opencv-python and when I execute the following code:

index = 0
cap = cv2.VideoCapture(video_path)
while True:
    offset = cap.get(cv2.CAP_PROP_POS_MSEC)
    print(cv2.__version__, index, offset)

    ok, frame = cap.read()
    if not ok:
        break
    index += 1

I get the following output:

3.4.7 0 0.0
3.4.7 1 33.36666666666667
3.4.7 2 66.73333333333333
3.4.7 3 100.10000000000001
3.4.7 4 133.46666666666667

If I execute this code on version 3.4.8.29, I get the following output:

3.4.8 0 0.0
3.4.8 1 0.0
3.4.8 2 33.36666666666667
3.4.8 3 66.73333333333333
3.4.8 4 100.10000000000001

And if I execute it on version 4.5.2.52 I get:

4.5.2 0 0.0
4.5.2 1 0.0
4.5.2 2 0.0
4.5.2 3 0.0
4.5.2 4 0.0

The question is first of all, which one is the correct one? It seems like 3.4.7 is correct, but it also seems to be changing randomly between versions.

And also how can I modify the other versions to get the proper result, same as 3.4.7

like image 578
user972014 Avatar asked Oct 10 '21 19:10

user972014


People also ask

What does cv2 VideoCapture return?

Next, we cay cap = cv2. VideoCapture(0) . This will return video from the first webcam on your computer.

How does OpenCV VideoCapture work?

Capture Video from Camera OpenCV allows a straightforward interface to capture live stream with the camera (webcam). It converts video into grayscale and display it. We need to create a VideoCapture object to capture a video. It accepts either the device index or the name of a video file.

How do I use VideoCapture in Python?

To capture a video in Python, use the cv2 VideoCapture class and then create an object of VideoCapture. VideoCapture has the device index or the name of a video file. The device index is just an integer to define a Camera. If we pass 0, it is for the first or primary camera, 1 for the second camera, etc.


1 Answers

I read the OpenCV docs and they said: "Reading / writing properties involves many layers. Some unexpected result might happens along this chain. Effective behaviour depends from device hardware, driver and API Backend." (source: https://docs.opencv.org/3.4.15/d4/d15/group__videoio__flags__base.html#gaeb8dd9c89c10a5c63c139bf7c4f5704d)

So in other words OpenCV does not guaranty consistent and reliable behavior of this function.

Also I installed openCV 4.5.2.52 and applied your script to one of my '.mp4' videos. Then I got the same result as you had for openCV version 3.4.8.29. So I think the behaviour you experience is not a 'bug', but rather the unreliable behavior of this function.

As work around you can compute the "offset" by dividing the frame number by the FPS count (see code below). Then you have more control over the behaviour and maybe more consisted results.

index = 0
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
while True:
    offset = cap.get(cv2.CAP_PROP_POS_MSEC)

    ok, frame = cap.read()
    if not ok:
        break
    
    # CAP_PROP_POS_MSEC
    print("CAP_PROP_POS_MSEC: ", index, offset)
    
    # Devide fps by frame number
    offset = cap.get(cv2.CAP_PROP_POS_FRAMES) / fps * 1000
    print("cv2.CAP_PROP_POS_FRAMES", index, offset)
     
    index += 1
like image 98
Thijs Ruigrok Avatar answered Oct 21 '22 13:10

Thijs Ruigrok