Float division by zero in clip duration: 在剪辑时发生浮点数除以零的错误。

huangapple go评论62阅读模式
英文:

Float division by zero in clip duration

问题

以下是您要翻译的内容:

"When using the main function for all the videos in a directory, this error 'division by zero' happens, but for just for a video file it doesn't happen, I used fmod function instead of /, but it has the math domain error, Could you please tell me how I can fix it?

! pip install python-opencv moviepy
from google.colab import drive
root = '/content/gdrive/'
drive.mount(root)
from datetime import timedelta
import cv2
import numpy as np
import os
# i.e if video of duration 30 seconds, saves 10 frame per second = 300 frames saved in total
SAVING_FRAMES_PER_SECOND = 10
def format_timedelta(td):
    """Utility function to format timedelta objects in a cool way (e.g 00:00:20.05)
    omitting microseconds and retaining milliseconds"""
    result = str(td)
    try:
        result, ms = result.split(".")
    except ValueError:
        return (result + ".00").replace(":", "-")
    ms = int(ms)
    ms = round(ms / 1e4)
    return f"{result}.{ms:02}".replace(":", "-")
def get_saving_frames_durations(cap, saving_fps):
    """A function that returns the list of durations where to save the frames"""
    s = []
    # get the clip duration by dividing number of frames by the number of frames per second
    clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)
    # use np.arange() to make floating-point steps
    for i in np.arange(0, clip_duration, 1 / saving_fps):
        s.append(i)
    return s

def main(video_file):
    filename, _ = os.path.splitext(video_file)
    filename += "-opencv"
    # make a folder by the name of the video file
    if not os.path.isdir(filename):
        os.mkdir(filename)
    # read the video file
    cap = cv2.VideoCapture(video_file)
    # get the FPS of the video
    fps = cap.get(cv2.CAP_PROP_FPS)
    # if the SAVING_FRAMES_PER_SECOND is above video FPS, then set it to FPS (as maximum)
    saving_frames_per_second = min(fps, SAVING_FRAMES_PER_SECOND)
    # get the list of duration spots to save
    saving_frames_durations = get_saving_frames_durations(cap, saving_frames_per_second)
    # start the loop
    count = 0
    while True:
        is_read, frame = cap.read()
        if not is_read:
            # break out of the loop if there are no frames to read
            break
        # get the duration by dividing the frame count by the FPS
        frame_duration = count / fps
        try:
            # get the earliest duration to save
            closest_duration = saving_frames_durations[0]
        except IndexError:
            # the list is empty, all duration frames were saved
            break
        if frame_duration >= closest_duration:
            # if closest duration is less than or equals the frame duration,
            # then save the frame
            frame_duration_formatted = format_timedelta(timedelta(seconds=frame_duration))
            cv2.imwrite(os.path.join(filename, f"frame{frame_duration_formatted}.jpg"), frame)
            # drop the duration spot from the list, since this duration spot is already saved
            try:
                saving_frames_durations.pop(0)
            except IndexError:
                pass
        # increment the frame count
        count += 1
import os
for filename in os.listdir('/content/gdrive/MyDrive/x/train_videos/Red'):
    if __name__ == "__main__":
    a = main(filename)
英文:

When using the main function for all the videos in a directory, this error 'division by zero' happens, but for just for a video file it doesn't happen, I used fmod function instead of /, but it has the math domain error, Could you please tell me how I can fix it?

! pip install python-opencv moviepy
from google.colab import drive
root = '/content/gdrive/'
drive.mount( root )
from datetime import timedelta
import cv2
import numpy as np
import os
# i.e if video of duration 30 seconds, saves 10 frame per second = 300 frames saved in total
SAVING_FRAMES_PER_SECOND = 10
def format_timedelta(td):
    """Utility function to format timedelta objects in a cool way (e.g 00:00:20.05) 
    omitting microseconds and retaining milliseconds"""
    result = str(td)
    try:
        result, ms = result.split(".")
    except ValueError:
        return (result + ".00").replace(":", "-")
    ms = int(ms)
    ms = round(ms / 1e4)
    return f"{result}.{ms:02}".replace(":", "-")
def get_saving_frames_durations(cap, saving_fps):
    """A function that returns the list of durations where to save the frames"""
    s = []
    # get the clip duration by dividing number of frames by the number of frames per second
    clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)
    # use np.arange() to make floating-point steps
    for i in np.arange(0, clip_duration, 1 / saving_fps):
        s.append(i)
    return s

