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()
|