from collections import namedtuple import torch from torch.utils import model_zoo import requests from tqdm import tqdm from pathlib import Path from src.FaceDetector.face_detector import FaceDetector from src.FaceId.faceid import FaceId from src.Generator.fs_networks_fix import Generator_Adain_Upsample from src.PostProcess.ParsingModel.model import BiSeNet from src.PostProcess.GFPGAN.gfpgan import GFPGANer from src.Blend.blend import BlendModule model = namedtuple("model", ["url", "model"]) models = { "face_detector": model( url="https://github.com/mike9251/simswap-inference-pytorch/releases/download/weights/face_detector_scrfd_10g_bnkps.onnx", model=FaceDetector, ), "arcface": model( url="https://github.com/mike9251/simswap-inference-pytorch/releases/download/weights/arcface_net.jit", model=FaceId, ), "generator_224": model( url="https://github.com/mike9251/simswap-inference-pytorch/releases/download/weights/simswap_224_latest_net_G.pth", model=Generator_Adain_Upsample, ), "generator_512": model( url="https://github.com/mike9251/simswap-inference-pytorch/releases/download/weights/simswap_512_390000_net_G.pth", model=Generator_Adain_Upsample, ), "parsing_model": model( url="https://github.com/mike9251/simswap-inference-pytorch/releases/download/weights/parsing_model_79999_iter.pth", model=BiSeNet, ), "gfpgan": model( url="https://github.com/mike9251/simswap-inference-pytorch/releases/download/v1.1/GFPGANv1.4_ema.pth", model=GFPGANer, ), "blend_module": model( url="https://github.com/mike9251/simswap-inference-pytorch/releases/download/v1.2/blend_module.jit", model=BlendModule ) } def get_model( model_name: str, device: torch.device, load_state_dice: bool, model_path: Path, **kwargs, ): dst_dir = Path.cwd() / "weights" dst_dir.mkdir(exist_ok=True) url = models[model_name].url if not model_path.is_file() else str(model_path) if load_state_dice: model = models[model_name].model(**kwargs) if Path(url).is_file(): state_dict = torch.load(url) else: state_dict = model_zoo.load_url( url, model_dir=str(dst_dir), progress=True, map_location="cpu", ) model.load_state_dict(state_dict) model.to(device) model.eval() else: dst_path = Path(url) if not dst_path.is_file(): dst_path = dst_dir / Path(url).name if not dst_path.is_file(): print(f"Downloading: '{url}' to {dst_path}") response = requests.get(url, stream=True) if int(response.status_code) == 200: file_size = int(response.headers["Content-Length"]) / (2 ** 20) chunk_size = 1024 bar_format = "{desc}: {percentage:3.0f}%|{bar}| {n:3.1f}M/{total:3.1f}M [{elapsed}<{remaining}]" with open(dst_path, "wb") as handle: with tqdm(total=file_size, bar_format=bar_format) as pbar: for data in response.iter_content(chunk_size=chunk_size): handle.write(data) pbar.update(len(data) / (2 ** 20)) else: raise ValueError( f"Couldn't download weights {url}. Specify weights for the '{model_name}' model manually." ) kwargs.update({"model_path": str(dst_path), "device": device}) model = models[model_name].model(**kwargs) return model