def main(video_file):
    filename, _ = os.path.splitext(video_file)
    filename += "-opencv"
    # make a folder by the name of the video file
    if not os.path.isdir(filename):
        os.mkdir(filename)
    # read the video file    
    cap = cv2.VideoCapture(video_file)
    # get the FPS of the video
    fps = cap.get(cv2.CAP_PROP_FPS)
    # if the SAVING_FRAMES_PER_SECOND is above video FPS, then set it to FPS (as maximum)
    saving_frames_per_second = min(fps, SAVING_FRAMES_PER_SECOND)
    # get the list of duration spots to save
    saving_frames_durations = get_saving_frames_durations(cap, saving_frames_per_second)
    #start the loop
    count = 0
    while True:
        is_read, frame = cap.read()
        if not is_read:
            # break out of the loop if there are no frames to read
            break
        # get the duration by dividing the frame count by the FPS
        frame_duration = count / fps
        try:
            # get the earliest duration to save
            closest_duration = saving_frames_durations[0]
        except IndexError:
            # the list is empty, all duration frames were saved
            break
        if frame_duration >= closest_duration:
            # if closest duration is less than or equals the frame duration, 
            # then save the frame
            frame_duration_formatted = format_timedelta(timedelta(seconds=frame_duration))
            cv2.imwrite(os.path.join(filename, f"frame{frame_duration_formatted}.jpg"), frame) 
            # drop the duration spot from the list, since this duration spot is already saved
            try:
                saving_frames_durations.pop(0)
            except IndexError:
                pass
        # increment the frame count
        count += 1
import os
for filename in os.listdir('/content/gdrive/MyDrive/x/train_videos/Red'):
    if __name__ == "__main__":
    a=main(filename)

答案1

得分: 1

以下是您要翻译的内容:

"The issue looks like paths related.

When using for filename in os.listdir('/content/gdrive/MyDrive/x/train_videos/Red'):
The filename excludes the directory name.

Instead of getting filename:
/content/gdrive/MyDrive/x/train_videos/Red/vid1.mp4
/content/gdrive/MyDrive/x/train_videos/Red/vid2.mp4
/content/gdrive/MyDrive/x/train_videos/Red/vid3.mp4
...

We are getting filename:
vid1.mp4
vid2.mp4
vid3.mp4
...


cap = cv2.VideoCapture(video_file) tries to read the file from the default working directory (not sure where it is in Google Colab).
The video file doesn't exist in the default working directory.
We are getting zero framerate, and division by zero exception when executing:
clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS).

Note that cap.get(cv2.CAP_PROP_FPS) returns 0 if the file doesn't exist, or not a valid video file.

I recommend you to use the debugger for making sure that this is the case...


First, we may add protections form "division by zero" in get_saving_frames_durations method:

def get_saving_frames_durations(cap, saving_fps):
"""A function that returns the list of durations where to save the frames"""
s = []
# get the clip duration by dividing number of frames by the number of frames per second
#clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)
cap_fps = cap.get(cv2.CAP_PROP_FPS)
if cap_fps == 0:
cap_fps = 1  # Protection form "division by zero"
clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap_fps
if saving_fps == 0:
saving_period = 1  # Protection form "division by zero"
else:
saving_period = 1 / saving_fps
# use np.arange() to make floating-point steps
for i in np.arange(0, clip_duration, saving_period):
s.append(i)
return s

Second, we may skip the file when it's not a valid video file by checking cap.isOpened():

if not cap.isOpened():
return

Third, we may pass the "working directory" that contains the files to main method, and use os.path.join(working_dir, filename) where appropriate.


Updated code sample (without using Google Colab):

