Update app.py
Browse files
app.py
CHANGED
|
@@ -12,14 +12,17 @@ from huggingface_hub import hf_hub_download
|
|
| 12 |
import subprocess
|
| 13 |
|
| 14 |
# Install Real-ESRGAN with dependencies
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
from RealESRGAN import RealESRGAN
|
| 18 |
|
| 19 |
# Force CPU usage
|
| 20 |
device = torch.device("cpu")
|
| 21 |
-
ENABLE_CPU_OFFLOAD = True
|
| 22 |
-
USE_TORCH_COMPILE = False
|
| 23 |
|
| 24 |
# Create model directories
|
| 25 |
os.makedirs("models/Stable-diffusion", exist_ok=True)
|
|
@@ -27,21 +30,17 @@ os.makedirs("models/ControlNet", exist_ok=True)
|
|
| 27 |
os.makedirs("models/VAE", exist_ok=True)
|
| 28 |
os.makedirs("models/upscalers", exist_ok=True)
|
| 29 |
|
| 30 |
-
# Download
|
| 31 |
-
def
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
"CONTROLNET": ("lllyasviel/ControlNet-v1-1", "control_v11f1e_sd15_tile.pth", "models/ControlNet"),
|
| 35 |
-
"VAE": ("stabilityai/sd-vae-ft-mse-original", "vae-ft-mse-840000-ema-pruned.safetensors", "models/VAE"),
|
| 36 |
-
"UPSCALER_X2": ("ai-forever/Real-ESRGAN", "RealESRGAN_x2.pth", "models/upscalers"),
|
| 37 |
-
}
|
| 38 |
-
for model, (repo_id, filename, local_dir) in models.items():
|
| 39 |
-
print(f"Downloading {model}...")
|
| 40 |
hf_hub_download(repo_id=repo_id, filename=filename, local_dir=local_dir)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
# Timer decorator for performance tracking
|
| 45 |
def timer_func(func):
|
| 46 |
def wrapper(*args, **kwargs):
|
| 47 |
start_time = time.time()
|
|
@@ -50,7 +49,7 @@ def timer_func(func):
|
|
| 50 |
return result
|
| 51 |
return wrapper
|
| 52 |
|
| 53 |
-
# Lazy pipeline
|
| 54 |
class LazyLoadPipeline:
|
| 55 |
def __init__(self):
|
| 56 |
self.pipe = None
|
|
@@ -59,6 +58,15 @@ class LazyLoadPipeline:
|
|
| 59 |
def load(self):
|
| 60 |
if self.pipe is None:
|
| 61 |
print("Setting up pipeline...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
controlnet = ControlNetModel.from_single_file(
|
| 63 |
"models/ControlNet/control_v11f1e_sd15_tile.pth", torch_dtype=torch.float16
|
| 64 |
)
|
|
@@ -79,15 +87,15 @@ class LazyLoadPipeline:
|
|
| 79 |
if ENABLE_CPU_OFFLOAD:
|
| 80 |
print("Enabling CPU offloading...")
|
| 81 |
pipe.enable_model_cpu_offload()
|
| 82 |
-
|
| 83 |
return self.pipe
|
| 84 |
|
| 85 |
def __call__(self, *args, **kwargs):
|
| 86 |
if self.pipe is None:
|
| 87 |
-
self.
|
| 88 |
return self.pipe(*args, **kwargs)
|
| 89 |
|
| 90 |
-
# Lazy Real-ESRGAN
|
| 91 |
class LazyRealESRGAN:
|
| 92 |
def __init__(self, device, scale):
|
| 93 |
self.device = device
|
|
@@ -96,6 +104,8 @@ class LazyRealESRGAN:
|
|
| 96 |
|
| 97 |
def load_model(self):
|
| 98 |
if self.model is None:
|
|
|
|
|
|
|
| 99 |
self.model = RealESRGAN(self.device, scale=self.scale)
|
| 100 |
self.model.load_weights(f'models/upscalers/RealESRGAN_x{self.scale}.pth', download=False)
|
| 101 |
|
|
@@ -121,7 +131,7 @@ def create_hdr_effect(original_image, hdr):
|
|
| 121 |
if hdr == 0:
|
| 122 |
return original_image
|
| 123 |
cv_original = cv2.cvtColor(np.array(original_image), cv2.COLOR_RGB2BGR)
|
| 124 |
-
factors = [1.0 - 0.
|
| 125 |
images = [cv2.convertScaleAbs(cv_original, alpha=factor) for factor in factors]
|
| 126 |
merge_mertens = cv2.createMergeMertens()
|
| 127 |
hdr_image = merge_mertens.process(images)
|
|
@@ -132,6 +142,8 @@ lazy_pipe = LazyLoadPipeline()
|
|
| 132 |
|
| 133 |
@timer_func
|
| 134 |
def gradio_process_image(input_image, resolution, num_inference_steps, strength, hdr, guidance_scale):
|
|
|
|
|
|
|
| 135 |
print("Starting image processing...")
|
| 136 |
condition_image = resize_and_upscale(input_image, resolution)
|
| 137 |
condition_image = create_hdr_effect(condition_image, hdr)
|
|
@@ -160,7 +172,7 @@ def gradio_process_image(input_image, resolution, num_inference_steps, strength,
|
|
| 160 |
|
| 161 |
# Gradio interface
|
| 162 |
title = """<h1 align="center">Image Upscaler with Tile ControlNet</h1>
|
| 163 |
-
<p align="center">CPU-optimized
|
| 164 |
|
| 165 |
with gr.Blocks() as demo:
|
| 166 |
gr.HTML(title)
|
|
@@ -171,8 +183,8 @@ with gr.Blocks() as demo:
|
|
| 171 |
with gr.Column():
|
| 172 |
output_slider = ImageSlider(label="Before / After", type="numpy")
|
| 173 |
with gr.Accordion("Advanced Options", open=False):
|
| 174 |
-
resolution = gr.Slider(minimum=256, maximum=
|
| 175 |
-
num_inference_steps = gr.Slider(minimum=1, maximum=
|
| 176 |
strength = gr.Slider(minimum=0, maximum=1, value=0.4, step=0.01, label="Strength")
|
| 177 |
hdr = gr.Slider(minimum=0, maximum=1, value=0, step=0.1, label="HDR Effect")
|
| 178 |
guidance_scale = gr.Slider(minimum=0, maximum=10, value=3, step=0.5, label="Guidance Scale")
|
|
@@ -181,5 +193,5 @@ with gr.Blocks() as demo:
|
|
| 181 |
inputs=[input_image, resolution, num_inference_steps, strength, hdr, guidance_scale],
|
| 182 |
outputs=output_slider)
|
| 183 |
|
| 184 |
-
|
| 185 |
-
demo.launch()
|
|
|
|
| 12 |
import subprocess
|
| 13 |
|
| 14 |
# Install Real-ESRGAN with dependencies
|
| 15 |
+
try:
|
| 16 |
+
subprocess.run("pip install git+https://github.com/inference-sh/Real-ESRGAN.git basicsr opencv-python-headless --no-cache-dir", shell=True, check=True)
|
| 17 |
+
except subprocess.CalledProcessError as e:
|
| 18 |
+
print(f"Failed to install Real-ESRGAN: {e}")
|
| 19 |
|
| 20 |
from RealESRGAN import RealESRGAN
|
| 21 |
|
| 22 |
# Force CPU usage
|
| 23 |
device = torch.device("cpu")
|
| 24 |
+
ENABLE_CPU_OFFLOAD = True
|
| 25 |
+
USE_TORCH_COMPILE = False
|
| 26 |
|
| 27 |
# Create model directories
|
| 28 |
os.makedirs("models/Stable-diffusion", exist_ok=True)
|
|
|
|
| 30 |
os.makedirs("models/VAE", exist_ok=True)
|
| 31 |
os.makedirs("models/upscalers", exist_ok=True)
|
| 32 |
|
| 33 |
+
# Download models on-demand
|
| 34 |
+
def download_model(repo_id, filename, local_dir):
|
| 35 |
+
try:
|
| 36 |
+
print(f"Downloading {filename} from {repo_id}...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
hf_hub_download(repo_id=repo_id, filename=filename, local_dir=local_dir)
|
| 38 |
+
print(f"Successfully downloaded {filename}")
|
| 39 |
+
except Exception as e:
|
| 40 |
+
print(f"Failed to download {filename}: {e}")
|
| 41 |
+
raise
|
| 42 |
|
| 43 |
+
# Timer decorator
|
|
|
|
|
|
|
| 44 |
def timer_func(func):
|
| 45 |
def wrapper(*args, **kwargs):
|
| 46 |
start_time = time.time()
|
|
|
|
| 49 |
return result
|
| 50 |
return wrapper
|
| 51 |
|
| 52 |
+
# Lazy pipeline
|
| 53 |
class LazyLoadPipeline:
|
| 54 |
def __init__(self):
|
| 55 |
self.pipe = None
|
|
|
|
| 58 |
def load(self):
|
| 59 |
if self.pipe is None:
|
| 60 |
print("Setting up pipeline...")
|
| 61 |
+
# Download models if not present
|
| 62 |
+
for model, (repo_id, filename, local_dir) in [
|
| 63 |
+
("MODEL", ("dantea1118/juggernaut_reborn", "juggernaut_reborn.safetensors", "models/Stable-diffusion")),
|
| 64 |
+
("CONTROLNET", ("lllyasviel/ControlNet-v1-1", "control_v11f1e_sd15_tile.pth", "models/ControlNet")),
|
| 65 |
+
("VAE", ("stabilityai/sd-vae-ft-mse-original", "vae-ft-mse-840000-ema-pruned.safetensors", "models/VAE")),
|
| 66 |
+
]:
|
| 67 |
+
if not os.path.exists(os.path.join(local_dir, filename)):
|
| 68 |
+
download_model(repo_id, filename, local_dir)
|
| 69 |
+
|
| 70 |
controlnet = ControlNetModel.from_single_file(
|
| 71 |
"models/ControlNet/control_v11f1e_sd15_tile.pth", torch_dtype=torch.float16
|
| 72 |
)
|
|
|
|
| 87 |
if ENABLE_CPU_OFFLOAD:
|
| 88 |
print("Enabling CPU offloading...")
|
| 89 |
pipe.enable_model_cpu_offload()
|
| 90 |
+
self.pipe = pipe
|
| 91 |
return self.pipe
|
| 92 |
|
| 93 |
def __call__(self, *args, **kwargs):
|
| 94 |
if self.pipe is None:
|
| 95 |
+
self.load()
|
| 96 |
return self.pipe(*args, **kwargs)
|
| 97 |
|
| 98 |
+
# Lazy Real-ESRGAN
|
| 99 |
class LazyRealESRGAN:
|
| 100 |
def __init__(self, device, scale):
|
| 101 |
self.device = device
|
|
|
|
| 104 |
|
| 105 |
def load_model(self):
|
| 106 |
if self.model is None:
|
| 107 |
+
if not os.path.exists(f"models/upscalers/RealESRGAN_x{self.scale}.pth"):
|
| 108 |
+
download_model("ai-forever/Real-ESRGAN", f"RealESRGAN_x{self.scale}.pth", "models/upscalers")
|
| 109 |
self.model = RealESRGAN(self.device, scale=self.scale)
|
| 110 |
self.model.load_weights(f'models/upscalers/RealESRGAN_x{self.scale}.pth', download=False)
|
| 111 |
|
|
|
|
| 131 |
if hdr == 0:
|
| 132 |
return original_image
|
| 133 |
cv_original = cv2.cvtColor(np.array(original_image), cv2.COLOR_RGB2BGR)
|
| 134 |
+
factors = [1.0 - 0.7 * hdr, 1.0, 1.0 + 0.2 * hdr]
|
| 135 |
images = [cv2.convertScaleAbs(cv_original, alpha=factor) for factor in factors]
|
| 136 |
merge_mertens = cv2.createMergeMertens()
|
| 137 |
hdr_image = merge_mertens.process(images)
|
|
|
|
| 142 |
|
| 143 |
@timer_func
|
| 144 |
def gradio_process_image(input_image, resolution, num_inference_steps, strength, hdr, guidance_scale):
|
| 145 |
+
if input_image is None:
|
| 146 |
+
raise gr.Error("Please upload an input image.")
|
| 147 |
print("Starting image processing...")
|
| 148 |
condition_image = resize_and_upscale(input_image, resolution)
|
| 149 |
condition_image = create_hdr_effect(condition_image, hdr)
|
|
|
|
| 172 |
|
| 173 |
# Gradio interface
|
| 174 |
title = """<h1 align="center">Image Upscaler with Tile ControlNet</h1>
|
| 175 |
+
<p align="center">CPU-optimized for Hugging Face Spaces</p>"""
|
| 176 |
|
| 177 |
with gr.Blocks() as demo:
|
| 178 |
gr.HTML(title)
|
|
|
|
| 183 |
with gr.Column():
|
| 184 |
output_slider = ImageSlider(label="Before / After", type="numpy")
|
| 185 |
with gr.Accordion("Advanced Options", open=False):
|
| 186 |
+
resolution = gr.Slider(minimum=256, maximum=768, value=512, step=64, label="Resolution")
|
| 187 |
+
num_inference_steps = gr.Slider(minimum=1, maximum=15, value=10, step=1, label="Inference Steps")
|
| 188 |
strength = gr.Slider(minimum=0, maximum=1, value=0.4, step=0.01, label="Strength")
|
| 189 |
hdr = gr.Slider(minimum=0, maximum=1, value=0, step=0.1, label="HDR Effect")
|
| 190 |
guidance_scale = gr.Slider(minimum=0, maximum=10, value=3, step=0.5, label="Guidance Scale")
|
|
|
|
| 193 |
inputs=[input_image, resolution, num_inference_steps, strength, hdr, guidance_scale],
|
| 194 |
outputs=output_slider)
|
| 195 |
|
| 196 |
+
if __name__ == "__main__":
|
| 197 |
+
demo.launch()
|