mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
3929bd3e13
* installer tweaks in preparation for v2.2.5 - pin numpy to 1.23.* to avoid requirements conflict with numba - update.sh and update.bat now accept a tag or branch string, not a URL - update scripts download latest requirements-base before updating. * update.bat.in debugged and working * update pulls from "latest" now * bump version number * fix permissions on create_installer.sh * give Linux user option of installing ROCm or CUDA * rc2.2.5 (install.sh) relative path fixes (#2155) * (installer) fix bug in resolution of relative paths in linux install script point installer at 2.2.5-rc1 selecting ~/Data/myapps/ as location would create a ./~/Data/myapps instead of expanding the ~/ to the value of ${HOME} also, squash the trailing slash in path, if it was entered by the user * (installer) add option to automatically start the app after install also: when exiting, print the command to get back into the app * remove extraneous whitespace * model_cache applies rootdir to config path * bring installers up to date with 2.2.5-rc2 * bump rc version * create_installer now adds version number * rebuild frontend * bump rc# * add locales to frontend dist package - bump to patchlevel 6 * bump patchlevel * use invoke-ai version of GFPGAN - This version is very slightly modified to allow weights files to be pre-downloaded by the configure script. * fix formatting error during startup * bump patch level * workaround #2 for GFPGAN facexlib() weights downloading * bump patch * ready for merge and release * remove extraneous comment * set PYTORCH_ENABLE_MPS_FALLBACK directly in invoke.py Co-authored-by: Eugene Brodsky <ebr@users.noreply.github.com>
88 lines
2.8 KiB
Python
88 lines
2.8 KiB
Python
import torch
|
|
import warnings
|
|
import os
|
|
import sys
|
|
import numpy as np
|
|
from ldm.invoke.globals import Globals
|
|
|
|
from PIL import Image
|
|
|
|
|
|
class GFPGAN():
|
|
def __init__(
|
|
self,
|
|
gfpgan_model_path='models/gfpgan/GFPGANv1.4.pth'
|
|
) -> None:
|
|
|
|
if not os.path.isabs(gfpgan_model_path):
|
|
gfpgan_model_path=os.path.abspath(os.path.join(Globals.root,gfpgan_model_path))
|
|
self.model_path = gfpgan_model_path
|
|
self.gfpgan_model_exists = os.path.isfile(self.model_path)
|
|
|
|
if not self.gfpgan_model_exists:
|
|
print('## NOT FOUND: GFPGAN model not found at ' + self.model_path)
|
|
return None
|
|
|
|
def model_exists(self):
|
|
return os.path.isfile(self.model_path)
|
|
|
|
def process(self, image, strength: float, seed: str = None):
|
|
if seed is not None:
|
|
print(f'>> GFPGAN - Restoring Faces for image seed:{seed}')
|
|
|
|
with warnings.catch_warnings():
|
|
warnings.filterwarnings('ignore', category=DeprecationWarning)
|
|
warnings.filterwarnings('ignore', category=UserWarning)
|
|
cwd = os.getcwd()
|
|
os.chdir(os.path.join(Globals.root,'models'))
|
|
try:
|
|
from gfpgan import GFPGANer
|
|
self.gfpgan = GFPGANer(
|
|
model_path=self.model_path,
|
|
upscale=1,
|
|
arch='clean',
|
|
channel_multiplier=2,
|
|
bg_upsampler=None,
|
|
)
|
|
except Exception:
|
|
import traceback
|
|
print('>> Error loading GFPGAN:', file=sys.stderr)
|
|
print(traceback.format_exc(), file=sys.stderr)
|
|
os.chdir(cwd)
|
|
|
|
if self.gfpgan is None:
|
|
print(
|
|
f'>> WARNING: GFPGAN not initialized.'
|
|
)
|
|
print(
|
|
f'>> Download https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth to {self.model_path}'
|
|
)
|
|
|
|
image = image.convert('RGB')
|
|
|
|
# GFPGAN expects a BGR np array; make array and flip channels
|
|
bgr_image_array = np.array(image, dtype=np.uint8)[...,::-1]
|
|
|
|
_, _, restored_img = self.gfpgan.enhance(
|
|
bgr_image_array,
|
|
has_aligned=False,
|
|
only_center_face=False,
|
|
paste_back=True,
|
|
)
|
|
|
|
# Flip the channels back to RGB
|
|
res = Image.fromarray(restored_img[...,::-1])
|
|
|
|
if strength < 1.0:
|
|
# Resize the image to the new image if the sizes have changed
|
|
if restored_img.size != image.size:
|
|
image = image.resize(res.size)
|
|
res = Image.blend(image, res, strength)
|
|
|
|
|
|
if torch.cuda.is_available():
|
|
torch.cuda.empty_cache()
|
|
self.gfpgan = None
|
|
|
|
return res
|