#from google.colab import drive
root = '/content/gdrive/'
#drive.mount( root )
from datetime import timedelta
import cv2
import numpy as np
import os
# i.e if video of duration 30 seconds, saves 10 frame per second = 300 frames saved in total
SAVING_FRAMES_PER_SECOND = 10
def format_timedelta(td):
"""Utility function to format timedelta objects in a cool way (e.g 00:00:20.05) 
omitting microseconds and retaining milliseconds"""
result = str(td)
try:
result, ms = result.split(".")
except ValueError:
return (result + ".00").replace(":", "-")
ms = int(ms)
ms = round(ms / 1e4)
return f"{result}.{ms:02}".replace(":", "-")
def get_saving_frames_durations(cap, saving_fps):
"""A function that returns the list of durations where to save the frames"""
s = []
# get the clip duration by dividing number of frames by the number of frames per second
#clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)
cap_fps = cap.get(cv2.CAP_PROP_FPS)
if cap_fps == 0:
cap_fps = 1  # Protection form "division by zero"
clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap_fps
if saving_fps == 0:
saving_period = 1  # Protection form "division by zero"
else:
saving_period = 1 / saving_fps
# use np.arange() to make floating-point steps
for i in np.arange(0, clip_duration, saving_period):
s.append(i)
return s
def main(working_dir, video_file):
filename, _ = os.path.splitext(video_file)
filename += "-opencv"
# read the video file
full_video_file = os.path.join(working_dir, video_file)  # Join the working directory and the file name
cap = cv2.VideoCapture(full_video_file) #cap = cv2.VideoCapture(video_file)
if not cap.isOpened():
return  # Skip the file if it's not a video file.
out_dir = os.path.join(working_dir, filename)
# make a folder by the name of the video file
if not os.path.isdir(out_dir):  #if not os.path.isdir(filename):
os.mkdir(out_dir) #os.mkdir(filename)
# get the FPS of the video
fps = cap.get(cv2.CAP_PROP_FPS)
# if the SAVING_FRAMES_PER_SECOND is above video FPS, then set it to FPS (as maximum)
saving_frames_per_second = min(fps, SAVING_FRAMES_PER_SECOND)
# get the list of duration spots to save
saving_frames_durations = get_saving_frames_durations(cap, saving_frames_per_second)
#start the loop
count = 0
while True:
is_read, frame = cap.read()
if not is_read:
# break out of the loop if there are no frames to read
break
# get the duration by dividing the frame count by the FPS
frame_duration = count / fps
try:
# get the earliest duration to save
closest_duration = saving_frames_durations[0]
except IndexError:
# the list is empty, all duration frames were saved
break
if frame_duration >= closest_duration:
# if closest duration is less than or equals the frame duration, 
# then save the frame
frame_duration_formatted = format_timedelta(timedelta(seconds=frame_duration))
cv2.imwrite(os.path.join(out_dir, f"frame{frame_duration_formatted}.jpg"), frame) #cv2.imwrite(os.path.join(filename, f"frame{frame_duration_formatted}.jpg"), frame)
# drop the duration spot from the list, since this duration spot is already saved
try:
saving_frames_durations.pop(0)
except IndexError:
pass
# increment the frame count
count += 1
import os
working_directory = '/content/gdrive/MyDrive/x/train_videos/Red'  # Assume the output directory is the same as the input directory (name it "working directory")
for filename in os.listdir(working_directory):
if __name__ == "__main__":
a = main
<details>
<summary>英文:</summary>
The issue looks like paths related.  
When using `for filename in os.listdir(&#39;/content/gdrive/MyDrive/x/train_videos/Red&#39;):`  
The `filename` excludes the directory name.  
Instead of getting `filename`:  
`/content/gdrive/MyDrive/x/train_videos/Red/vid1.mp4`  
`/content/gdrive/MyDrive/x/train_videos/Red/vid2.mp4`  
`/content/gdrive/MyDrive/x/train_videos/Red/vid3.mp4`  
...
We are getting `filename`:  
`vid1.mp4`  
`vid2.mp4`  
`vid3.mp4`  
...
---
`cap = cv2.VideoCapture(video_file)` tries to read the file from the default working directory (not sure where it is in Google Colab).  
The video file doesn&#39;t exist in the default working directory.  
We are getting zero framerate, and `division by zero` exception when executing:  
`clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)`.  
Note that `cap.get(cv2.CAP_PROP_FPS)` returns `0` if the file doesn&#39;t exist, or not a valid video file.  
I recommend you to use the debugger for making sure that this is the case...
---
First, we may add protections form &quot;division by zero&quot; in `get_saving_frames_durations` method:  
def get_saving_frames_durations(cap, saving_fps):
&quot;&quot;&quot;A function that returns the list of durations where to save the frames&quot;&quot;&quot;
s = []
# get the clip duration by dividing number of frames by the number of frames per second
#clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)
cap_fps = cap.get(cv2.CAP_PROP_FPS)
if cap_fps == 0:
cap_fps = 1  # Protection form &quot;division by zero&quot;
clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap_fps
if saving_fps == 0:
saving_period = 1  # Protection form &quot;division by zero&quot;
else:
saving_period = 1 / saving_fps
# use np.arange() to make floating-point steps
for i in np.arange(0, clip_duration, saving_period):
s.append(i)
return s
---
Second, we may skip the file when it&#39;s not a valid video file by checking `cap.isOpened()`:  
if not cap.isOpened():
return
---
Third, we may pass the &quot;working directory&quot; that contains the files to `main` method, and use `os.path.join(working_dir, filename)` where appropriate.  
---
Updated code sample (without using Google Colab):  
#from google.colab import drive
root = &#39;/content/gdrive/&#39;
#drive.mount( root )
from datetime import timedelta
import cv2
import numpy as np
import os
# i.e if video of duration 30 seconds, saves 10 frame per second = 300 frames saved in total
SAVING_FRAMES_PER_SECOND = 10
def format_timedelta(td):
&quot;&quot;&quot;Utility function to format timedelta objects in a cool way (e.g 00:00:20.05) 
omitting microseconds and retaining milliseconds&quot;&quot;&quot;
result = str(td)
try:
result, ms = result.split(&quot;.&quot;)
except ValueError:
return (result + &quot;.00&quot;).replace(&quot;:&quot;, &quot;-&quot;)
ms = int(ms)
ms = round(ms / 1e4)
return f&quot;{result}.{ms:02}&quot;.replace(&quot;:&quot;, &quot;-&quot;)
def get_saving_frames_durations(cap, saving_fps):
&quot;&quot;&quot;A function that returns the list of durations where to save the frames&quot;&quot;&quot;
s = []
# get the clip duration by dividing number of frames by the number of frames per second
#clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap.get(cv2.CAP_PROP_FPS)
cap_fps = cap.get(cv2.CAP_PROP_FPS)
if cap_fps == 0:
cap_fps = 1  # Protection form &quot;division by zero&quot;
clip_duration = cap.get(cv2.CAP_PROP_FRAME_COUNT) / cap_fps
if saving_fps == 0:
saving_period = 1  # Protection form &quot;division by zero&quot;
else:
saving_period = 1 / saving_fps
# use np.arange() to make floating-point steps
for i in np.arange(0, clip_duration, saving_period):
s.append(i)
return s
def main(working_dir, video_file):
filename, _ = os.path.splitext(video_file)
filename += &quot;-opencv&quot;
# read the video file
full_video_file = os.path.join(working_dir, video_file)  # Join the working directory and the file name
cap = cv2.VideoCapture(full_video_file) #cap = cv2.VideoCapture(video_file)
if not cap.isOpened():
return  # Skip the file if it&#39;s not a video file.
out_dir = os.path.join(working_dir, filename)
# make a folder by the name of the video file
if not os.path.isdir(out_dir):  #if not os.path.isdir(filename):
os.mkdir(out_dir) #os.mkdir(filename)
# get the FPS of the video
fps = cap.get(cv2.CAP_PROP_FPS)
# if the SAVING_FRAMES_PER_SECOND is above video FPS, then set it to FPS (as maximum)
saving_frames_per_second = min(fps, SAVING_FRAMES_PER_SECOND)
# get the list of duration spots to save
saving_frames_durations = get_saving_frames_durations(cap, saving_frames_per_second)
#start the loop
count = 0
while True:
is_read, frame = cap.read()
if not is_read:
# break out of the loop if there are no frames to read
break
# get the duration by dividing the frame count by the FPS
frame_duration = count / fps
try:
# get the earliest duration to save
closest_duration = saving_frames_durations[0]
except IndexError:
# the list is empty, all duration frames were saved
break
if frame_duration &gt;= closest_duration:
# if closest duration is less than or equals the frame duration, 
# then save the frame
frame_duration_formatted = format_timedelta(timedelta(seconds=frame_duration))
cv2.imwrite(os.path.join(out_dir, f&quot;frame{frame_duration_formatted}.jpg&quot;), frame) #cv2.imwrite(os.path.join(filename, f&quot;frame{frame_duration_formatted}.jpg&quot;), frame)
# drop the duration spot from the list, since this duration spot is already saved
try:
saving_frames_durations.pop(0)
except IndexError:
pass
# increment the frame count
count += 1
import os
working_directory = &#39;/content/gdrive/MyDrive/x/train_videos/Red&#39;  # Assume the output directory is the same as the input directory (name it &quot;working directory&quot;)
for filename in os.listdir(working_directory):
if __name__ == &quot;__main__&quot;:
a = main(working_directory, filename)
---
Note:  
In case you like to save the output images in other directory you may have to pass the output directory as argument to `main`, and update the code accordingly.
</details>

huangapple
  • 本文由 发表于 2023年5月7日 22:09:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76194438.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定