2023-12-25 12:43:51 +00:00
import logging
2023-05-29 07:38:51 +00:00
import sys
2022-09-26 14:29:50 +00:00
2022-09-26 14:29:22 +00:00
import numpy as np
import torch
2022-09-26 14:29:50 +00:00
from PIL import Image
2022-12-03 15:06:33 +00:00
from modules import modelloader , devices , script_callbacks , shared
2023-12-30 20:53:49 +00:00
from modules . shared import opts
2022-09-29 22:46:23 +00:00
from modules . upscaler import Upscaler , UpscalerData
2023-12-30 20:53:49 +00:00
from modules . upscaler_utils import tiled_upscale_2
2022-09-26 14:29:22 +00:00
2023-06-13 10:00:05 +00:00
SWINIR_MODEL_URL = " https://github.com/JingyunLiang/SwinIR/releases/download/v0.0/003_realSR_BSRGAN_DFOWMFC_s64w8_SwinIR-L_x4_GAN.pth "
2022-09-26 14:29:22 +00:00
2023-12-25 12:43:51 +00:00
logger = logging . getLogger ( __name__ )
2022-12-03 15:06:33 +00:00
2022-09-29 22:46:23 +00:00
class UpscalerSwinIR ( Upscaler ) :
def __init__ ( self , dirname ) :
2023-07-08 19:05:38 +00:00
self . _cached_model = None # keep the model when SWIN_torch_compile is on to prevent re-compile every runs
self . _cached_model_config = None # to clear '_cached_model' when changing model (v1/v2) or settings
2022-09-29 22:46:23 +00:00
self . name = " SwinIR "
2023-06-13 10:00:05 +00:00
self . model_url = SWINIR_MODEL_URL
2022-09-29 22:46:23 +00:00
self . model_name = " SwinIR 4x "
self . user_path = dirname
super ( ) . __init__ ( )
scalers = [ ]
model_files = self . find_models ( ext_filter = [ " .pt " , " .pth " ] )
for model in model_files :
2023-05-29 06:41:36 +00:00
if model . startswith ( " http " ) :
2022-09-29 22:46:23 +00:00
name = self . model_name
else :
name = modelloader . friendly_name ( model )
model_data = UpscalerData ( name , model , self )
scalers . append ( model_data )
self . scalers = scalers
2023-12-25 12:43:51 +00:00
def do_upscale ( self , img : Image . Image , model_file : str ) - > Image . Image :
2023-07-08 19:05:38 +00:00
current_config = ( model_file , opts . SWIN_tile )
2023-12-25 12:43:51 +00:00
device = self . _get_device ( )
if self . _cached_model_config == current_config :
2023-07-08 19:05:38 +00:00
model = self . _cached_model
else :
try :
model = self . load_model ( model_file )
except Exception as e :
print ( f " Failed loading SwinIR model { model_file } : { e } " , file = sys . stderr )
return img
2023-12-25 12:43:51 +00:00
self . _cached_model = model
self . _cached_model_config = current_config
img = upscale (
img ,
model ,
tile = opts . SWIN_tile ,
tile_overlap = opts . SWIN_tile_overlap ,
device = device ,
)
2023-07-08 14:13:18 +00:00
devices . torch_gc ( )
2022-09-29 22:46:23 +00:00
return img
2022-09-26 14:29:22 +00:00
2022-09-29 22:46:23 +00:00
def load_model ( self , path , scale = 4 ) :
2023-05-29 06:41:36 +00:00
if path . startswith ( " http " ) :
2023-05-29 06:34:26 +00:00
filename = modelloader . load_file_from_url (
url = path ,
model_dir = self . model_download_path ,
file_name = f " { self . model_name . replace ( ' ' , ' _ ' ) } .pth " ,
)
2022-09-29 22:46:23 +00:00
else :
filename = path
2023-12-30 22:09:51 +00:00
model_descriptor = modelloader . load_spandrel_model (
2023-12-25 12:43:51 +00:00
filename ,
device = self . _get_device ( ) ,
dtype = devices . dtype ,
2023-12-30 14:37:03 +00:00
expected_architecture = " SwinIR " ,
2023-12-25 12:43:51 +00:00
)
if getattr ( opts , ' SWIN_torch_compile ' , False ) :
try :
2023-12-30 22:09:51 +00:00
model_descriptor . model . compile ( )
2023-12-25 12:43:51 +00:00
except Exception :
logger . warning ( " Failed to compile SwinIR model, fallback to JIT " , exc_info = True )
2023-12-30 22:09:51 +00:00
return model_descriptor
2022-09-26 14:29:22 +00:00
2023-12-25 12:43:51 +00:00
def _get_device ( self ) :
return devices . get_device_for ( ' swinir ' )
2022-09-26 14:29:22 +00:00
def upscale (
2023-12-25 12:43:51 +00:00
img ,
model ,
* ,
tile : int ,
tile_overlap : int ,
window_size = 8 ,
scale = 4 ,
device ,
2022-09-26 14:29:22 +00:00
) :
2022-12-03 17:40:11 +00:00
2022-09-26 14:29:22 +00:00
img = np . array ( img )
img = img [ : , : , : : - 1 ]
img = np . moveaxis ( img , 2 , 0 ) / 255
img = torch . from_numpy ( img ) . float ( )
2023-12-25 12:43:51 +00:00
img = img . unsqueeze ( 0 ) . to ( device , dtype = devices . dtype )
2022-11-29 02:36:35 +00:00
with torch . no_grad ( ) , devices . autocast ( ) :
2022-09-26 14:29:22 +00:00
_ , _ , h_old , w_old = img . size ( )
h_pad = ( h_old / / window_size + 1 ) * window_size - h_old
w_pad = ( w_old / / window_size + 1 ) * window_size - w_old
img = torch . cat ( [ img , torch . flip ( img , [ 2 ] ) ] , 2 ) [ : , : , : h_old + h_pad , : ]
img = torch . cat ( [ img , torch . flip ( img , [ 3 ] ) ] , 3 ) [ : , : , : , : w_old + w_pad ]
2023-12-30 20:53:49 +00:00
output = tiled_upscale_2 (
2023-12-25 12:43:51 +00:00
img ,
model ,
2023-12-30 20:53:49 +00:00
tile_size = tile ,
2023-12-25 12:43:51 +00:00
tile_overlap = tile_overlap ,
scale = scale ,
device = device ,
2023-12-30 20:53:49 +00:00
desc = " SwinIR tiles " ,
2023-12-25 12:43:51 +00:00
)
2022-09-26 14:29:22 +00:00
output = output [ . . . , : h_old * scale , : w_old * scale ]
output = output . data . squeeze ( ) . float ( ) . cpu ( ) . clamp_ ( 0 , 1 ) . numpy ( )
if output . ndim == 3 :
output = np . transpose (
output [ [ 2 , 1 , 0 ] , : , : ] , ( 1 , 2 , 0 )
) # CHW-RGB to HCW-BGR
output = ( output * 255.0 ) . round ( ) . astype ( np . uint8 ) # float32 to uint8
return Image . fromarray ( output , " RGB " )
2022-12-03 15:06:33 +00:00
def on_ui_settings ( ) :
import gradio as gr
shared . opts . add_option ( " SWIN_tile " , shared . OptionInfo ( 192 , " Tile size for all SwinIR. " , gr . Slider , { " minimum " : 16 , " maximum " : 512 , " step " : 16 } , section = ( ' upscaling ' , " Upscaling " ) ) )
shared . opts . add_option ( " SWIN_tile_overlap " , shared . OptionInfo ( 8 , " Tile overlap, in pixels for SwinIR. Low values = visible seam. " , gr . Slider , { " minimum " : 0 , " maximum " : 48 , " step " : 1 } , section = ( ' upscaling ' , " Upscaling " ) ) )
2023-12-25 12:43:51 +00:00
shared . opts . add_option ( " SWIN_torch_compile " , shared . OptionInfo ( False , " Use torch.compile to accelerate SwinIR. " , gr . Checkbox , { " interactive " : True } , section = ( ' upscaling ' , " Upscaling " ) ) . info ( " Takes longer on first run " ) )
2022-12-03 15:06:33 +00:00
script_callbacks . on_ui_settings ( on_ui_settings )