Python厉害已经不是一天两天的事了,但是我怎么也没想到,Python还能做特效!
因为之前接触过Python一个批量抠图的模型库,然后最近看视频突然就灵光一现,为啥不用Python给视频抠图换个背景?于是就有了下面这个操作:
先看看效果,这是原场景:
这是换过背景的样子:
看起来还不错吧。
再看另一种效果,是不是要狂放许多:
重点来了!
1、具体步骤
-
读取视频,获取每一帧画面
-
批量抠图
-
读取场景图片
-
对每一帧画面进行场景切换
-
写入视频
-
读取原视频的音频
-
给新视频设置音频
2、模块安装
我们需要使用到的模块主要有如下几个:
pillow
opencv
moviepy
paddlehub
都可以直接用pip安装:
pip install pillow
pip install opencv-python
pip install moviepy
其中OpenCV有一些适配问题,建议选取3.0以上版本。
在我们使用paddlehub之前,我们需要安装paddlepaddle。
用paddlehub抠图。
我们这里直接用pip安装cpu版本的:
# 安装paddlepaddle
python -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
# 安装paddlehub
pip install -i https://mirror.baidu.com/pypi/simple paddlehub
有了这些准备工作就可以开始我们功能的实现了。
3、具体实现
我们导入如下包:
import cv2 # opencv
import mail # 自定义包,用于发邮件
import math
import numpy as np
from PIL import Image # pillow
import paddlehub as hub
from moviepy.editor import *
其中Pillow和opencv导入的名称不太一样,还有就是我自定义的mail模块。
另外我们还要先准备一些路径:
# 当前项目根目录,系统自动获取当前目录
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "."))
# 每一帧画面保存的地址
frame_path = BASE_DIR + '\\frames\\'
# 抠好的图片位置
humanseg_path = BASE_DIR + '\\humanseg_output\\'
# 最终视频的保存路径
output_video = BASE_DIR + '\\result.mp4'
接下来我们按照上面说的步骤一个一个实现。
(1)读取视频,获取每一帧画面
def getFrame(video_name, save_path):
"""
读取视频将视频逐帧保存为图片,并返回视频的分辨率size和帧率fps
:param video_name: 视频的名称
:param save_path: 保存的路径
:return: fps帧率,size分辨率
"""
# 读取视频
video = cv2.VideoCapture(video_name)
# 获取视频帧率
fps = video.get(cv2.CAP_PROP_FPS)
# 获取画面大小
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
size = (width, height)
# 🦍获取帧数,用于给图片命名
frame_num = str(video.get(7))
name = int(math.pow(10, len(frame_num)))
# 读取帧,ret为是否还有下一帧,frame为当前帧的ndarray对象
ret, frame = video.read()
while ret:
cv2.imwrite(save_path + str(name) + '.jpg', frame)
ret, frame = video.read()
name +=&nb