数字人开源代码运行---PC-AVS

github地址:Hangz-nju-cuhk/Talking-Face_PC-AVS: Code for Pose-Controllable Talking Face Generation by Implicitly Modularized Audio-Visual Representation (CVPR 2021) (github.com)原文地址:

2104.11116 (arxiv.org)

1、下载代码

git clone https://github.com/Hangz-nju-cuhk/Talking-Face_PC-AVS.git

或者直接download zip

2、安装环境

官方的环境是python3.6和pytorch1.3.0,由于这是2021年的一个代码,按照官方的安装可能会存在有的库用不了的情况,对于这种时间比较久的代码,我们碰到的大多数问题issues中可能都会有答案,我们去找一找。在issues中搜索requirements找到了一个环境相关的回答,可以作为借鉴。

创建一个conda环境
conda create -n pc-avs python==3.8.10
conda activate pc-avs
下载pytorch

pytoch下载地址:PyTorch

根据issues中的环境,选择这个版本

conda install pytorch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 pytorch-cuda=11.7 -c pytorch -c nvidia
安装requirements.txt

pytorch已经安装了,requirements.txt暂时需要这几个

pip install -r requirements.txt

3、模型下载

项目中给出了模型下载地址,但是应该是需要科学上网。

模型下载后解压到./checkpoints/demo中,解压后应该是这样:

4、数据准备

代码在misc目录下给出了demo数据,将mics目录下的所有zip文件解压,得到的目录包含以下文件:

demo.csv是推理时要用到的参数,主要是指明了推理所用到的数据。结构如下:

其中:

misc/Input/517600055  表示要驱动的原图像
1 表示原图像一张
misc/Pose_Source/517600078 表示姿势图像
160 表示160张姿势图像
misc/Audio_Source/681600002.mp3 表示要驱动的音频
misc/Mouth_Source/681600002 表示音频所对应的嘴型图像
363 表示嘴型图像363张

5、推理

linux系统直接可以使用

windows系统:

inference中有些命令cp等是linux中才使用的,稍微改造一下inference.py如下:

import os
import sys
import subprocess

sys.path.append('..')
from options.test_options import TestOptions
import torch
from models import create_model
import data
import util.util as util
from tqdm import tqdm


def video_concat(processed_file_savepath, name, video_names, audio_path):
    cmd = ['ffmpeg']
    num_inputs = len(video_names)
    for video_name in video_names:
        cmd += ['-i', os.path.join(processed_file_savepath, video_name + '.mp4')]

    cmd += ['-filter_complex', f"hstack=inputs={num_inputs}",
            os.path.join(processed_file_savepath, name + '.mp4'), '-loglevel', 'error', '-y']

    subprocess.run(cmd, shell=True)

    video_add_audio(name, audio_path, processed_file_savepath)


def video_add_audio(name, audio_path, processed_file_savepath):
    subprocess.run(['copy', audio_path, processed_file_savepath], shell=True)
    cmd = ['ffmpeg', '-i', os.path.join(processed_file_savepath, name + '.mp4'),
           '-i', audio_path,
           '-q:v', '0',
           '-strict', '-2',
           os.path.join(processed_file_savepath, 'av' + name + '.mp4'),
           '-loglevel', 'error', '-y']
    subprocess.run(cmd, shell=True)


def img2video(dst_path, prefix, video_path):
    cmd = ['ffmpeg', '-i', os.path.join(video_path, prefix + '%d.jpg'),
           '-q:v', '0', os.path.join(dst_path, prefix + '.mp4'), '-loglevel', 'error', '-y']
    subprocess.run(cmd, shell=True)


def inference_single_audio(opt, path_label, model):
    #
    opt.path_label = path_label
    dataloader = data.create_dataloader(opt)
    processed_file_savepath = dataloader.dataset.get_processed_file_savepath()

    idx = 0
    if opt.driving_pose:
        video_names = ['Input_', 'G_Pose_Driven_', 'Pose_Source_', 'Mouth_Source_']
    else:
        video_names = ['Input_', 'G_Fix_Pose_', 'Mouth_Source_']
    is_mouth_frame = os.path.isdir(dataloader.dataset.mouth_frame_path)
    if not is_mouth_frame:
        video_names.pop()
    save_paths = []
    for name in video_names:
        save_path = os.path.join(processed_file_savepath, name)
        util.mkdir(save_path)
        save_paths.append(save_path)
    for data_i in tqdm(dataloader):
        fake_image_original_pose_a, fake_image_driven_pose_a = model.forward(data_i, mode='inference')

        for num in range(len(fake_image_driven_pose_a)):
            util.save_torch_img(data_i['input'][num], os.path.join(save_paths[0], video_names[0] + str(idx) + '.jpg'))
            if opt.driving_pose:
                util.save_torch_img(fake_image_driven_pose_a[num],
                                    os.path.join(save_paths[1], video_names[1] + str(idx) + '.jpg'))
                util.save_torch_img(data_i['driving_pose_frames'][num],
                                    os.path.join(save_paths[2], video_names[2] + str(idx) + '.jpg'))
            else:
                util.save_torch_img(fake_image_original_pose_a[num],
                                    os.path.join(save_paths[1], video_names[1] + str(idx) + '.jpg'))
            if is_mouth_frame:
                util.save_torch_img(data_i['target'][num],
                                    os.path.join(save_paths[-1], video_names[-1] + str(idx) + '.jpg'))
            idx += 1

    if opt.gen_video:
        for i, video_name in enumerate(video_names):
            img2video(processed_file_savepath, video_name, save_paths[i])
        video_concat(processed_file_savepath, 'concat', video_names, dataloader.dataset.audio_path)

    print('results saved...' + processed_file_savepath)
    del dataloader
    return


def main():
    opt = TestOptions().parse()
    opt.isTrain = False
    torch.manual_seed(0)
    model = create_model(opt).cuda()
    model.eval()

    with open(opt.meta_path_vox, 'r') as f:
        lines = f.read().splitlines()

    for clip_idx, path_label in enumerate(lines):
        try:
            assert len(path_label.split()) == 8, path_label

            inference_single_audio(opt, path_label, model)

        except Exception as ex:
            import traceback
            traceback.print_exc()
            print(path_label + '\n')
            print(str(ex))


if __name__ == '__main__':
    main()

在运行前可能会显示缺少lws,pip一下就行

pip install lws 

推理使用命令:

set meta_path_vox=./misc/demo.csv 
python -u inference.py --name demo --meta_path_vox %meta_path_vox% --dataset_mode voxtest --netG modulate --netA resseaudio --netA_sync ressesync --netD multiscale --netV resnext --netE fan --model av --gpu_ids 0 --clip_len 1 --batchSize 16 --style_dim 2560 --nThreads 4 --input_id_feature --generate_interval 1 --style_feature_loss --use_audio 1 --noise_pose --driving_pose --gen_video --generate_from_audio_only

结果保存在results中:

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值