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

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

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


image.png


一、环境设置


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


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))


相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
并行计算 Linux C语言
PaddleOCR
PaddleOCR
597 0
|
4月前
|
XML Shell API
python ConfigParser、shutil、subprocess、ElementTree模块简解
python ConfigParser、shutil、subprocess、ElementTree模块简解
|
4月前
|
测试技术 Python
Python 中的 Monkey Patching
【8月更文挑战第29天】
50 5
|
7月前
|
IDE 开发工具 Python
发布Package到PyPI
发布Package到PyPI
43 0
|
人工智能
Learn R package together--(3)
论文中作图经常会有合并图排版需求,一般会放入PPT中或AI手动调节,若是在R中出图前直接调好岂不是更美滋滋,So本次就介绍几种关于合并图形的包cowplot、gridExtra、ggpubr、patchwork
82 0
Learn R package together--(2)
介绍俩个小众但实用的包wherepackage、rPlotter
95 0
Learn R package together--(1)
ggrepel包 此包可解决标签重合问题
83 0
|
XML JSON 测试技术
Python之configparser模块详解和使用
Python之configparser模块详解和使用
92 0
Python之configparser模块详解和使用
|
存储 Java 数据安全/隐私保护
java包(package)
1.包的概念 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。 包的作用 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。 Java使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等✨
97 0
java包(package)
No package ‘libpeas-1.0‘ found/No package ‘libpeas-gtk-1.0‘
No package ‘libpeas-1.0‘ found/No package ‘libpeas-gtk-1.0‘
60 0