博客首页:knighthood2001 欢迎点赞评论️ ❤️ 热爱python,期待与大家一同进步成长!!❤️ 给大家推荐一款很火爆的刷题、面试求职网站 跟我一起来巩固基础、开启刷题之旅吧 |
这年头还不来尝试线稿图视频??
之前笔者也写过将视频转换为线稿图视频的教程,不过将其分成了五部分,也分了五个.py文件,这样虽然讲解很透彻,但是对于想要批量转换的话,每换一个视频,就要去每个.py文件中去修改相应的参数。因此显得非常麻烦。
因此本文将上述所有文件整合在一起,通过是需要更改视频文件名,即可输出相应的线稿图视频。这样就变得非常便捷了。
目录
一、目录介绍
二、模块导入
三、文件相关操作
四、获取原视频相应参数、逐帧保存
五、函数讲解
音频提取
原图-线稿图转换
生成无声视频
最终合成有声视频
调用函数
六、总结
一、目录介绍
在线稿图目录下,只需要有py文件和原视频(如dindin.mp4)即可,剩下的只需运行代码,其会自动生成。
代码最终生成的视频会放在和原视频同一目录下,而data文件夹下的内容,是代码运行过程中的其他文件,如分离出来的音频,转换前后的逐帧图片,无声视频。
本次例子以之前很火爆的叮叮当当舞。
二、模块导入
import osimport cv2from PIL import Imagefrom PIL import ImageFilterimport moviepy.editor as mp
三、文件相关操作
# TODO 更改文件名称file = 'dindin.mp4'filename = file.split(".")[0]mp3_file = f'{filename}.mp3'if not os.path.exists('data'): os.mkdir('data')path = os.path.join('data', filename)new_picture_path = os.path.join('data', filename + "_newpc")if not os.path.exists(path): os.mkdir(path)if not os.path.exists(new_picture_path): os.mkdir(new_picture_path)# 无声视频file_name = os.path.join('data', 'silence_' + file)
file = 'dindin.mp4'
file为原视频,放在代码相同目录下
注:一定要是英文,否则会因为编码问题出错
filename = file.split(".")[0]为提取到的文件无后缀名称
mp3_file = f'{filename}.mp3'为分离出来的mp3
if not os.path.exists('data'): os.mkdir('data')path = os.path.join('data', filename)new_picture_path = os.path.join('data', filename + "_newpc")if not os.path.exists(path): os.mkdir(path)if not os.path.exists(new_picture_path): os.mkdir(new_picture_path)
这段代码的意思是,首先判断是否有data文件夹,没有则创建。接下来
path = os.path.join('data', filename)new_picture_path = os.path.join('data', filename + "_newpc")表示data目录下存放两个文件夹,一个存放的是原视频的逐帧图片,另外一个存放的是新产生的线稿图片。接下来判断两个目录是否存在并创建。
# 无声视频file_name = os.path.join('data', 'silence_' + file)
将无声视频也存在data文件夹下面,因为也不是最终版本。
四、获取原视频相应参数、逐帧保存
cap = cv2.VideoCapture(file)fps = int(cap.get(cv2.CAP_PROP_FPS))width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))print('fps:', fps, '\n', 'width:', width, '\n', 'height:', height, '\n', 'frames:', frames)for i in range(0, frames): flag, frame = cap.read() filename = path + '/{}.jpg'.format(str(i)) print(filename) cv2.imwrite(filename, frame)
首先读取视频,然后获取视频的fps、宽度、高度和总帧数,注意:使用get()函数获取到的数据类型是float类型,需要进行转换才能进行后续的操作,因此这里全部将其转为int类型。
接下来我们将读取到的每帧图片保存起来
flag, frame = cap.read()需要在for循环里面,否则每次保存的图片都是视频第一帧的图片。
五、函数讲解
音频提取
# 音频提取def extract_audio(): my_clip = mp.VideoFileClip(file) my_clip.audio.write_audiofile('data/' + mp3_file)
这一部分内容很简单,就不细讲了
原图-线稿图转换
# 原图-线稿图转换def convert(): for i in range(0, frames): '''细节''' square = Image.open(path + "/{}.jpg".format(i)) square1 = square.filter(ImageFilter.DETAIL) '''轮廓''' square2 = square1.filter(ImageFilter.CONTOUR) # videowrite.write(square2) square2.save(new_picture_path + "/{}.jpg".format(i)) print(new_picture_path + "/{}.jpg".format(i))
frames是视频总帧数,该函数通过打开指定路径中的原图像,并通过两轮转换,将其保存到新路径中。
生成无声视频
# 生成无声视频def picture_merge(): size = (width, height) videowrite = cv2.VideoWriter(file_name, -1, fps, size) for i in range(0, frames): img = cv2.imread(new_picture_path + "/{}.jpg".format(i)) videowrite.write(img) videowrite.release() print('end!')
该函数通过
videowrite = cv2.VideoWriter(file_name, -1, fps, size)
将视频保存,将刚刚的获得的线稿图合成一个无声视频。
最终合成有声视频
# 最终合成有声视频def final_merge(): video = mp.VideoFileClip(file_name) audio = mp.AudioFileClip('data/' + mp3_file) video_merge = video.set_audio(audio) video_merge.write_videofile('final_' + filename + '.mp4')
最终将上述的无声视频和分离的音频合成最终的视频。
调用函数
if __name__ == '__main__': extract_audio() convert() picture_merge() final_merge()
主函数运行一下,大功告成了。
六、总结
看到这,是不是觉得很棒呀,如果对你有帮助的话,麻烦来个三连吧