一、介绍:

视频人像抠图(Videyo human matting)是计算机视觉的经典任务,输入一个视频(图像序列),得到对应视频中人像的alpha图,其中alpha与分割mask不同,mask将视频分为前景与背景,取值只有0和1,而alpha的取值范围是0到1之间,返回数值代表透明度。VHM模型处理1080P视频每帧计算量为10.6G,参数量只有6.3M。

二、下载模型

该模型由四部分构成:backbone中间处理层decoder高分辨率处理层

其中backbone是基于efficientnetv2实现,为了实现更小的计算量和更好的效果,我们对原网络模块进行了一定修改后重新与unet结构进行人像分割任务训练,结果的backbone参数作为预训练载入; 中间处理层使用ASPP模块作为基本单元,多层空洞卷积扩大感受野; decoder部分将会逐步融合backbone各层特征,同时将原始图像特征作为一部分输入来引导网络学习,此外,我们将gru作为基础模块嵌入网络以便于处理时序相关信息; 高分辨率处理层基于DGF(Deep Guided Filter),实现对低分辨率后超分至原有分辨率,该层仍具有可学习参数,效果远优于直接上采样效果。

三、配置环境

conda create -n vilify python=3.8
conda activate vilify
pip install torch-1.10.0+cu113-cp38-cp38-win_amd64.whl
pip install torchvision-0.11.0+cu113-cp38-cp38-win_amd64.whl
pip install modelscope 
pip install moviepy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple

四、核心代码

1、遮罩输出

默认情况下,使用该方式将会仅输出视频的黑白遮罩,如果您会使用PhotoShop或After Effects等软件,那么您肯定会了解遮罩的作用是什么,您可以理解为这个遮罩层的白色为保留区域,黑色删除的部分。

该模型官方并未给了示例,本站已经帮您写好了相关的代码,复制粘贴即可使用。

注意:请自行修改视频名称(Video_Name)为自己的视频文件名称,然后再执行,否则会报错。

# 本代码由openai.wiki提供转载请注明出处

import cv2
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
from modelscope.outputs import OutputKeys

# 原视频路径
input_video = 'D:/openai.wiki/cv_effnetv2_video-human-matting/Video_Name.mp4'
# Mask遮罩路径
maskoutput_video = 'D:/openai.wiki/cv_effnetv2_video-human-matting/video_name_mask.mp4'

video_matting = pipeline(Tasks.video_human_matting, 
                       model='damo/cv_effnetv2_video-human-matting')
result_status = video_matting({'video_input_path':input_video,
                           'output_path':maskoutput_video})
result = result_status[OutputKeys.MASKS]

2、抠图输出

执行如下代码,将会自动输出遮罩层,并将遮罩层自动叠加至原视频的颜色层,输出您想要的最终视频。

# 本代码由openai.wiki提供转载请注明出处

import cv2

from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
from modelscope.outputs import OutputKeys

# 源视频路径
input_video = 'D:/openai.wiki/cv_effnetv2_video-human-matting/Video_Name.mp4'
# Mask遮罩路径
maskoutput_video = 'D:/openai.wiki/cv_effnetv2_video-human-matting/video_name_mask.mp4'
# 输出视频路径
output_video = 'D:/openai.wiki/cv_effnetv2_video-human-matting/video_name_final.mp4'

video_matting = pipeline(Tasks.video_human_matting, 
                       model='damo/cv_effnetv2_video-human-matting')
result_status = video_matting({'video_input_path':input_video,
                           'output_path':maskoutput_video})
result = result_status[OutputKeys.MASKS]

# 读取原始视频和抠图的mask视频
cap = cv2.VideoCapture(input_video)
mask_cap = cv2.VideoCapture(maskoutput_video)

# 获取视频帧率和大小
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# 创建新的视频文件写入器
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_video, fourcc, fps, (width, height))

while True:
    # 读取原始视频和抠图的mask视频的下一帧
    ret, frame = cap.read()
    ret_mask, mask_frame = mask_cap.read()
    
    # 如果没有读取到帧则退出循环
    if not ret or not ret_mask:
        break
        
    # 将抠图的mask视频转换为二进制掩码
    gray_mask = cv2.cvtColor(mask_frame, cv2.COLOR_BGR2GRAY)
    ret, binary_mask = cv2.threshold(gray_mask, 10, 255, cv2.THRESH_BINARY)
    
    # 将原始视频的每一帧与二进制掩码进行按位与运算
    result = cv2.bitwise_and(frame, frame, mask=binary_mask)
    
    # 将生成的每一帧写入到新的视频文件中
    out.write(result)

# 释放资源
cap.release()
mask_cap.release()
out.release()

五、效果展示

原视频

Mask遮罩

抠图效果