upscale / app.py
Phips's picture
Upload project
b394b97
raw
history blame
10.5 kB
# Code taken (and slightly adopted) from https://huggingface.co/spaces/havas79/Real-ESRGAN_Demo/blob/main/app.py - credit where credit is due. I am not showcasing code here, but demoing my own trained models ;)
import gradio as gr
import cv2
import numpy
import os
import random
from basicsr.archs.rrdbnet_arch import RRDBNet
from basicsr.utils.download_util import load_file_from_url
from realesrgan import RealESRGANer
from realesrgan.archs.srvgg_arch import SRVGGNetCompact
last_file = None
img_mode = "RGBA"
def realesrgan(img, model_name, face_enhance):
if not img:
return
imgwidth, imgheight = img.size
if imgwidth > 1000 or imgheight > 1000:
return error("Input Image too big")
# Define model parameters
if model_name == '4xNomos8kSC':
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
netscale = 4
elif model_name == '4xHFA2k':
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
netscale = 4
elif model_name == '4xLSDIR':
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
netscale = 4
elif model_name == '4xLSDIRplusN':
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
netscale = 4
elif model_name == '4xLSDIRplusC':
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
netscale = 4
elif model_name == '4xLSDIRplusR':
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
netscale = 4
elif model_name == '2xParimgCompact':
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=16, upscale=2, act_type='prelu')
netscale = 2
elif model_name == '2xHFA2kCompact':
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=16, upscale=2, act_type='prelu')
netscale = 2
elif model_name == '4xLSDIRCompactN':
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=16, upscale=4, act_type='prelu')
netscale = 4
elif model_name == '4xLSDIRCompactC3':
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=16, upscale=4, act_type='prelu')
netscale = 4
elif model_name == '4xLSDIRCompactR3':
model = SRVGGNetCompact(num_in_ch=3, num_out_ch=3, num_feat=64, num_conv=16, upscale=4, act_type='prelu')
netscale = 4
# Determine model paths
model_path = os.path.join('weights', model_name + '.pth')
# Restorer Class
upsampler = RealESRGANer(
scale=netscale,
model_path=model_path,
dni_weight=None,
model=model,
tile=0,
tile_pad=10,
pre_pad=10,
half=False,
gpu_id=None,
)
# Use GFPGAN for face enhancement
if face_enhance:
from gfpgan import GFPGANer
face_enhancer = GFPGANer(
model_path='https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.4.pth',
upscale=netscale,
arch='clean',
channel_multiplier=2,
bg_upsampler=upsampler)
# Convert the input PIL image to cv2 image, so that it can be processed by realesrgan
cv_img = numpy.array(img)
img = cv2.cvtColor(cv_img, cv2.COLOR_RGBA2BGRA)
# Apply restoration
try:
if face_enhance:
_, _, output = face_enhancer.enhance(img, has_aligned=False, only_center_face=False, paste_back=True)
else:
output, _ = upsampler.enhance(img, netscale)
except RuntimeError as error:
print('Error', error)
print('If you encounter CUDA out of memory, try to set --tile with a smaller number.')
else:
# Save restored image and return it to the output Image component
if img_mode == 'RGBA': # RGBA images should be saved in png format
extension = 'png'
else:
extension = 'jpg'
out_filename = f"output_{rnd_string(16)}.{extension}"
cv2.imwrite(out_filename, output)
global last_file
last_file = out_filename
return out_filename
def rnd_string(x):
"""Returns a string of 'x' random characters
"""
characters = "abcdefghijklmnopqrstuvwxyz_0123456789"
result = "".join((random.choice(characters)) for i in range(x))
return result
def reset():
"""Resets the Image components of the Gradio interface and deletes
the last processed image
"""
global last_file
if last_file:
print(f"Deleting {last_file} ...")
os.remove(last_file)
last_file = None
return gr.update(value=None), gr.update(value=None)
def has_transparency(img):
"""This function works by first checking to see if a "transparency" property is defined
in the image's info -- if so, we return "True". Then, if the image is using indexed colors
(such as in GIFs), it gets the index of the transparent color in the palette
(img.info.get("transparency", -1)) and checks if it's used anywhere in the canvas
(img.getcolors()). If the image is in RGBA mode, then presumably it has transparency in
it, but it double-checks by getting the minimum and maximum values of every color channel
(img.getextrema()), and checks if the alpha channel's smallest value falls below 255.
https://stackoverflow.com/questions/43864101/python-pil-check-if-image-is-transparent
"""
if img.info.get("transparency", None) is not None:
return True
if img.mode == "P":
transparent = img.info.get("transparency", -1)
for _, index in img.getcolors():
if index == transparent:
return True
elif img.mode == "RGBA":
extrema = img.getextrema()
if extrema[3][0] < 255:
return True
return False
def image_properties(img):
"""Returns the dimensions (width and height) and color mode of the input image and
also sets the global img_mode variable to be used by the realesrgan function
"""
global img_mode
if img:
if has_transparency(img):
img_mode = "RGBA"
else:
img_mode = "RGB"
properties = f"Width: {img.size[0]}, Height: {img.size[1]} | Color Mode: {img_mode}"
return properties
def main():
# Gradio Interface
with gr.Blocks(title="Self-trained ESRGAN models demo", theme="dark") as demo:
gr.Markdown(
"""# <div align="center"> Upscale image </div>
Here I demo my self-trained models. The models with their corresponding infos can be found on [my github repo](https://github.com/phhofm/models).
"""
)
with gr.Group():
with gr.Group():
model_name = gr.Dropdown(label="Model to be used",
choices=["2xHFA2kCompact", "2xParimgCompact", "4xLSDIRCompactN", "4xLSDIRCompactC3", "4xLSDIRCompactR3", "4xNomos8kSC", "4xHFA2k", "4xLSDIR", "4xLSDIRplusN", "4xLSDIRplusC", "4xLSDIRplusR"], value="4xLSDIRCompactC3",
info="See model infos at the bottom of this page")
face_enhance = gr.Checkbox(label="Face Enhancement using GFPGAN (Doesn't work for anime images)",value=False, show_label=True)
with gr.Row():
with gr.Group():
input_image = gr.Image(label="Source Image", type="pil", image_mode="RGBA")
input_image_properties = gr.Textbox(label="Image Properties - Demo will throw error if input image has either width or height > 1000. Output download is jpg for smaller size. Use models locally to circument these limits.", max_lines=1)
output_image = gr.Image(label="Upscaled Image", image_mode="RGBA")
with gr.Row():
upscale_btn = gr.Button("Upscale")
reset_btn = gr.Button("Reset")
with gr.Group():
gr.Markdown(
"""
**Model infos**
*SRVGGNetCompact models - in general faster, but less powerful, than RRDBNet*
2xHFA2kCompact - use for upscaling anime images 2x, faster than 4xHFA2k but less powerful (SRVGGNetCompact)
2xParimgCompact - upscaling photos 2x, fast (SRVGGNetCompact)
4xLSDIRCompactN - upscale a good quality photo (no degradations) 4x, faster than 4xLSDIRN but less powerful (SRVGGNetCompact)
4xLSDIRCompactC3 - upscale a jpg compressed photo 4x, fast (SRVGGNetCompact)
4xLSDIRCompactR3 - upscale a degraded photo 4x, fast (SRVGGNetCompact) (too strong, best used for interpolation like 4xLSDIRCompactN (or C) 75% 4xLSDIRCompactR3 25% to add little degradation handling to the previous one)
*RRDBNet models - in general more powerful than SRVGGNetCompact, but very slow in this demo*
4xNomos8kSC - use for upscaling photos 4x
4xHFA2k - use for upscaling anime images 4x
4xLSDIR - upscale a good quality photo (no degradation) 4x
4xLSDIRplusN - upscale a good quality photo (no degradation) 4x
4xLSDIRplusC - upscale a jpg compressed photo 4x
4xLSDIRplusR - upscale a degraded photo 4x (too strong, best used for interpolation like 4xLSDIRplusN (or C) 75% 4xLSDIRplusR 25% to add little degradation handling to the previous one)
*The following are not models I had trained, but rather interpolations I had created, they are available on my [repo](https://github.com/phhofm/models) and can be tried out locally with chaiNNer:*
4xLSDIRCompact3 (4xLSDIRCompactC3 + 4xLSDIRCompactR3)
4xLSDIRCompact2 (4xLSDIRCompactC2 + 4xLSDIRCompactR2)
4xInt-Ultracri (UltraSharp + Remacri)
4xInt-Superscri (Superscale + Remacri)
4xInt-Siacri(Siax + Remacri)
4xInt-RemDF2K (Remacri + RealSR_DF2K_JPEG)
4xInt-RemArt (Remacri + VolArt)
4xInt-RemAnime (Remacri + AnimeSharp)
4xInt-RemacRestore (Remacri + UltraMix_Restore)
4xInt-AnimeArt (AnimeSharp + VolArt)
2xInt-LD-AnimeJaNai (LD-Anime + AnimeJaNai)
""")
# Event listeners:
input_image.change(fn=image_properties, inputs=input_image, outputs=input_image_properties)
upscale_btn.click(fn=realesrgan, inputs=[input_image, model_name, face_enhance], outputs=output_image)
reset_btn.click(fn=reset, inputs=[], outputs=[output_image, input_image])
demo.launch()
if __name__ == "__main__":
main()