[英]convert numpy.ndarray into video
在我的代碼中,我正在循環播放視頻的幀,並嘗試生成另一個 mp4 視頻。
這是我的代碼:
cap = cv2.VideoCapture(args.video)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (frame_width, frame_height))
while cap.isOpened():
ret, img = cap.read()
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
out.release()
break
#<code>...
#<code>...
print(type(my_image))
out.write(my_image)
print(type(my_image))
的輸出是每幀的numpy.ndarray
。 當我運行代碼時,我得到了output_video.mp4
文件,但重量只有 300 kb(它需要大約 50 mb)。
我嘗試將每一幀保存為圖像,並查看它是否可以工作,並且確實有效。 這是代碼:
img = Image.fromarray(my_image, 'RGB')
img.save('frameeeee-%s.png'%i)
我編寫了這個函數來解決一個類似的問題,您需要將圖像單獨保存到一個文件夾中,然后您可以使用 frames2video 將其轉換為視頻。
def frames2video( path_in = "/content/original_frames" , path_out = "/content/outputvideo",
frame_rate = 30 , video_name="output_video" ):
"""
Given an input path to a folder that contains a set of frames, this function
convert them into a video and then save it in the path_out.
You need to know the fps of the original video, are 30 by default.
"""
img_path_list = natsorted(os.listdir(path_in))
assert(len(img_path_list)>0)
img_array = []
print("[F2V] Frames to video...", end="\n\n")
with tqdm(total=len(img_path_list)) as pbar:
for count,filename in enumerate(img_path_list):
img = cv2.imread(path_in+"/"+filename)
if(img is None):break
height, width, layers = img.shape
img_array.append(img)
size = (width,height)
pbar.update()
if os.path.exists(path_out): shutil.rmtree(path_out)
os.mkdir(path_out)
out = cv2.VideoWriter(path_out+"/"+str(video_name)+'.mp4', cv2.VideoWriter_fourcc(*'DIVX'), frame_rate, size)
for i in range(len(img_array)):
out.write(img_array[i])
out.release()
print("\n[F2V] Video made from "+str(count+1)+" frames", end="\n\n")
為了完整起見,我還發布了反之亦然,一個給定視頻提取幀的函數。
def n_frames(video):
"""
Given an input video returns the EXACT number of frames(CV2 was not precise)
"""
success = True
count = 0
while success:
success,image = video.read()
if success == False: break
count+=1
return count
def video2frames( path_in = "/content/video.mp4" , path_out = "/content/original_frames",
n_of_frames_to_save = 999999, rotate=True, frames_name = "OrigFrame" ):
"""
Given a video from path_in saves all the frames inside path_out.
The number of frames(in case of long videos) can be truncated with
the n_of_frames_to_save parameter. Rotate is used to save rotated
frames by 90 degree. All the frames are named frames_name with an
index
"""
blur_threshold = 0
if os.path.exists(path_out): shutil.rmtree(path_out)
os.mkdir(path_out)
count = 0
success = True
vidcap = cv2.VideoCapture(path_in)
v2 = cv2.VideoCapture(path_in)
fps = vidcap.get(cv2.CAP_PROP_FPS)
if(fps>120):
print("CAP_PROP_FPS > 120, probabily you are using a webcam. Setting fps manually")
fps = 25
n_of_frames = n_frames(v2) # #int(video.get(cv2.CAP_PROP_FRAME_COUNT)) is not accurate, https://stackoverflow.com/questions/31472155/python-opencv-cv2-cv-cv-cap-prop-frame-count-get-wrong-numbers
if(n_of_frames_to_save < n_of_frames): n_of_frames = n_of_frames_to_save
print("[V2F] Dividing the video in " + str(n_of_frames) + " frames", end="\n\n")
for count in trange(n_of_frames):
success,image = vidcap.read()
if not success: break
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
if(rotate): image = cv2.rotate(image,cv2.ROTATE_90_CLOCKWISE)
plt.imsave("%s/%s%d.png" % (path_out,frames_name+"_", count), image)
count+=1
print("\n[V2F] "+str(count)+" frames saved",end="\n\n")
return fps
好的,我找到了解決方案。 我注意到我的代碼中有resize
函數:
my_image = cv2.resize(image_before, (1280, 720))
所以我改變了
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (frame_width, frame_height))
至
out = cv2.VideoWriter('outputttttt.mp4', fourcc, fps, (1280, 720))
它有效(:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.