GBMedusa
GBMedusa

Reputation: 183

Python, OpenCV: stopping capture at end of file

(Using OpenCV 4.1)

I am trying to capture screenshots from videos. My intention is to have the script capture a frame every five minutes up to 20 captures.

My test video is 20 minutes long. Once the script loops 4 times, I want it to quit. However, it loops a 5th time and captures 2 seconds from the end of the video. Then it loops a 6th time and captures the same frame as the 4th loop. It keeps repeating these last two loops until there are 20 frames captured.

How do I get the script to recognize that it has reached the end of the video and stop?

Note: the last frame captured may not be the last frame in the video. For example, if the video is 23 minutes long, the last frame captured should be near the 20-minute mark.

import datetime
import sys
import time

from cv2 import cv2


def milsec_to_hr_min_sec(milliseconds):  # Returned from CAP_PROP_POS_MSEC
    ms = int(milliseconds)
    seconds = str(int((ms / 1000) % 60))
    minutes = str(int((ms / (1000 * 60)) % 60))
    hours = str(int((ms / (1000 * 60 * 60)) % 24))
    return hours, minutes, seconds


def FrameCapture(path):  # Extract frame
    cap = cv2.VideoCapture(path)
    framerate = cap.get(cv2.CAP_PROP_FPS)
    count = 1
    framecount = 0

    # checks whether frames were extracted
    while True:
        while count < 21 and framecount < cap.get(cv2.CAP_PROP_FRAME_COUNT):
            # Capture frame every 5 minutes
            framecount = count * framerate * 60 * 5
            cap.set(1, framecount)

            # capture frame at timestamp
            success, image = cap.read()
            if success:
                cv2.imwrite(
                    path + " (screencap #%d).jpg" % count, image,
                )
                # Convert timestamp to hr:min:sec
                hours, minutes, seconds = milsec_to_hr_min_sec(
                    cap.get(cv2.CAP_PROP_POS_MSEC)
                )
                print(
                    str(success)
                    + " "
                    + "Captured: screencap #{} at timestamp ".format(count)
                    + hours
                    + "h "
                    + minutes
                    + "m "
                    + seconds
                    + "s"
                )
                count += 1
                if cv2.waitKey(1) & 0xFF == ord("q"):
                    break
            else:
                break

    # When everything done, release the capture
    cap.release()
    cv2.destroyAllWindows()
    print("Finished capture")


# Driver Code
if __name__ == "__main__":

    # Calling the function
    fn = "\\full\path\to\file"
    FrameCapture(fn)

Please forgive the hack-y nature of my scripts. I pieced them together with parts found from searches.

Upvotes: 2

Views: 8295

Answers (4)

A simple way is:

    sucess, img = cap.read()
    if img is None:
        print(' Successful process  ')
        break

You just have to add this line and process will be ended if 'cap' is empty

Upvotes: 0

m.hasheminejad
m.hasheminejad

Reputation: 71

At the beginning of the "while" loop you may use the following code:

ret, frames = cap.read()

if frames is None:

    break

Upvotes: 2

George
George

Reputation: 1

This code will get all frames from your video

def get_list_frame_by_video(file_path_video):
    vs = cv2.VideoCapture(file_path_video)
    list_frame = []

    print("____start load video____")
    len_frames = int(vs.get(cv2.CAP_PROP_FRAME_COUNT))
    while True:
        is_cap, frame = vs.read()
        if frame is None:
            continue
        list_frame.append(frame)
        if len_frames == len(list_frame):
            break

    print("____complete load video____")
    return list_frame

Upvotes: 0

Faizan Cassim
Faizan Cassim

Reputation: 19

There are two ways of doing it:

  • Loop through a while(true) loop and break when frame.empty().
  • Obtain the frame count using: int nFrames = vid_cap.get(CAP_PROP_FRAME_COUNT); //Get the number of frames avaiable in the video and use a for_loop to loop through the frames.

Upvotes: 0

Related Questions