mirror of
https://github.com/TencentARC/GFPGAN.git
synced 2026-02-14 13:46:30 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af7569775d | ||
|
|
c6593e7221 | ||
|
|
7272e45887 | ||
|
|
3e27784b1b | ||
|
|
2c420ee565 | ||
|
|
8e7cf5d723 | ||
|
|
c541e97f83 | ||
|
|
86756cba65 | ||
|
|
a9a2e3ae15 | ||
|
|
9c3f2d62cb | ||
|
|
ccd30af837 | ||
|
|
7d657f26b6 | ||
|
|
c7ccc098a7 | ||
|
|
bc3f0c4d91 |
41
.github/workflows/release.yml
vendored
Normal file
41
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
permissions: write-all
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: GFPGAN ${{ github.ref }} Release Note
|
||||
body: |
|
||||
🚀 See you again 😸
|
||||
🚀Have a nice day 😸 and happy everyday 😃
|
||||
🚀 Long time no see ☄️
|
||||
|
||||
✨ **Highlights**
|
||||
✅ [Features] Support ...
|
||||
|
||||
🐛 **Bug Fixes**
|
||||
|
||||
🌴 **Improvements**
|
||||
|
||||
📢📢📢
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/TencentARC/GFPGAN/master/assets/gfpgan_logo.png" height=150>
|
||||
</p>
|
||||
draft: true
|
||||
prerelease: false
|
||||
14
README.md
14
README.md
@@ -4,6 +4,11 @@
|
||||
|
||||
## <div align="center"><b><a href="README.md">English</a> | <a href="README_CN.md">简体中文</a></b></div>
|
||||
|
||||
<div align="center">
|
||||
<!-- <a href="https://twitter.com/_Xintao_" style="text-decoration:none;">
|
||||
<img src="https://user-images.githubusercontent.com/17445847/187162058-c764ced6-952f-404b-ac85-ba95cce18e7b.png" width="4%" alt="" />
|
||||
</a> -->
|
||||
|
||||
[](https://github.com/TencentARC/GFPGAN/releases)
|
||||
[](https://pypi.org/project/gfpgan/)
|
||||
[](https://github.com/TencentARC/GFPGAN/issues)
|
||||
@@ -11,12 +16,15 @@
|
||||
[](https://github.com/TencentARC/GFPGAN/blob/master/LICENSE)
|
||||
[](https://github.com/TencentARC/GFPGAN/blob/master/.github/workflows/pylint.yml)
|
||||
[](https://github.com/TencentARC/GFPGAN/blob/master/.github/workflows/publish-pip.yml)
|
||||
</div>
|
||||
|
||||
1. :boom: **Updated** online demo: [](https://replicate.com/tencentarc/gfpgan). Here is the [backup](https://replicate.com/xinntao/gfpgan).
|
||||
1. :boom: **Updated** online demo: [](https://huggingface.co/spaces/Xintao/GFPGAN)
|
||||
1. [Colab Demo](https://colab.research.google.com/drive/1sVsoBd9AjckIXThgtZhGrHRfFI6UUYOo) for GFPGAN <a href="https://colab.research.google.com/drive/1sVsoBd9AjckIXThgtZhGrHRfFI6UUYOo"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="google colab logo"></a>; (Another [Colab Demo](https://colab.research.google.com/drive/1Oa1WwKB4M4l1GmR7CtswDVgOCOeSLChA?usp=sharing) for the original paper model)
|
||||
2. Online demo: [Huggingface](https://huggingface.co/spaces/akhaliq/GFPGAN) (return only the cropped face)
|
||||
3. Online demo: [Replicate.ai](https://replicate.com/xinntao/gfpgan) (may need to sign in, return the whole image)
|
||||
|
||||
<!-- 3. Online demo: [Replicate.ai](https://replicate.com/xinntao/gfpgan) (may need to sign in, return the whole image)
|
||||
4. Online demo: [Baseten.co](https://app.baseten.co/applications/Q04Lz0d/operator_views/8qZG6Bg) (backed by GPU, returns the whole image)
|
||||
5. We provide a *clean* version of GFPGAN, which can run without CUDA extensions. So that it can run in **Windows** or on **CPU mode**.
|
||||
5. We provide a *clean* version of GFPGAN, which can run without CUDA extensions. So that it can run in **Windows** or on **CPU mode**. -->
|
||||
|
||||
> :rocket: **Thanks for your interest in our work. You may also want to check our new updates on the *tiny models* for *anime images and videos* in [Real-ESRGAN](https://github.com/xinntao/Real-ESRGAN/blob/master/docs/anime_video_model.md)** :blush:
|
||||
|
||||
|
||||
22
cog.yaml
Normal file
22
cog.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
# This file is used for constructing replicate env
|
||||
image: "r8.im/tencentarc/gfpgan"
|
||||
|
||||
build:
|
||||
gpu: true
|
||||
python_version: "3.8"
|
||||
system_packages:
|
||||
- "libgl1-mesa-glx"
|
||||
- "libglib2.0-0"
|
||||
python_packages:
|
||||
- "torch==1.7.1"
|
||||
- "torchvision==0.8.2"
|
||||
- "numpy==1.21.1"
|
||||
- "lmdb==1.2.1"
|
||||
- "opencv-python==4.5.3.56"
|
||||
- "PyYAML==5.4.1"
|
||||
- "tqdm==4.62.2"
|
||||
- "yapf==0.31.0"
|
||||
- "basicsr==1.4.2"
|
||||
- "facexlib==0.2.5"
|
||||
|
||||
predict: "cog_predict.py:Predictor"
|
||||
147
cog_predict.py
Normal file
147
cog_predict.py
Normal file
@@ -0,0 +1,147 @@
|
||||
# flake8: noqa
|
||||
# This file is used for deploying replicate models
|
||||
# running: cog predict -i img=@inputs/whole_imgs/10045.png -i version='v1.4' -i scale=2
|
||||
# push: cog push r8.im/tencentarc/gfpgan
|
||||
# push (backup): cog push r8.im/xinntao/gfpgan
|
||||
|
||||
import os
|
||||
|
||||
os.system('python setup.py develop')
|
||||
os.system('pip install realesrgan')
|
||||
|
||||
import cv2
|
||||
import shutil
|
||||
import tempfile
|
||||
import torch
|
||||
from basicsr.archs.srvgg_arch import SRVGGNetCompact
|
||||
|
||||
from gfpgan import GFPGANer
|
||||
|
||||
try:
|
||||
from cog import BasePredictor, Input, Path
|
||||
from realesrgan.utils import RealESRGANer
|
||||
except Exception:
|
||||
print('please install cog and realesrgan package')
|
||||
|
||||
|
||||
class Predictor(BasePredictor):
|
||||
|
||||
def setup(self):
|
||||
# download weights
|
||||
if not os.path.exists('gfpgan/weights/realesr-general-x4v3.pth'):
|
||||
os.system(
|
||||
'wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesr-general-x4v3.pth -P ./gfpgan/weights'
|
||||
)
|
||||
if not os.path.exists('gfpgan/weights/GFPGANv1.2.pth'):
|
||||
os.system(
|
||||
'wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.2.pth -P ./gfpgan/weights')
|
||||
if not os.path.exists('gfpgan/weights/GFPGANv1.3.pth'):
|
||||
os.system(
|
||||
'wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth -P ./gfpgan/weights')
|
||||
if not os.path.exists('gfpgan/weights/GFPGANv1.4.pth'):
|
||||
os.system(
|
||||
'wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth -P ./gfpgan/weights')
|
||||
|
||||
# background enhancer with RealESRGAN
|
||||
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=32, upscale=4, act_type='prelu')
|
||||
model_path = 'gfpgan/weights/realesr-general-x4v3.pth'
|
||||
half = True if torch.cuda.is_available() else False
|
||||
self.upsampler = RealESRGANer(
|
||||
scale=4, model_path=model_path, model=model, tile=0, tile_pad=10, pre_pad=0, half=half)
|
||||
|
||||
# Use GFPGAN for face enhancement
|
||||
self.face_enhancer = GFPGANer(
|
||||
model_path='gfpgan/weights/GFPGANv1.4.pth',
|
||||
upscale=2,
|
||||
arch='clean',
|
||||
channel_multiplier=2,
|
||||
bg_upsampler=self.upsampler)
|
||||
self.current_version = 'v1.4'
|
||||
|
||||
def predict(
|
||||
self,
|
||||
img: Path = Input(description='Input'),
|
||||
version: str = Input(
|
||||
description='GFPGAN version. v1.3: better quality. v1.4: more details and better identity.',
|
||||
choices=['v1.2', 'v1.3', 'v1.4'],
|
||||
default='v1.4'),
|
||||
scale: float = Input(description='Rescaling factor', default=2)
|
||||
) -> Path:
|
||||
print(img, version, scale)
|
||||
try:
|
||||
img = cv2.imread(str(img), cv2.IMREAD_UNCHANGED)
|
||||
if len(img.shape) == 3 and img.shape[2] == 4:
|
||||
img_mode = 'RGBA'
|
||||
else:
|
||||
img_mode = None
|
||||
|
||||
h, w = img.shape[0:2]
|
||||
if h < 300:
|
||||
img = cv2.resize(img, (w * 2, h * 2), interpolation=cv2.INTER_LANCZOS4)
|
||||
|
||||
if self.current_version != version:
|
||||
if version == 'v1.2':
|
||||
self.face_enhancer = GFPGANer(
|
||||
model_path='gfpgan/weights/GFPGANv1.2.pth',
|
||||
upscale=2,
|
||||
arch='clean',
|
||||
channel_multiplier=2,
|
||||
bg_upsampler=self.upsampler)
|
||||
self.current_version = 'v1.2'
|
||||
elif version == 'v1.3':
|
||||
self.face_enhancer = GFPGANer(
|
||||
model_path='gfpgan/weights/GFPGANv1.3.pth',
|
||||
upscale=2,
|
||||
arch='clean',
|
||||
channel_multiplier=2,
|
||||
bg_upsampler=self.upsampler)
|
||||
self.current_version = 'v1.3'
|
||||
elif version == 'v1.4':
|
||||
self.face_enhancer = GFPGANer(
|
||||
model_path='gfpgan/weights/GFPGANv1.4.pth',
|
||||
upscale=2,
|
||||
arch='clean',
|
||||
channel_multiplier=2,
|
||||
bg_upsampler=self.upsampler)
|
||||
self.current_version = 'v1.4'
|
||||
|
||||
try:
|
||||
_, _, output = self.face_enhancer.enhance(
|
||||
img, has_aligned=False, only_center_face=False, paste_back=True)
|
||||
except RuntimeError as error:
|
||||
print('Error', error)
|
||||
else:
|
||||
extension = 'png'
|
||||
|
||||
try:
|
||||
if scale != 2:
|
||||
interpolation = cv2.INTER_AREA if scale < 2 else cv2.INTER_LANCZOS4
|
||||
h, w = img.shape[0:2]
|
||||
output = cv2.resize(output, (int(w * scale / 2), int(h * scale / 2)), interpolation=interpolation)
|
||||
except Exception as error:
|
||||
print('wrong scale input.', error)
|
||||
if img_mode == 'RGBA': # RGBA images should be saved in png format
|
||||
extension = 'png'
|
||||
else:
|
||||
extension = 'jpg'
|
||||
save_path = f'output/out.{extension}'
|
||||
cv2.imwrite(save_path, output)
|
||||
out_path = Path(tempfile.mkdtemp()) / 'output.png'
|
||||
cv2.imwrite(str(out_path), output)
|
||||
except Exception as error:
|
||||
print('global exception', error)
|
||||
finally:
|
||||
clean_folder('output')
|
||||
return out_path
|
||||
|
||||
|
||||
def clean_folder(folder):
|
||||
for filename in os.listdir(folder):
|
||||
file_path = os.path.join(folder, filename)
|
||||
try:
|
||||
if os.path.isfile(file_path) or os.path.islink(file_path):
|
||||
os.unlink(file_path)
|
||||
elif os.path.isdir(file_path):
|
||||
shutil.rmtree(file_path)
|
||||
except Exception as e:
|
||||
print(f'Failed to delete {file_path}. Reason: {e}')
|
||||
@@ -3,7 +3,7 @@ import os.path as osp
|
||||
import torch
|
||||
from basicsr.archs import build_network
|
||||
from basicsr.losses import build_loss
|
||||
from basicsr.losses.losses import r1_penalty
|
||||
from basicsr.losses.gan_loss import r1_penalty
|
||||
from basicsr.metrics import calculate_metric
|
||||
from basicsr.models.base_model import BaseModel
|
||||
from basicsr.utils import get_root_logger, imwrite, tensor2img
|
||||
|
||||
@@ -29,12 +29,12 @@ class GFPGANer():
|
||||
bg_upsampler (nn.Module): The upsampler for the background. Default: None.
|
||||
"""
|
||||
|
||||
def __init__(self, model_path, upscale=2, arch='clean', channel_multiplier=2, bg_upsampler=None):
|
||||
def __init__(self, model_path, upscale=2, arch='clean', channel_multiplier=2, bg_upsampler=None, device=None):
|
||||
self.upscale = upscale
|
||||
self.bg_upsampler = bg_upsampler
|
||||
|
||||
# initialize model
|
||||
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
||||
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') if device is None else device
|
||||
# initialize the GFP-GAN
|
||||
if arch == 'clean':
|
||||
self.gfpgan = GFPGANv1Clean(
|
||||
@@ -79,7 +79,9 @@ class GFPGANer():
|
||||
crop_ratio=(1, 1),
|
||||
det_model='retinaface_resnet50',
|
||||
save_ext='png',
|
||||
device=self.device)
|
||||
use_parse=True,
|
||||
device=self.device,
|
||||
model_rootpath='gfpgan/weights')
|
||||
|
||||
if model_path.startswith('https://'):
|
||||
model_path = load_file_from_url(
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
torch>=1.7
|
||||
numpy<1.21 # numba requires numpy<1.21,>=1.17
|
||||
opencv-python
|
||||
torchvision
|
||||
scipy
|
||||
tqdm
|
||||
basicsr>=1.3.4.0
|
||||
facexlib>=0.2.0.3
|
||||
basicsr>=1.4.2
|
||||
facexlib>=0.2.5
|
||||
lmdb
|
||||
numpy
|
||||
opencv-python
|
||||
pyyaml
|
||||
scipy
|
||||
tb-nightly
|
||||
torch>=1.7
|
||||
torchvision
|
||||
tqdm
|
||||
yapf
|
||||
|
||||
Reference in New Issue
Block a user