【谁说视频不能P】之基于PaddleHub的100行代码P阿力木视频

我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!

【谁说视频不能P】之基于PaddleHub的100行代码P阿力木视频,顾名思义,就是通过简单的几行python代码实现P视频,比如最近的那个“疆域阿力木”视频背景切换。话不多说,下面就开干。

微信图片_20220804003844.jpg

一、环境设置

话不多说,主要做以下工作。

1.安装依赖

pip安装嘛,主要有以下包需要安装。。。。。。

  • 安装PaddePaddle-gpu (gpu快啊)
  • 安装PaddleHub
  • 其他依赖若干

2.引入包

import cv2
import os
import numpy as np
from PIL import Image
import paddlehub as hub
​
%set_env GPU_NUM=1
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
复制代码

二、视频切分转图片

主要是以下功能

  • 从摄像头获取视频切分为图片帧
  • 从视频文件获取视频切分为图片帧
​
def CutVideo2Image(video_path, img_path):
    cap = cv2.VideoCapture(video_path)
    index = 0
    while(True):
        ret,frame = cap.read() 
        if ret:
            cv2.imwrite('video/frame/%d.jpg'%index, frame)
            # img_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) 
            # imgs.append(img_rgb)
            index += 1
        else:
            break
    cap.release()
    print('Video cut finish, all %d frame' % index)
​
复制代码

三、人像抠图

很简单,直接调用paddlehub的deeplabv3p_xception65_humanseg人像抠图模块进行抠图。

def GetHumanSeg(in_path, out_path):
    # load model
    module = hub.Module(name="deeplabv3p_xception65_humanseg")
    # config
    frame_path = in_path
    test_img_path = [os.path.join(frame_path, fname) for fname in os.listdir(frame_path)]
    input_dict = {"image": test_img_path}
    print('file len: %d'% len(test_img_path))
​
    total_num = len(test_img_path)
    loop_num = int(np.ceil(total_num / 10))
​
​
    for iter_id in range(loop_num):
        batch_data=list()
        handle_id=iter_id *10
        for image_id in range(10):
            try:
                batch_data.append(test_img_path[handle_id +image_id])
                print(handle_id +image_id)
                print(test_img_path[handle_id +image_id])
            except:
                pass
        batch_input_dict={"image": batch_data}
        results = module.segmentation(data=batch_input_dict, use_gpu=True, visualization=True,  output_dir=out_path)
            # del results
            # del batch_input_dict复制代码

四、人像背景替换

def BlendImg(fore_image, base_image, output_path):
    """
    将抠出的人物图像换背景
    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(output_path)
​
def BlendHumanImg(in_path, screen_path, out_path):
    humanseg_png = [filename for filename in os.listdir(in_path)]
    for i, img in enumerate(humanseg_png):
        img_path = os.path.join(in_path + '%d.png' % (i))
        output_path_img = out_path + '%d.png' % i
        BlendImg(img_path, screen_path, output_path_img)
   
​
def init_canvas(width, height, color=(255, 255, 255)):
    canvas = np.ones((height, width, 3), dtype="uint8")
    canvas[:] = color
    return canvas
​
def GetGreenScreen(width, height, out_path):
    canvas = init_canvas(width, height, color=(0, 255, 0))
    cv2.imwrite(out_path, canvas)
复制代码

五、合并还原视频

合并嘛,很简单不讲了。

​
def CombVideo(in_path, out_path, size):
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(out_path,fourcc, 30.0, size)
    files = os.listdir(in_path)
​
    for i in range(len(files)):
        img = cv2.imread(in_path + '%d.png' % i)
        # cv2.imshow("test", img)
        # cv2.waitKey(0)
        # img = cv2.resize(img, (1280,720))
        out.write(img)#保存帧
    out.release()
​
​
​
复制代码

六、运行

由于是jupyter写的,所以都是代码段,后续将进行优化整理。运行程序如下。

  • 视频-图像转换
  • 抠图
  • 生成绿幕并合并
  • 合并视频
# Config
Video_Path = 'video/2.mp4'
FrameCut_Path = 'video/frame/'
FrameSeg_Path = 'video/frame_seg/'
FrameCom_Path = 'video/frame_com/'
GreenScreen_Path = 'video/base_image.png'
ComOut_Path = 'output.mp4'
​
​
# 第一步:视频->图像
if not os.path.exists(FrameCut_Path):
    os.mkdir(FrameCut_Path)     
    CutVideo2Image(Video_Path, FrameCut_Path)
​
# 第二步:抠图
if not os.path.exists(FrameSeg_Path):
    os.mkdir(FrameSeg_Path) 
    GetHumanSeg(FrameCut_Path, FrameSeg_Path)
​
# 第三步:生成绿幕并合成
if not os.path.exists(GreenScreen_Path):
    GetGreenScreen(720, 480, GreenScreen_Path)
​
if not os.path.exists(FrameCom_Path):
    os.mkdir(FrameCom_Path) 
    BlendHumanImg(FrameSeg_Path, GreenScreen_Path, FrameCom_Path)
​
# 第四步:合成视频
if not os.path.exists(ComOut_Path):
    CombVideo(FrameCom_Path, ComOut_Path, (720, 480))
复制代码

\

猜你喜欢

转载自juejin.im/post/7127691591686291470