Yankkee commited on
Commit
58b2866
·
verified ·
1 Parent(s): 87bd262

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +42 -7
  2. app.py +190 -0
  3. requirements.txt +8 -0
README.md CHANGED
@@ -1,13 +1,48 @@
1
  ---
2
- title: Depth ControlNet
3
- emoji: 🏆
4
- colorFrom: purple
5
- colorTo: red
6
  sdk: gradio
7
- sdk_version: 6.25.0
8
- python_version: '3.12'
9
  app_file: app.py
10
  pinned: false
 
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Depth ControlNet Logo Generator
3
+ emoji: 🎨
4
+ colorFrom: indigo
5
+ colorTo: pink
6
  sdk: gradio
7
+ sdk_version: 4.44.0
 
8
  app_file: app.py
9
  pinned: false
10
+ license: openrail
11
+ short_description: Depth-ControlNet Logo-Restyling mit SD 1.5 auf ZeroGPU
12
  ---
13
 
14
+ # Depth ControlNet Logo Generator
15
+
16
+ Lädt ein Logo hoch, extrahiert daraus eine Depth Map, und generiert per
17
+ Stable Diffusion 1.5 + ControlNet-Depth ein neu gestyltes Bild, das die
18
+ Struktur/Silhouette der Vorlage beibehält.
19
+
20
+ ## Deployment auf HuggingFace Spaces
21
+
22
+ 1. Neuen Space erstellen: **huggingface.co/new-space**
23
+ 2. SDK: **Gradio** auswählen
24
+ 3. Hardware: **ZeroGPU** auswählen (unter Space-Settings → Hardware)
25
+ - Benötigt einen HF-Account mit ZeroGPU-Zugriff (Pro-Account oder
26
+ freigeschaltete Community-GPU-Quota)
27
+ 4. Diese drei Dateien hochladen (oder per `git push`):
28
+ - `app.py`
29
+ - `requirements.txt`
30
+ - `README.md`
31
+ 5. Space startet automatisch, Modelle werden beim ersten Start
32
+ heruntergeladen (kann 1–2 Minuten dauern).
33
+
34
+ ## Nutzung
35
+
36
+ 1. Logo/Referenzbild hochladen
37
+ 2. Prompt eingeben (Stil, Farben, Motiv)
38
+ 3. Optional: ControlNet-Stärke, Steps, Guidance Scale anpassen
39
+ 4. Generieren klicken
40
+
41
+ ## Hinweise
42
+
43
+ - `controlnet_conditioning_scale` steuert, wie stark die Original-Struktur
44
+ erhalten bleibt (1.0 = Standard, niedriger = mehr Freiheit).
45
+ - Modelle: `runwayml/stable-diffusion-v1-5` + `lllyasviel/sd-controlnet-depth`
46
+ - Für SDXL-Qualität könnte `diffusers/controlnet-depth-sdxl-1.0` +
47
+ ein SDXL-Basismodell eingesetzt werden (langsamer, mehr GPU-Zeit nötig —
48
+ ZeroGPU-Timeout ggf. erhöhen).
app.py ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Depth ControlNet Logo Generator
3
+ --------------------------------
4
+ - Nimmt ein hochgeladenes Logo/Referenzbild
5
+ - Berechnet daraus eine Depth Map (Midas)
6
+ - Generiert per Stable Diffusion 1.5 + ControlNet-Depth ein neues,
7
+ strukturell ähnliches Bild nach Text-Prompt
8
+ - Läuft auf HuggingFace ZeroGPU (dynamisch zugewiesene GPU pro Request)
9
+ """
10
+
11
+ import spaces
12
+ import gradio as gr
13
+ import numpy as np
14
+ import torch
15
+ from PIL import Image
16
+ from diffusers import (
17
+ StableDiffusionControlNetPipeline,
18
+ ControlNetModel,
19
+ UniPCMultistepScheduler,
20
+ )
21
+ from transformers import pipeline as hf_pipeline
22
+
23
+ # ---------------------------------------------------------------------------
24
+ # Konfiguration
25
+ # ---------------------------------------------------------------------------
26
+ SD_MODEL_ID = "runwayml/stable-diffusion-v1-5"
27
+ CONTROLNET_ID = "lllyasviel/sd-controlnet-depth"
28
+ DEPTH_MODEL_ID = "Intel/dpt-hybrid-midas" # gleicher Preprocessor wie beim ControlNet-Training
29
+ RESOLUTION = 512 # native SD1.5 Auflösung
30
+
31
+ device = "cuda"
32
+ dtype = torch.float16
33
+
34
+ # ---------------------------------------------------------------------------
35
+ # Modelle laden (einmalig beim Space-Start)
36
+ # Bei ZeroGPU: .to("cuda") hier ist ok, tatsächliche GPU wird erst bei
37
+ # @spaces.GPU-Aufrufen zugewiesen.
38
+ # ---------------------------------------------------------------------------
39
+ print("Lade Depth-Estimator ...")
40
+ depth_estimator = hf_pipeline("depth-estimation", model=DEPTH_MODEL_ID)
41
+
42
+ print("Lade ControlNet + Stable Diffusion Pipeline ...")
43
+ controlnet = ControlNetModel.from_pretrained(CONTROLNET_ID, torch_dtype=dtype)
44
+ pipe = StableDiffusionControlNetPipeline.from_pretrained(
45
+ SD_MODEL_ID,
46
+ controlnet=controlnet,
47
+ torch_dtype=dtype,
48
+ safety_checker=None,
49
+ )
50
+ pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
51
+ pipe = pipe.to(device)
52
+
53
+ try:
54
+ pipe.enable_xformers_memory_efficient_attention()
55
+ except Exception:
56
+ pass
57
+
58
+
59
+ # ---------------------------------------------------------------------------
60
+ # Hilfsfunktionen
61
+ # ---------------------------------------------------------------------------
62
+ def preprocess_image(image: Image.Image, resolution: int = RESOLUTION) -> Image.Image:
63
+ """Logo auf quadratische Zielauflösung bringen."""
64
+ image = image.convert("RGB")
65
+ image = image.resize((resolution, resolution), Image.LANCZOS)
66
+ return image
67
+
68
+
69
+ def get_depth_map(image: Image.Image) -> Image.Image:
70
+ """Depth Map aus dem Logo berechnen (das ist das ControlNet-Kontrollbild)."""
71
+ depth = depth_estimator(image)["depth"]
72
+ depth = np.array(depth)
73
+ depth = depth[:, :, None]
74
+ depth = np.concatenate([depth, depth, depth], axis=2)
75
+ return Image.fromarray(depth)
76
+
77
+
78
+ # ---------------------------------------------------------------------------
79
+ # Haupt-Generierungsfunktion (läuft auf der ZeroGPU-Instanz)
80
+ # ---------------------------------------------------------------------------
81
+ @spaces.GPU(duration=60)
82
+ def generate(
83
+ logo_image,
84
+ prompt,
85
+ negative_prompt,
86
+ controlnet_scale,
87
+ num_steps,
88
+ guidance_scale,
89
+ seed,
90
+ progress=gr.Progress(track_tqdm=True),
91
+ ):
92
+ if logo_image is None:
93
+ raise gr.Error("Bitte zuerst ein Logo-/Referenzbild hochladen.")
94
+ if not prompt or prompt.strip() == "":
95
+ raise gr.Error("Bitte einen Prompt eingeben.")
96
+
97
+ logo_image = preprocess_image(logo_image)
98
+ depth_image = get_depth_map(logo_image)
99
+
100
+ seed = int(seed)
101
+ if seed < 0:
102
+ generator = None # zufälliger Seed
103
+ else:
104
+ generator = torch.Generator(device=device).manual_seed(seed)
105
+
106
+ result = pipe(
107
+ prompt=prompt,
108
+ negative_prompt=negative_prompt,
109
+ image=depth_image,
110
+ num_inference_steps=int(num_steps),
111
+ guidance_scale=float(guidance_scale),
112
+ controlnet_conditioning_scale=float(controlnet_scale),
113
+ generator=generator,
114
+ ).images[0]
115
+
116
+ return result, depth_image
117
+
118
+
119
+ # ---------------------------------------------------------------------------
120
+ # Gradio UI
121
+ # ---------------------------------------------------------------------------
122
+ with gr.Blocks(title="Depth ControlNet Logo Generator") as demo:
123
+ gr.Markdown(
124
+ """
125
+ # 🎨 Depth ControlNet — Logo Generator
126
+ Lade ein bestehendes Logo hoch, gib einen neuen Stil-Prompt ein.
127
+ Die **Tiefenstruktur / Silhouette** des Logos bleibt erhalten,
128
+ während Stil, Farben und Textur komplett neu generiert werden.
129
+ """
130
+ )
131
+
132
+ with gr.Row():
133
+ with gr.Column():
134
+ logo_input = gr.Image(
135
+ label="1️⃣ Logo / Referenzbild hochladen",
136
+ type="pil",
137
+ height=300,
138
+ )
139
+ prompt = gr.Textbox(
140
+ label="2️⃣ Prompt",
141
+ placeholder="z.B. vintage japanese emblem logo, ink brush style, minimal, black and red, flat vector, white background",
142
+ lines=3,
143
+ )
144
+ negative_prompt = gr.Textbox(
145
+ label="Negative Prompt",
146
+ value="blurry, low quality, watermark, text, extra elements, photo, 3d render",
147
+ lines=2,
148
+ )
149
+
150
+ with gr.Accordion("⚙️ Erweiterte Einstellungen", open=False):
151
+ controlnet_scale = gr.Slider(
152
+ 0.0, 2.0, value=1.0, step=0.05,
153
+ label="ControlNet Conditioning Scale (Struktur-Treue)",
154
+ )
155
+ num_steps = gr.Slider(10, 50, value=25, step=1, label="Inference Steps")
156
+ guidance_scale = gr.Slider(1.0, 20.0, value=7.5, step=0.5, label="Guidance Scale")
157
+ seed = gr.Slider(-1, 999999, value=-1, step=1, label="Seed (-1 = zufällig)")
158
+
159
+ run_button = gr.Button("🚀 Generieren", variant="primary")
160
+
161
+ with gr.Column():
162
+ output_image = gr.Image(label="Ergebnis", height=400)
163
+ depth_preview = gr.Image(label="Erkannte Depth Map (Kontrollbild)", height=200)
164
+
165
+ run_button.click(
166
+ fn=generate,
167
+ inputs=[
168
+ logo_input,
169
+ prompt,
170
+ negative_prompt,
171
+ controlnet_scale,
172
+ num_steps,
173
+ guidance_scale,
174
+ seed,
175
+ ],
176
+ outputs=[output_image, depth_preview],
177
+ )
178
+
179
+ gr.Markdown(
180
+ """
181
+ ---
182
+ 💡 **Tipps:**
183
+ - Höherer *ControlNet Conditioning Scale* = Form/Struktur des Original-Logos wird strenger befolgt.
184
+ - Niedrigerer Wert = mehr kreative Freiheit, weniger Ähnlichkeit zur Vorlage.
185
+ - Für saubere Vektor-Optik: Begriffe wie "flat vector", "clean lines", "white background" im Prompt verwenden.
186
+ """
187
+ )
188
+
189
+ demo.queue(max_size=20)
190
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ diffusers>=0.31.0
2
+ transformers>=4.46.0
3
+ accelerate>=0.34.0
4
+ safetensors
5
+ Pillow
6
+ gradio>=4.44.0
7
+ spaces
8
+ torch