0

Edit:

In short:

cap = cv2.VideoCapture(input_loc); 
fps = cap.get(cv2.CAP_PROP_FPS)

returns ZeroDivisionError: float division by zero starting from the 2nd video in the loop. (works fine on 1st video)

Note: already tried solution in Python OpenCV video.get(cv2.CAP_PROP_FPS) returns 0.0 FPS but didn't solve my issue.


I'm sorry that the title seems very vague since I'm not sure how to describe my issue.

To be short, I guess that OpenCV failed to load the video in started from the second video. Maybe it's because I forgot to reset something?

My goal is to extract frames from multiple videos, so I've implemented a function to do that:

def video_to_frames(input_loc, output_loc, filename, sec):
    """Function to extract frames from input video file
    and save them as separate frames in an output directory.
    Args:
        input_loc: Input video file.
        output_loc: Output directory to save the frames.
        filename: name of the video file
        sec: how many seconds per frame
    """
    
    try:
        os.mkdir(output_loc)
    except OSError:
        pass

    # Start capturing the feed
    cap = cv2.VideoCapture(input_loc)
        
    # Find the total duration of videos
    fps = cap.get(cv2.CAP_PROP_FPS)
    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    video_length = frame_count/fps
 
    print("Video Length:", video_length)
    

    count = 1
    timepoint = count*sec*1000
    
    # Start converting the video
    while cap.isOpened():
        # Extract the frame
        cap.set(cv2.CAP_PROP_POS_MSEC,(timepoint))      
        ret, frame = cap.read()
        
        for t in range(-2, 3):
            cap.set(cv2.CAP_PROP_POS_MSEC,(timepoint + t*50))
            ret, frame = cap.read()
            cv2.imwrite("{}{}-{}-{}.png".format(output_loc, filename[:-4], count-1, t+2), frame[:480, :640, :]) # the shape of frame should be consistent

        count = count + 1 # jump to the next frame
        timepoint = count*sec*1000


        # If there are no more frames left
        if (timepoint > ((video_length -1 ) *1000)):
            # Release the feed
            cap.release()
            # Print stats
            print ("{} frames extracted".format(count-1))

            break
    
    return  video_length, count

To execute this function, I put it in a loop

frames = 0
extracts = 0
total_frames = 0

for file_name in video_list:

    input_path = input_path + "{}".format(f)
    print (file_name)
    video_to_frames(input_path, output_path, file_name, 2)

cv2.destroyAllWindows()

My issue is that extracting the first file seems fine, but once it moves to the next file, there are some problems so I get an error like this:

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-55-002937137b8e> in <module>()
      7     input_path = input_path + "{}".format(f)
      8     print (file_name)
----> 9     video_to_frames(input_path, output_path, file_name, 2)
     10 
     11 cv2.destroyAllWindows()

<ipython-input-52-e4a4392eaa12> in video_to_frames(input_loc, output_loc, filename, sec)
     22     fps = cap.get(cv2.CAP_PROP_FPS)
     23     frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
---> 24     video_length = frame_count/fps
     25 
     26     print("Video Length:", video_length)

ZeroDivisionError: float division by zero

Anyone knows why and how should I deal with this?

sealpuppy
  • 615
  • 4
  • 12
  • 27
  • It's clear you get a division by 0. You could reduce your script down to `cap = cv2.VideoCapture(input_loc); fps = cap.get(cv2.CAP_PROP_FPS)` and ask why the fps is 0 for an equivalent, yet more concise question. – Reti43 Feb 15 '21 at 15:36
  • Does this answer your question? [Python OpenCV video.get(cv2.CAP\_PROP\_FPS) returns 0.0 FPS](https://stackoverflow.com/questions/49025795/python-opencv-video-getcv2-cap-prop-fps-returns-0-0-fps) – Reti43 Feb 15 '21 at 15:39
  • I tried the solution in that link, but it actually returns `Requirements already satisfied` – sealpuppy Feb 15 '21 at 15:42
  • Can you verify the file at `input_loc` actually exists? `cv2.VideoCapture()` will not raise an error when trying to load a non-existent file and extracting the fps will obviously return 0. – Reti43 Feb 15 '21 at 15:45
  • The list for the loop is generated by `video_list = sorted(os.listdir(input_path))`, so I guess it's not the issue? – sealpuppy Feb 15 '21 at 15:51
  • [os.listdir](https://stackoverflow.com/questions/3207219/how-do-i-list-all-files-of-a-directory) will also give you any directories that reside it. Can you ensure you only have valid videos files in that directory? In fact, can you print `input_path` inside the loop to see where exactly the program chokes? – Reti43 Feb 15 '21 at 15:58
  • I printed out the `input_path` of every loop and turns out the problem is ` input_path = input_path + "{}".format(f)` This line makes the input path wrong started from the 2nd file. Thank you so much. – sealpuppy Feb 15 '21 at 16:20

1 Answers1

0

The issue happens because of

input_path = input_path + "{}".format(f)

This line makes the input file name wrong and became something like this:

clip_2.avi24.36
sealpuppy
  • 615
  • 4
  • 12
  • 27