seawolf2357 commited on
Commit
32c2062
Β·
verified Β·
1 Parent(s): ad7b826

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +176 -93
app.py CHANGED
@@ -6,8 +6,9 @@ from diffusers import FluxKontextPipeline
6
  from diffusers.utils import load_image
7
  from PIL import Image
8
  import os
 
9
 
10
- # Style dictionary
11
  style_type_lora_dict = {
12
  "3D_Chibi": "3D_Chibi_lora_weights.safetensors",
13
  "American_Cartoon": "American_Cartoon_lora_weights.safetensors",
@@ -36,23 +37,33 @@ style_type_lora_dict = {
36
  # Create LoRAs directory if it doesn't exist
37
  os.makedirs("./LoRAs", exist_ok=True)
38
 
39
- # Download all LoRA weights at startup
40
- print("Downloading LoRA weights...")
41
- for style_name, lora_file in style_type_lora_dict.items():
42
- if not os.path.exists(f"./LoRAs/{lora_file}"):
43
- hf_hub_download(
44
- repo_id="Owen777/Kontext-Style-Loras",
45
- filename=lora_file,
46
- local_dir="./LoRAs"
47
- )
48
- print("All LoRA weights downloaded!")
 
 
 
 
 
 
 
 
 
49
 
50
- # Initialize pipeline globally (will be loaded to GPU when needed)
51
  pipeline = None
52
 
53
  def load_pipeline():
54
  global pipeline
55
  if pipeline is None:
 
56
  pipeline = FluxKontextPipeline.from_pretrained(
57
  "black-forest-labs/FLUX.1-Kontext-dev",
58
  torch_dtype=torch.bfloat16
@@ -60,74 +71,131 @@ def load_pipeline():
60
  return pipeline
61
 
62
  @spaces.GPU(duration=120) # Request GPU for 120 seconds
63
- def style_transfer(input_image, style_name, num_inference_steps, guidance_scale, seed):
64
  """
65
  Apply style transfer to the input image using selected style
66
  """
67
- # Load pipeline and move to GPU
68
- pipe = load_pipeline()
69
- pipe = pipe.to('cuda')
70
-
71
- # Set seed for reproducibility
72
- if seed is not None and seed > 0:
73
- generator = torch.Generator(device="cuda").manual_seed(seed)
74
- else:
75
- generator = None
76
-
77
- # Resize input image to 1024x1024
78
- if isinstance(input_image, str):
79
- image = load_image(input_image)
80
- else:
81
- image = input_image
82
-
83
- image = image.resize((1024, 1024), Image.Resampling.LANCZOS)
84
-
85
- # Load the selected LoRA
86
- lora_path = f"./LoRAs/{style_type_lora_dict[style_name]}"
87
- pipe.load_lora_weights(lora_path, adapter_name="style_lora")
88
- pipe.set_adapters(["style_lora"], adapter_weights=[1.0])
89
-
90
- # Generate the styled image
91
- prompt = f"Turn this image into the {style_name.replace('_', ' ')} style."
92
-
93
- result = pipe(
94
- image=image,
95
- prompt=prompt,
96
- height=1024,
97
- width=1024,
98
- num_inference_steps=num_inference_steps,
99
- guidance_scale=guidance_scale,
100
- generator=generator
101
- )
102
 
103
- # Clear GPU memory
104
- torch.cuda.empty_cache()
105
-
106
- return result.images[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
  # Create Gradio interface
109
- with gr.Blocks(title="Flux Kontext Style Transfer") as demo:
110
  gr.Markdown("""
111
- # 🎨 Flux Kontext Style Transfer
112
 
113
- Transform your images into various artistic styles using FLUX.1-Kontext and style-specific LoRAs.
114
 
115
- Upload an image and select a style to apply the transformation!
116
  """)
117
 
118
  with gr.Row():
119
- with gr.Column():
120
  input_image = gr.Image(
121
- label="Input Image",
122
  type="pil",
123
  height=400
124
  )
125
 
126
  style_dropdown = gr.Dropdown(
127
  choices=list(style_type_lora_dict.keys()),
128
- value="3D_Chibi",
129
  label="Select Style",
130
- info="Choose the artistic style to apply"
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  )
132
 
133
  with gr.Accordion("Advanced Settings", open=False):
@@ -136,66 +204,81 @@ with gr.Blocks(title="Flux Kontext Style Transfer") as demo:
136
  maximum=50,
137
  value=24,
138
  step=1,
139
- label="Number of Inference Steps",
140
  info="More steps = better quality but slower"
141
  )
142
 
143
- guidance = gr.Slider(
144
- minimum=1.0,
145
- maximum=10.0,
146
- value=3.5,
147
- step=0.5,
148
- label="Guidance Scale",
149
- info="Higher values = stronger style adherence"
150
- )
151
-
152
  seed = gr.Number(
153
  label="Seed",
154
- value=0,
155
- precision=0,
156
- info="Set to 0 for random, or use specific seed for reproducibility"
157
  )
158
 
159
- generate_btn = gr.Button("🎨 Apply Style Transfer", variant="primary")
160
 
161
- with gr.Column():
162
  output_image = gr.Image(
163
- label="Styled Output",
164
  type="pil",
165
  height=400
166
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
  # Examples
169
  gr.Examples(
170
  examples=[
171
- ["https://huggingface.co/datasets/black-forest-labs/kontext-bench/resolve/main/test/images/0003.jpg", "3D_Chibi"],
172
- ["https://huggingface.co/datasets/black-forest-labs/kontext-bench/resolve/main/test/images/0003.jpg", "Ghibli"],
173
- ["https://huggingface.co/datasets/black-forest-labs/kontext-bench/resolve/main/test/images/0003.jpg", "Van_Gogh"],
 
174
  ],
175
- inputs=[input_image, style_dropdown],
176
  outputs=output_image,
177
- fn=lambda img, style: style_transfer(img, style, 24, 3.5, 0),
178
- cache_examples=True
179
  )
180
 
181
  # Connect the generate button
182
  generate_btn.click(
183
  fn=style_transfer,
184
- inputs=[input_image, style_dropdown, num_steps, guidance, seed],
185
  outputs=output_image
186
  )
187
 
188
  gr.Markdown("""
189
- ## πŸ“ Notes:
190
- - Processing takes about 30-60 seconds depending on the number of steps
191
- - All images are resized to 1024x1024 for optimal results
192
- - Different styles work better with different types of images
193
- - Try adjusting the advanced settings for better results
194
-
195
- ## 🎨 Available Styles:
196
- 3D Chibi, American Cartoon, Chinese Ink, Clay Toy, Fabric, Ghibli, Irasutoya,
197
- Jojo, Oil Painting, Pixel, Snoopy, Poly, LEGO, Origami, Pop Art, Van Gogh,
198
- Paper Cutting, Line, Vector, Picasso, Macaron, Rick & Morty
 
 
 
 
 
 
199
  """)
200
 
201
  if __name__ == "__main__":
 
6
  from diffusers.utils import load_image
7
  from PIL import Image
8
  import os
9
+ import numpy as np
10
 
11
+ # Style dictionary - μ™„μ „ν•œ μŠ€νƒ€μΌ λͺ©λ‘
12
  style_type_lora_dict = {
13
  "3D_Chibi": "3D_Chibi_lora_weights.safetensors",
14
  "American_Cartoon": "American_Cartoon_lora_weights.safetensors",
 
37
  # Create LoRAs directory if it doesn't exist
38
  os.makedirs("./LoRAs", exist_ok=True)
39
 
40
+ # Download LoRA weights on demand
41
+ def download_lora(style_name):
42
+ lora_file = style_type_lora_dict[style_name]
43
+ lora_path = f"./LoRAs/{lora_file}"
44
+
45
+ if not os.path.exists(lora_path):
46
+ gr.Info(f"Downloading {style_name} LoRA...")
47
+ try:
48
+ hf_hub_download(
49
+ repo_id="Owen777/Kontext-Style-Loras",
50
+ filename=lora_file,
51
+ local_dir="./LoRAs"
52
+ )
53
+ print(f"Downloaded {lora_file}")
54
+ except Exception as e:
55
+ print(f"Error downloading {lora_file}: {e}")
56
+ raise e
57
+
58
+ return lora_path
59
 
60
+ # Initialize pipeline globally
61
  pipeline = None
62
 
63
  def load_pipeline():
64
  global pipeline
65
  if pipeline is None:
66
+ gr.Info("Loading FLUX.1-Kontext model...")
67
  pipeline = FluxKontextPipeline.from_pretrained(
68
  "black-forest-labs/FLUX.1-Kontext-dev",
69
  torch_dtype=torch.bfloat16
 
71
  return pipeline
72
 
73
  @spaces.GPU(duration=120) # Request GPU for 120 seconds
74
+ def style_transfer(input_image, style_name, prompt_suffix, num_inference_steps, seed):
75
  """
76
  Apply style transfer to the input image using selected style
77
  """
78
+ if input_image is None:
79
+ gr.Warning("Please upload an image first!")
80
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
+ try:
83
+ # Load pipeline and move to GPU
84
+ pipe = load_pipeline()
85
+ pipe = pipe.to('cuda')
86
+
87
+ # Set seed for reproducibility
88
+ if seed > 0:
89
+ generator = torch.Generator(device="cuda").manual_seed(seed)
90
+ else:
91
+ generator = None
92
+
93
+ # Process input image
94
+ if isinstance(input_image, str):
95
+ image = load_image(input_image)
96
+ else:
97
+ image = input_image
98
+
99
+ # Resize to 1024x1024 (required for Kontext)
100
+ image = image.resize((1024, 1024), Image.Resampling.LANCZOS)
101
+
102
+ # Download and load the selected LoRA
103
+ gr.Info(f"Loading {style_name} style...")
104
+ lora_path = download_lora(style_name)
105
+
106
+ pipe.load_lora_weights(lora_path, adapter_name="style")
107
+ pipe.set_adapters(["style"], adapter_weights=[1])
108
+
109
+ # Create prompt
110
+ style_name_readable = style_name.replace('_', ' ')
111
+ prompt = f"Turn this image into the {style_name_readable} style."
112
+ if prompt_suffix:
113
+ prompt += f" {prompt_suffix}"
114
+
115
+ gr.Info("Generating styled image...")
116
+
117
+ # Generate the styled image
118
+ result = pipe(
119
+ image=image,
120
+ prompt=prompt,
121
+ height=1024,
122
+ width=1024,
123
+ num_inference_steps=num_inference_steps,
124
+ generator=generator
125
+ )
126
+
127
+ # Clear GPU memory
128
+ torch.cuda.empty_cache()
129
+
130
+ return result.images[0]
131
+
132
+ except Exception as e:
133
+ gr.Error(f"Error during style transfer: {str(e)}")
134
+ torch.cuda.empty_cache()
135
+ return None
136
+
137
+ # Style descriptions
138
+ style_descriptions = {
139
+ "3D_Chibi": "Cute, miniature 3D character style with big heads",
140
+ "American_Cartoon": "Classic American animation style",
141
+ "Chinese_Ink": "Traditional Chinese ink painting aesthetic",
142
+ "Clay_Toy": "Playful clay/plasticine toy appearance",
143
+ "Fabric": "Soft, textile-like rendering",
144
+ "Ghibli": "Studio Ghibli's distinctive anime style",
145
+ "Irasutoya": "Simple, flat Japanese illustration style",
146
+ "Jojo": "JoJo's Bizarre Adventure manga style",
147
+ "Oil_Painting": "Classic oil painting texture and strokes",
148
+ "Pixel": "Retro pixel art style",
149
+ "Snoopy": "Peanuts comic strip style",
150
+ "Poly": "Low-poly 3D geometric style",
151
+ "LEGO": "LEGO brick construction style",
152
+ "Origami": "Paper folding art style",
153
+ "Pop_Art": "Bold, colorful pop art style",
154
+ "Van_Gogh": "Van Gogh's expressive brushstroke style",
155
+ "Paper_Cutting": "Paper cut-out art style",
156
+ "Line": "Clean line art/sketch style",
157
+ "Vector": "Clean vector graphics style",
158
+ "Picasso": "Cubist art style inspired by Picasso",
159
+ "Macaron": "Soft, pastel macaron-like style",
160
+ "Rick_Morty": "Rick and Morty cartoon style"
161
+ }
162
 
163
  # Create Gradio interface
164
+ with gr.Blocks(title="FLUX.1 Kontext Style Transfer", theme=gr.themes.Soft()) as demo:
165
  gr.Markdown("""
166
+ # 🎨 FLUX.1 Kontext Style Transfer
167
 
168
+ Transform your images into various artistic styles using FLUX.1-Kontext-dev and high-quality style LoRAs.
169
 
170
+ This demo uses the official Owen777/Kontext-Style-Loras collection with 22 different artistic styles!
171
  """)
172
 
173
  with gr.Row():
174
+ with gr.Column(scale=1):
175
  input_image = gr.Image(
176
+ label="Upload Image",
177
  type="pil",
178
  height=400
179
  )
180
 
181
  style_dropdown = gr.Dropdown(
182
  choices=list(style_type_lora_dict.keys()),
183
+ value="Ghibli",
184
  label="Select Style",
185
+ info="Choose from 22 different artistic styles"
186
+ )
187
+
188
+ style_info = gr.Textbox(
189
+ label="Style Description",
190
+ value=style_descriptions["Ghibli"],
191
+ interactive=False,
192
+ lines=2
193
+ )
194
+
195
+ prompt_suffix = gr.Textbox(
196
+ label="Additional Prompt (Optional)",
197
+ placeholder="Add extra details to the transformation...",
198
+ lines=2
199
  )
200
 
201
  with gr.Accordion("Advanced Settings", open=False):
 
204
  maximum=50,
205
  value=24,
206
  step=1,
207
+ label="Inference Steps",
208
  info="More steps = better quality but slower"
209
  )
210
 
 
 
 
 
 
 
 
 
 
211
  seed = gr.Number(
212
  label="Seed",
213
+ value=42,
214
+ info="Set to 0 for random results"
 
215
  )
216
 
217
+ generate_btn = gr.Button("🎨 Transform Image", variant="primary", size="lg")
218
 
219
+ with gr.Column(scale=1):
220
  output_image = gr.Image(
221
+ label="Styled Result",
222
  type="pil",
223
  height=400
224
  )
225
+
226
+ gr.Markdown("""
227
+ ### πŸ’‘ Tips:
228
+ - All images are resized to 1024x1024
229
+ - First run may take longer to download the model
230
+ - Each style LoRA is ~359MB and downloaded on first use
231
+ - Try different styles to find the best match!
232
+ """)
233
+
234
+ # Update style description when style changes
235
+ def update_description(style):
236
+ return style_descriptions.get(style, "")
237
+
238
+ style_dropdown.change(
239
+ fn=update_description,
240
+ inputs=[style_dropdown],
241
+ outputs=[style_info]
242
+ )
243
 
244
  # Examples
245
  gr.Examples(
246
  examples=[
247
+ ["https://huggingface.co/datasets/black-forest-labs/kontext-bench/resolve/main/test/images/0003.jpg", "Ghibli", ""],
248
+ ["https://huggingface.co/datasets/black-forest-labs/kontext-bench/resolve/main/test/images/0003.jpg", "3D_Chibi", "make it extra cute"],
249
+ ["https://huggingface.co/datasets/black-forest-labs/kontext-bench/resolve/main/test/images/0003.jpg", "Van_Gogh", "with swirling sky"],
250
+ ["https://huggingface.co/datasets/black-forest-labs/kontext-bench/resolve/main/test/images/0003.jpg", "Pixel", "8-bit retro game style"],
251
  ],
252
+ inputs=[input_image, style_dropdown, prompt_suffix],
253
  outputs=output_image,
254
+ fn=lambda img, style, prompt: style_transfer(img, style, prompt, 24, 42),
255
+ cache_examples=False
256
  )
257
 
258
  # Connect the generate button
259
  generate_btn.click(
260
  fn=style_transfer,
261
+ inputs=[input_image, style_dropdown, prompt_suffix, num_steps, seed],
262
  outputs=output_image
263
  )
264
 
265
  gr.Markdown("""
266
+ ---
267
+ ### πŸ“š Available Styles:
268
+
269
+ **Anime/Cartoon**: Ghibli, American Cartoon, Jojo, Snoopy, Rick & Morty, Irasutoya
270
+
271
+ **3D/Geometric**: 3D Chibi, Poly, LEGO, Clay Toy
272
+
273
+ **Traditional Art**: Chinese Ink, Oil Painting, Van Gogh, Picasso, Pop Art
274
+
275
+ **Craft/Material**: Fabric, Origami, Paper Cutting, Macaron
276
+
277
+ **Digital/Modern**: Pixel, Line, Vector
278
+
279
+ ---
280
+
281
+ Created with ❀️ using [Owen777/Kontext-Style-Loras](https://huggingface.co/Owen777/Kontext-Style-Loras)
282
  """)
283
 
284
  if __name__ == "__main__":