####################################################################################### # # MIT License # # Copyright (c) [2025] [leonelhs@gmail.com] # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # ####################################################################################### # This file implements an API endpoint GFPGAN system. # It provides functionality to enhances an image by upscaling it 4 times its original size . # Source code is based on or inspired by several projects. # For more details and proper attribution, please refer to the following resources: # # - [GFPGAN] - [https://github.com/TencentARC/GFPGAN] # - [utils.py] - [https://github.com/TencentARC/GFPGAN/blob/master/gfpgan/utils.py] import torch from basicsr.utils import img2tensor, tensor2img from gfpgan.archs.gfpganv1_clean_arch import GFPGANv1Clean from huggingface_hub import hf_hub_download from torchvision.transforms.functional import normalize GFPGAN_REPO_ID = 'leonelhs/gfpgan' class TinyGFPGAN: """ Minimal functionalities from GFPGAN project. Args: channel_multiplier (int): Channel multiplier for large networks of StyleGAN2. Default: 2. """ def __init__(self, channel_multiplier=2, device=None): # initialize model self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') if device is None else device # initialize the GFP-GAN self.gfpgan = GFPGANv1Clean( out_size=512, channel_multiplier=channel_multiplier, fix_decoder=False, input_is_latent=True, different_w=True, sft_half=True) model_path = hf_hub_download(repo_id=GFPGAN_REPO_ID, filename="GFPGANv1.4.pth") loadnet = torch.load(model_path) if 'params_ema' in loadnet: keyname = 'params_ema' else: keyname = 'params' self.gfpgan.load_state_dict(loadnet[keyname], strict=True) self.gfpgan.eval() self.gfpgan = self.gfpgan.to(self.device) @torch.no_grad() def inference(self, cropped_face, weight=0.5): cropped_face_t = img2tensor(cropped_face / 255., bgr2rgb=True, float32=True) normalize(cropped_face_t, [0.5, 0.5, 0.5], [0.5, 0.5, 0.5], inplace=True) cropped_face_t = cropped_face_t.unsqueeze(0).to(self.device) try: output = self.gfpgan(cropped_face_t, return_rgb=False, weight=weight)[0] # convert to image restored_face = tensor2img(output.squeeze(0), rgb2bgr=True, min_max=(-1, 1)) return restored_face.astype('uint8') except RuntimeError as error: raise ValueError(f'\tFailed inference for GFPGAN: {error}.') def enhance(self, cropped_faces): return [self.inference(face) for face in cropped_faces]