User-2468's picture
Serve Gradio directly without optional SSR proxy
f0a94d4 verified
Raw History Blame
4.67 kB
"""Pinned-release Gradio app. Import spaces before torch for ZeroGPU emulation."""
import os
from pathlib import Path
import spaces
import torch
import gradio as gr
from huggingface_hub import snapshot_download
from inference import prepare, chroma_coefficients, render, load_colorizer
import json
REPO=os.getenv('MODEL_ID','User-2468/mini-unet-colorizer')
REV=os.getenv('MODEL_REVISION','1a9eb8af2754ad2329a24cfe50d388cb559441d0')
SUBFOLDER=os.getenv('MODEL_SUBFOLDER','').strip('/')
CPU=os.getenv('ZEROGPU_CPU_TEST')=='1'
DEVICE='cpu' if CPU else 'cuda'
if CPU:torch.set_num_threads(min(4,os.cpu_count() or 1))
path=Path(REPO)
if not path.is_dir():
prefix=SUBFOLDER+'/' if SUBFOLDER else ''
path=Path(snapshot_download(REPO,revision=REV,allow_patterns=[prefix+'model.safetensors',prefix+'config.json']))
if SUBFOLDER:path=path/SUBFOLDER
cfg=json.loads((path/'config.json').read_text())
if cfg.get('architecture')=='DecisionColorizer':
from decision_model import load_decision
MODEL=load_decision(path,DEVICE)
else:MODEL=load_colorizer(path,DEVICE)
MODEL.eval().requires_grad_(False)
PARAMETERS=sum(p.numel() for p in MODEL.parameters())
if PARAMETERS>=4_000_000:raise RuntimeError('Model exceeds the four-million-parameter limit.')
MODES=getattr(MODEL,'modes',1)
class PaletteView(torch.nn.Module):
def __init__(self,model,mode):super().__init__();self.model=model;self.mode=mode
def forward(self,L):
return self.model(L) if self.mode<0 else self.model(L,True)['all'][:,self.mode]
@spaces.GPU(duration=15)
def infer(small,radius,mode):
return chroma_coefficients(PaletteView(MODEL,mode),small,radius)
def run(image,strength,smoothing,detail,mode):
if image is None:raise gr.Error('Upload a photograph first.')
mode=int(mode)
if mode < -1 or mode>=MODES or (MODES==1 and mode!=-1):raise gr.Error('That colour interpretation is unavailable.')
try:
radius={'Gentle':4,'Balanced':8,'Strong':16}[smoothing]
size={'Standard':256,'Detailed':384,'Maximum':512}[detail]
light,alpha,small=prepare(image,size)
coefficients=infer(small,radius,mode)
result=render(light,alpha,coefficients,strength)
cache=(light,alpha,coefficients)
except (ValueError,RuntimeError,TypeError,KeyError) as exc:
raise gr.Error(str(exc)) from exc
return result,cache
def recolour(strength,cache):
if cache is None:return gr.skip()
light,alpha,coefficients=cache
return render(light,alpha,coefficients,strength)
with gr.Blocks(title='Mini Photo Colorizer',delete_cache=(3600,3600)) as demo:
gr.Markdown('# Give an old photograph new colour\nPlausible colour, with the original detail and proportions preserved.')
cache=gr.State(value=None,time_to_live=600)
with gr.Row():
source=gr.Image(type='pil',image_mode='RGBA',label='Your photograph',sources=['upload','clipboard'],height=460)
result=gr.Image(type='pil',label='Colourised photograph',format='png',height=460,interactive=False)
with gr.Row():
button=gr.Button('Colourise',variant='primary',scale=2)
clear=gr.ClearButton([source,result,cache],value='Clear',scale=1)
strength=gr.Slider(0,1.5,value=1.,step=.05,label='Colour strength',info='Adjust after colourising without another GPU request.')
with gr.Accordion('Fine-tune the result',open=False):
detail=gr.Radio(['Standard','Detailed','Maximum'],value='Standard',label='Detail',info='Higher detail can change the colours. Try Detailed if small objects are missed.')
smoothing=gr.Radio(['Gentle','Balanced','Strong'],value='Balanced',label='Colour smoothing')
palette=gr.Dropdown([('Automatic',-1)]+[(f'Alternative {i+1}',i) for i in range(MODES)] if MODES>1 else [('Automatic',-1)],value=-1,label='Colour interpretation',visible=MODES>1)
gr.Markdown('After changing these settings, select **Colourise** again.')
button.click(run,[source,strength,smoothing,detail,palette],[result,cache],api_name='colorize',concurrency_limit=1)
strength.release(recolour,[strength,cache],result,api_name=False,concurrency_limit=1)
source.change(lambda:None,outputs=cache,api_name=False,queue=False)
gr.Markdown('Download the result as PNG using its download button. Up to 12 megapixels; transparency is preserved.\n\nColours are interpretations, not recovered historical facts. Unusual scenes, damaged scans and tiny objects can still produce muted colours or colour bleeding. [About the model](https://huggingface.co/User-2468/mini-unet-colorizer).')
demo.queue(default_concurrency_limit=1,max_size=12)
if __name__=='__main__':demo.launch(max_file_size='30mb',ssr_mode=False)