AI人像抠图及视频合成:让你体验复仇者联盟的终局之战

本程序基于百度飞浆 PaddlePaddle 平台完成。

该程序通过DeepLabv3+模型完成一键抠图。

encoder-decoder进行多尺度信息的融合,同时保留了原来的空洞卷积和ASSP层, 其骨干网络使用了Xception模型,提高了语义分割的健壮性和运行速率,在 PASCAL VOC 2012 dataset取得新的state-of-art performance,该PaddleHub Module使用百度自建数据集进行训练,可用于人像分割,支持任意大小的图片输入。

在完成一键抠图之后,通过视频的合成,实现有趣的应用!

程序实现

首先安装 paddlehub

pip install paddlehub==1.6.0 -i https://pypi.tuna.tsinghua.edu.cn/simple

载入目标图片

# 待预测图片
img_name = 'ty.jpg'
test_img_path = ["./"+img_name]
#test_img_path = ["./meditation.jpg"]


import matplotlib.pyplot as plt 
import matplotlib.image as mpimg 

img = mpimg.imread(test_img_path[0]) 

# 展示待预测图片
plt.figure(figsize=(10,10))
plt.imshow(img) 
plt.axis('off') 
plt.show()

AI人像抠图及视频合成:让你体验复仇者联盟的终局之战_第1张图片
加载预训练模型

import paddlehub as hub

module = hub.Module(name="deeplabv3p_xception65_humanseg")

input_dict = {"image": test_img_path}

# execute predict and print the result
results = module.segmentation(data=input_dict)
for result in results:
    print(result)

# 预测结果展示
test_img_path = "./humanseg_output/"+img_name.split('.')[0]+'.png'
img = mpimg.imread(test_img_path)
plt.figure(figsize=(10,10))
plt.imshow(img) 
plt.axis('off') 
plt.show()

AI人像抠图及视频合成:让你体验复仇者联盟的终局之战_第2张图片
视频图像提取

import cv2
import matplotlib.pyplot as plt 
from PIL import Image
import numpy as np

cap = cv2.VideoCapture("a.mp4")
i=1
while True:
    ret, frame = cap.read()
    if frame is None:
        break
    else:
        img = Image.fromarray(np.uint8(frame))
        img.save('./vedio_img/'+str(i)+".jpg")
        i+=1


图像合成

from PIL import Image
import numpy as np

def blend_images(fore_image, base_image, img_num):
#def blend_images(fore_image, base_image):
    """
    将抠出的人物图像换背景
    fore_image: 前景图片,抠出的人物图片
    base_image: 背景图片
    """
    # 读入图片
    base_image = Image.open(base_image).convert('RGB')
    fore_image = Image.open(fore_image).resize(base_image.size)

    # 图片加权合成
    scope_map = np.array(fore_image)[:,:,-1] / 255
    scope_map = scope_map[:,:,np.newaxis]
    scope_map = np.repeat(scope_map, repeats=3, axis=2)
    res_image = np.multiply(scope_map, np.array(fore_image)[:,:,:3]) + np.multiply((1-scope_map), np.array(base_image))
    
    #保存图片
    res_image = Image.fromarray(np.uint8(res_image))
    res_image.save('./vedio_img_out/'+str(img_num)+".jpg")

设定何时进入画面

import os

# 合成几张图片
path = './vedio_img/'
filelist = os.listdir(path)
img_num = len(filelist)

# 你想在第几张图片的时候跳进视频
jump_in = 108

for i in range(jump_in,img_num):
    blend_images('./humanseg_output/'+img_name.split('.')[0]+'.png', './vedio_img/'+str(i+1)+".jpg", i+1)

其他部分用原始画面

# 其他部分我们用原来提取的图片
for i in range(jump_in):
    b_img = Image.open('./vedio_img/'+str(i+1)+".jpg").convert('RGB')
    s_img = Image.fromarray(np.uint8(b_img))
    s_img.save('./vedio_img_out/'+str(i+1)+".jpg")

最后合成视频

# 合成视频
import cv2
import os

# 查看原始视频的参数
cap = cv2.VideoCapture("a.mp4")
ret, frame = cap.read()
height=frame.shape[0]
width=frame.shape[1]
fps = cap.get(cv2.CAP_PROP_FPS)  #返回视频的fps--帧率
size=cap.get(cv2.CAP_PROP_FRAME_WIDTH)  #返回视频的宽,等同于frame.shape[1]
size1=cap.get(cv2.CAP_PROP_FRAME_HEIGHT)  #返回视频的高,等同于frame.shape[0]

#把参数用到我们要创建的视频上
video = cv2.VideoWriter('b.mp4', cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), fps, (width,height)) #创建视频流对象

path = './vedio_img_out/'
filelist = os.listdir(path)
img_num = len(filelist)

for i in range(img_num):
    #if item.endswith('.jpg'):   #判断图片后缀是否是.png
    item = path + str(i+1) + '.jpg' 
    img = cv2.imread(item)  #使用opencv读取图像,直接返回numpy.ndarray 对象,通道顺序为BGR ,注意是BGR,通道值默认范围0-255。
    video.write(img)        #把图片写进视频
video.release() #释放


利用 moviepy 把原视频的音频合成到我们新的视频上

# 提取原音频,合成到新的视频上
from moviepy.editor import *
video_o = VideoFileClip("a.mp4")
videoclip = VideoFileClip("b.mp4")
audio_o = video_o.audio

videoclip2 = videoclip.set_audio(audio_o)

videoclip2.write_videofile("c.mp4")

欢迎大家交流有趣的应用!

你可能感兴趣的:(PaddlePaddle,神经网络,计算机视觉,opencv,深度学习,计算机视觉,cv,paddlepaddle)