У меня есть проект о данных из вещания. Я написал разделение видео на кадр для python. Но я просто понял, что было бы лучше, если бы я мог снимать кадр видео только между черными кадрами. Возможно ли это? Я делюсь своим кодом;
import cv2
import time
import os
def video_to_frames(input_loc, output_loc):
"""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.
Returns:
None
"""
try:
os.mkdir(output_loc)
except OSError:
pass
# Log the time
time_start = time.time()
# Start capturing the feed
cap = cv2.VideoCapture(input_loc)
# Find the number of frames
video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - 1
print ("Number of frames: ", video_length)
count = 0
print ("Converting video..\n")
# Start converting the video
while cap.isOpened():
# Extract the frame
ret, frame = cap.read()
# Write the results back to output location.
cv2.imwrite(output_loc + "/%#05d.jpg" % (count+1), frame)
count = count + 1
# If there are no more frames left
if (count > (video_length-1)):
# Log the time again
time_end = time.time()
# Release the feed
cap.release()
# Print stats
print ("Done extracting frames.\n%d frames extracted" % count)
print ("It took %d seconds forconversion." % (time_end-time_start))
break
input_loc = 'try.mp4'
output_loc = 'try/'
video_to_frames(input_loc, output_loc)





Поскольку изображения в openCV (или в вашем случае кадры) представлены в виде массива numpy, их можно усреднить для низких значений (которые представляют черные кадры).
import numpy as np
# converts the frame to gray scale for easier computation
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if np.average(gray) < 20:
# skips an iteration, so the frame isn't saved
continue
В данном случае 20 — это порог, используемый для «черных изображений». Если у вас есть более легкие, вы можете увеличить эту константу. Таким образом, ваш общий код должен выглядеть примерно так:
import cv2
import numpy as np
import time
import os
def video_to_frames(input_loc, output_loc):
"""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.
Returns:
None
"""
try:
os.mkdir(output_loc)
except OSError:
pass
# Log the time
time_start = time.time()
# Start capturing the feed
cap = cv2.VideoCapture(input_loc)
# Find the number of frames
video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - 1
print("Number of frames: ", video_length)
count = 0
print("Converting video..\n")
# Start converting the video
while cap.isOpened():
# Extract the frame
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if np.average(gray) < 20:
# skips an iteration, so the frame isn't saved
continue
# Write the results back to output location.
cv2.imwrite(output_loc + "/%#05d.jpg" % (count+1), frame)
count = count + 1
# If there are no more frames left
if count > video_length-1:
# Log the time again
time_end = time.time()
# Release the feed
cap.release()
# Print stats
print("Done extracting frames.\n%d frames extracted" % count)
print("It took %d seconds forconversion." % (time_end-time_start))
break
input_loc = 'try.mp4'
output_loc = 'try/'
video_to_frames(input_loc, output_loc)
В моем случае у меня были некоторые кадры с большей частью черными, но не полностью черными. Они все еще были отмечены как черные рамки np.average(image) < 20. Вместо этого я использовал np.max(image) < 20, что в моем случае сработало очень хорошо. Как сказал Комрон, 20, возможно, придется скорректировать для вашего варианта использования.