mirror of
https://github.com/storytold/storyteller-ml.git
synced 2026-10-19 07:54:56 +00:00
Add SadTalker @ ae0b26359d44c9379450a8e02a38b45eeec15549
MIT license Commit: https://github.com/OpenTalker/SadTalker commit ae0b26359d44c9379450a8e02a38b45eeec15549 (HEAD -> main, origin/main, origin/HEAD) Author: shadowcun <shadowcun@tencent.com> Date: Mon Jul 3 13:48:35 2023 +0800 fixed bug: hacking facexlib of FAN
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import os
|
||||
import torch
|
||||
|
||||
from gfpgan import GFPGANer
|
||||
|
||||
from tqdm import tqdm
|
||||
|
||||
from src.utils.videoio import load_video_to_cv2
|
||||
|
||||
import cv2
|
||||
|
||||
|
||||
class GeneratorWithLen(object):
|
||||
""" From https://stackoverflow.com/a/7460929 """
|
||||
|
||||
def __init__(self, gen, length):
|
||||
self.gen = gen
|
||||
self.length = length
|
||||
|
||||
def __len__(self):
|
||||
return self.length
|
||||
|
||||
def __iter__(self):
|
||||
return self.gen
|
||||
|
||||
def enhancer_list(images, method='gfpgan', bg_upsampler='realesrgan'):
|
||||
gen = enhancer_generator_no_len(images, method=method, bg_upsampler=bg_upsampler)
|
||||
return list(gen)
|
||||
|
||||
def enhancer_generator_with_len(images, method='gfpgan', bg_upsampler='realesrgan'):
|
||||
""" Provide a generator with a __len__ method so that it can passed to functions that
|
||||
call len()"""
|
||||
|
||||
if os.path.isfile(images): # handle video to images
|
||||
# TODO: Create a generator version of load_video_to_cv2
|
||||
images = load_video_to_cv2(images)
|
||||
|
||||
gen = enhancer_generator_no_len(images, method=method, bg_upsampler=bg_upsampler)
|
||||
gen_with_len = GeneratorWithLen(gen, len(images))
|
||||
return gen_with_len
|
||||
|
||||
def enhancer_generator_no_len(images, method='gfpgan', bg_upsampler='realesrgan'):
|
||||
""" Provide a generator function so that all of the enhanced images don't need
|
||||
to be stored in memory at the same time. This can save tons of RAM compared to
|
||||
the enhancer function. """
|
||||
|
||||
print('face enhancer....')
|
||||
if not isinstance(images, list) and os.path.isfile(images): # handle video to images
|
||||
images = load_video_to_cv2(images)
|
||||
|
||||
# ------------------------ set up GFPGAN restorer ------------------------
|
||||
if method == 'gfpgan':
|
||||
arch = 'clean'
|
||||
channel_multiplier = 2
|
||||
model_name = 'GFPGANv1.4'
|
||||
url = 'https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth'
|
||||
elif method == 'RestoreFormer':
|
||||
arch = 'RestoreFormer'
|
||||
channel_multiplier = 2
|
||||
model_name = 'RestoreFormer'
|
||||
url = 'https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/RestoreFormer.pth'
|
||||
elif method == 'codeformer': # TODO:
|
||||
arch = 'CodeFormer'
|
||||
channel_multiplier = 2
|
||||
model_name = 'CodeFormer'
|
||||
url = 'https://github.com/sczhou/CodeFormer/releases/download/v0.1.0/codeformer.pth'
|
||||
else:
|
||||
raise ValueError(f'Wrong model version {method}.')
|
||||
|
||||
|
||||
# ------------------------ set up background upsampler ------------------------
|
||||
if bg_upsampler == 'realesrgan':
|
||||
if not torch.cuda.is_available(): # CPU
|
||||
import warnings
|
||||
warnings.warn('The unoptimized RealESRGAN is slow on CPU. We do not use it. '
|
||||
'If you really want to use it, please modify the corresponding codes.')
|
||||
bg_upsampler = None
|
||||
else:
|
||||
from basicsr.archs.rrdbnet_arch import RRDBNet
|
||||
from realesrgan import RealESRGANer
|
||||
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=2)
|
||||
bg_upsampler = RealESRGANer(
|
||||
scale=2,
|
||||
model_path='https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.1/RealESRGAN_x2plus.pth',
|
||||
model=model,
|
||||
tile=400,
|
||||
tile_pad=10,
|
||||
pre_pad=0,
|
||||
half=True) # need to set False in CPU mode
|
||||
else:
|
||||
bg_upsampler = None
|
||||
|
||||
# determine model paths
|
||||
model_path = os.path.join('gfpgan/weights', model_name + '.pth')
|
||||
|
||||
if not os.path.isfile(model_path):
|
||||
model_path = os.path.join('checkpoints', model_name + '.pth')
|
||||
|
||||
if not os.path.isfile(model_path):
|
||||
# download pre-trained models from url
|
||||
model_path = url
|
||||
|
||||
restorer = GFPGANer(
|
||||
model_path=model_path,
|
||||
upscale=2,
|
||||
arch=arch,
|
||||
channel_multiplier=channel_multiplier,
|
||||
bg_upsampler=bg_upsampler)
|
||||
|
||||
# ------------------------ restore ------------------------
|
||||
for idx in tqdm(range(len(images)), 'Face Enhancer:'):
|
||||
|
||||
img = cv2.cvtColor(images[idx], cv2.COLOR_RGB2BGR)
|
||||
|
||||
# restore faces and background if necessary
|
||||
cropped_faces, restored_faces, r_img = restorer.enhance(
|
||||
img,
|
||||
has_aligned=False,
|
||||
only_center_face=False,
|
||||
paste_back=True)
|
||||
|
||||
r_img = cv2.cvtColor(r_img, cv2.COLOR_BGR2RGB)
|
||||
yield r_img
|
||||
Reference in New Issue
Block a user