我目前正在尝试用图像制作电影,但我找不到任何有用的东西。
这是迄今为止我的代码:
import time
from PIL import ImageGrab
x =0
while True:
try:
x+= 1
ImageGrab().grab().save('img{}.png'.format(str(x))
except:
movie = #Idontknow
for _ in range(x):
movie.save("img{}.png".format(str(_)))
movie.save()
您可以考虑使用 ffmpeg 等外部工具将图像合并到电影中(参见答案此处),或者您可以尝试使用 OpenCv 将图像合并到电影中,如示例此处。
我在下面附加了一段代码片段,我用来将名为“images”的文件夹中的所有 png 文件合并到视频中。
import cv2
import os
image_folder = 'images'
video_name = 'video.avi'
images = [img for img in os.listdir(image_folder) if img.endswith(".png")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 1, (width,height))
for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
这个答案中评论最多的部分似乎是VideoWriter的使用。您可以在这个答案(静态)的链接中查找它的文档,或者您可以自己进行一些挖掘。第一个参数是文件名,后跟一个整数(文档中的fourcc,使用的编解码器)、FPS 计数和帧尺寸的元组。如果您真的喜欢挖掘那些蠕虫,这里是 fourcc 视频编解码器列表。
谢谢,但我找到了使用 ffmpeg 的替代解决方案:
def save():
os.system("ffmpeg -r 1 -i img%01d.png -vcodec mpeg4 -y movie.mp4")
但是谢谢你的帮助:)
这是一个使用 moviepy 的最小示例。对我来说,这是最简单的解决方案。
import os
import moviepy.video.io.ImageSequenceClip
image_folder='folder_with_images'
fps=1
image_files = [os.path.join(image_folder,img)
for img in os.listdir(image_folder)
if img.endswith(".png")]
clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(image_files, fps=fps)
clip.write_videofile('my_video.mp4')
我使用
ffmpeg-python
绑定。您可以在此处找到更多信息。
import ffmpeg
(
ffmpeg
.input('/path/to/jpegs/*.jpg', pattern_type='glob', framerate=25)
.output('movie.mp4')
.run()
)
使用 moviepy 的
ImageSequenceClip
时,图像按顺序排列非常重要。
虽然文档指出框架可以在引擎盖下按字母数字顺序排序,但我发现事实并非如此。
因此,如果您遇到问题,请务必先手动订购框架。
@Wei Shan Lee(和其他人):当然,我的整个代码看起来像这样
import os
import moviepy.video.io.ImageSequenceClip
from PIL import Image, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
image_files = []
for img_number in range(1,20):
image_files.append(path_to_images + 'image_folder/image_' + str(img_number) + '.png')
fps = 30
clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(image_files, fps=fps)
clip.write_videofile(path_to_videos + 'my_new_video.mp4')
我创建了一个函数来执行此操作。与第一个答案(使用 opencv)类似,但想补充一点,对我来说,“.mp4”格式不起作用。这就是我在函数中使用加注的原因。
import cv2
import typing
def write_video(video_path_out:str,
frames_sequence:typing.Tuple[np.ndarray,...]):
if ".mp4" in video_path_out: raise ValueError("[ERROR] This method does not support .mp4; try .avi instead")
height, width, _ = frames_sequence[0].shape
# 0 means no preprocesing
# 1 means each image will be played with 1 sec delay (1fps)
out = cv2.VideoWriter(video_path_out,0, 1,(width,height))
for frame in frames_sequence:
out.write(frame)
out.release()
# you can use as much images as you need, I just use 3 for this example
# put your img1_path,img2_path, img3_path
img1 = cv2.imread(img1_path)
img2 = cv2.imread(img2_path)
img3 = cv2.imread(img3_path)
# img1 can be cv2.imread out; which is a np.ndarray; you can also se PIL
# if you'd like to.
frames_sequence = [img1,img2,img3]
write_video(video_path_out = "mypath_outvideo.avi",
frames_sequence = frames_sequence
)
希望有用!
有点 hacky,但避免创建文件,只是让您实时观看它。
import glob
from PIL import Image
import cv2
import numpy as np
import time
####### PARAMS
imgs_path = "/Users/user/Desktop/lidar_rig/ouster_data_wide_angle_cam_v9/imgs/*"
cur_img_index = 0
ds_st_index = 0
ds_en_index = -1
fps = 35 # tweak this
###### PARAMS
def cnvt_pil_to_cv2(pil_img):
open_cv_image = np.array(pil_img)
# Convert RGB to BGR
open_cv_image = open_cv_image[:, :, ::-1].copy()
return open_cv_image
img_files = sorted(glob.glob(imgs_path), key = lambda x: int(x.split('/')[-1].split('.')[0]))[ds_st_index:ds_en_index][cur_img_index:]
cnt = 0
for img_pth in img_files:
if not cnt %50: ## DDD -- avoid mem overflow
cv2.destroyAllWindows()
img = Image.open(img_pth).resize((750,750))
cv2.imshow(img_pth.split("/")[-1], cnvt_pil_to_cv2(img))
time.sleep(float(1.0/float(fps)))
cnt+=1
作为额外贡献,如果有人难以按字母顺序对加载的图像进行排序,这里有一个使用内置排序(os.listdir(image_folder))函数的版本。
import os
import moviepy.video.io.ImageSequenceClip
from PIL import Image, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
image_folder='frames'
fps=10
image_files = [os.path.join(image_folder,img)
for img in sorted(os.listdir(image_folder))
if img.endswith(".png")]
print(image_files)
clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(image_files, fps=fps)
clip.write_videofile('myvideo.mp4')
但是,请注意,它取决于文件系统/文件名,并且会将数字排序错误(1,10,2,3…)。下面是另一个带有
sorted_alphanumeric(data)
函数的解决方案,可以解决这个问题(来自另一个 线程)
import os
import moviepy.video.io.ImageSequenceClip
from PIL import Image, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
image_folder='frames'
fps=10
import re
def sorted_alphanumeric(data):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
return sorted(data, key=alphanum_key)
image_files = [os.path.join(image_folder,img)
for img in sorted_alphanumeric(os.listdir(image_folder))
if img.endswith(".png")]
print(image_files)
clip = moviepy.video.io.ImageSequenceClip.ImageSequenceClip(image_files, fps=fps)
clip.write_videofile('myvideo.mp4')