Severian commited on
Commit
4a0b4d5
·
verified ·
1 Parent(s): d6fed93

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +290 -226
app.py CHANGED
@@ -15,19 +15,7 @@ from pyzxing import BarCodeReader
15
  from PIL import ImageOps, ImageEnhance, ImageFilter
16
  from huggingface_hub import hf_hub_download, snapshot_download
17
  from PIL import ImageEnhance
18
-
19
- from diffusers import (
20
- StableDiffusionPipeline,
21
- StableDiffusionControlNetImg2ImgPipeline,
22
- StableDiffusionControlNetPipeline,
23
- ControlNetModel,
24
- DDIMScheduler,
25
- DPMSolverMultistepScheduler,
26
- DEISMultistepScheduler,
27
- HeunDiscreteScheduler,
28
- EulerDiscreteScheduler,
29
- )
30
-
31
  from dotenv import load_dotenv
32
 
33
  # Load environment variables from .env file
@@ -35,6 +23,10 @@ load_dotenv()
35
 
36
  USERNAME = os.getenv("USERNAME")
37
  PASSWORD = os.getenv("PASSWORD")
 
 
 
 
38
 
39
  qrcode_generator = qrcode.QRCode(
40
  version=1,
@@ -61,36 +53,36 @@ DIFFUSION_MODELS = {
61
  loaded_controlnet = None
62
  loaded_pipe = None
63
 
64
- def load_models_on_launch():
65
- global loaded_controlnet, loaded_pipe
66
- print("Loading models on launch...")
67
-
68
- # Download the main repository
69
- main_repo_path = snapshot_download("monster-labs/control_v1p_sd15_qrcode_monster")
70
 
71
- # Construct the path to the subfolder
72
- controlnet_path = os.path.join(main_repo_path, "v2")
73
 
74
- loaded_controlnet = ControlNetModel.from_pretrained(
75
- controlnet_path,
76
- torch_dtype=torch.float16
77
- ).to("cuda")
78
-
79
- diffusion_path = snapshot_download(DIFFUSION_MODELS["GhostMix"])
80
- loaded_pipe = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(
81
- diffusion_path,
82
- controlnet=loaded_controlnet,
83
- torch_dtype=torch.float16,
84
- safety_checker=None,
85
- ).to("cuda")
86
- print("Models loaded successfully!")
 
 
 
87
 
88
  # Modify the load_models function to use global variables
89
- def load_models(controlnet_model, diffusion_model):
90
- global loaded_controlnet, loaded_pipe
91
- if loaded_controlnet is None or loaded_pipe is None:
92
- load_models_on_launch()
93
- return loaded_pipe
94
 
95
  # Add new functions for image adjustments
96
  def adjust_image(image, brightness, contrast, saturation):
@@ -120,14 +112,14 @@ def resize_for_condition_image(input_image: Image.Image, resolution: int):
120
  return img
121
 
122
 
123
- SAMPLER_MAP = {
124
- "DPM++ Karras SDE": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True, algorithm_type="sde-dpmsolver++"),
125
- "DPM++ Karras": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True),
126
- "Heun": lambda config: HeunDiscreteScheduler.from_config(config),
127
- "Euler": lambda config: EulerDiscreteScheduler.from_config(config),
128
- "DDIM": lambda config: DDIMScheduler.from_config(config),
129
- "DEIS": lambda config: DEISMultistepScheduler.from_config(config),
130
- }
131
 
132
  def scan_qr_code(image):
133
  # Convert gradio image to PIL Image if necessary
@@ -188,111 +180,98 @@ def invert_displayed_image(image):
188
  return inverted
189
 
190
 
191
- @spaces.GPU()
192
  def inference(
193
  qr_code_content: str,
194
  prompt: str,
195
  negative_prompt: str,
196
- guidance_scale: float = 15.0, # Increased from 10.0 to 15.0
197
- controlnet_conditioning_scale: float = 1.5, # Adjusted from 2.0 to 1.5
198
- strength: float = 0.6, # Reduced from 0.8 to 0.6
199
  seed: int = -1,
200
- init_image: Image.Image | None = None,
201
- qrcode_image: Image.Image | None = None,
202
- use_qr_code_as_init_image = True,
203
- sampler = "DPM++ Karras SDE",
204
- bg_color: str = "white",
205
- qr_color: str = "black",
206
- invert_final_image: bool = False,
207
- invert_init_image: bool = False,
208
- controlnet_model: str = "QR Code Monster",
209
- diffusion_model: str = "Stable v1.5",
210
- reference_image_strength: float = 0.6,
211
  ):
212
  try:
213
  progress = gr.Progress()
214
- # Load models based on user selection
215
- progress(0, desc="Downloading models...")
216
- pipe = load_models(controlnet_model, diffusion_model)
217
- progress(0.5, desc="Models downloaded, preparing for inference...")
218
-
219
- if prompt is None or prompt == "":
220
- raise gr.Error("Prompt is required")
221
-
222
- if qrcode_image is None and qr_code_content == "":
223
- raise gr.Error("QR Code Image or QR Code Content is required")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
- pipe.scheduler = SAMPLER_MAP[sampler](pipe.scheduler.config)
226
 
227
- if seed == -1:
228
- seed = torch.seed() # Generate a truly random seed
229
- generator = torch.manual_seed(seed)
230
 
231
- if qr_code_content != "" or qrcode_image.size == (1, 1):
232
- print("Generating QR Code from content")
233
- qr = qrcode.QRCode(
234
- version=1,
235
- error_correction=qrcode.constants.ERROR_CORRECT_H,
236
- box_size=10,
237
- border=4,
238
- )
239
- qr.add_data(qr_code_content)
240
- qr.make(fit=True)
241
 
242
- qrcode_image = qr.make_image(fill_color=qr_color, back_color=bg_color)
243
- qrcode_image = resize_for_condition_image(qrcode_image, 1024)
244
- else:
245
- print("Using QR Code Image")
246
- qrcode_image = resize_for_condition_image(qrcode_image, 1024)
247
 
248
- # Determine which image to use as init_image and control_image
249
- if use_qr_code_as_init_image:
250
- init_image = qrcode_image
251
- control_image = qrcode_image
252
- else:
253
- control_image = qrcode_image
254
- if init_image is None:
255
- # If no init_image provided, set strength to 1.0 to generate a new image
256
- strength = 1.0
257
-
258
- # Adjust strength if using an init_image
259
- if init_image is not None and not use_qr_code_as_init_image:
260
- # Map the 0-5 range to 0-1 range for the strength parameter
261
- mapped_strength = min(reference_image_strength / 5.0, 1.0)
262
- strength = 1.0 - mapped_strength # Invert the strength for img2img
263
- elif use_qr_code_as_init_image:
264
- strength = min(strength, 0.6) # Cap strength at 0.6 when using QR code as init_image
265
-
266
- # Invert init_image if requested
267
- if invert_init_image and init_image is not None:
268
- init_image = invert_image(init_image)
269
-
270
- final_image = None
271
- out = pipe(
272
- prompt=prompt, # Use the full prompt
273
- negative_prompt=negative_prompt, # Use the full negative prompt
274
- image=init_image,
275
- control_image=control_image,
276
- width=1024,
277
- height=1024,
278
- guidance_scale=float(guidance_scale),
279
- controlnet_conditioning_scale=float(controlnet_conditioning_scale),
280
- generator=generator,
281
- strength=float(strength),
282
- num_inference_steps=50,
283
- )
284
- final_image = out.images[0] if final_image is None else final_image
285
 
286
- if invert_final_image:
287
- final_image = invert_image(final_image)
288
-
289
- return final_image, seed
290
- except gr.Error as e:
291
- print(f"Gradio error in inference: {str(e)}")
292
- return Image.new('RGB', (1024, 1024), color='white'), -1
293
- except Exception as e:
294
- print(f"Unexpected error in inference: {str(e)}")
295
- return Image.new('RGB', (1024, 1024), color='white'), -1
296
 
297
  def invert_init_image_display(image):
298
  if image is None:
@@ -361,7 +340,7 @@ def login(username, password):
361
  return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), gr.update(value="Login successful! You can now access the QR Code Art Generator tab.", visible=True)
362
  else:
363
  return gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), gr.update(value="Invalid username or password. Please try again.", visible=True)
364
-
365
  # Add login elements to the Gradio interface
366
  with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True) as blocks:
367
  generated_images = gr.State([])
@@ -399,9 +378,9 @@ with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True
399
  )
400
 
401
  with gr.Row():
402
- username = gr.Textbox(label="Username", placeholder="Enter your username", value="ugd")
403
  with gr.Row():
404
- password = gr.Textbox(label="Password", type="password", placeholder="Enter your password", value="ugd!")
405
  with gr.Row():
406
  login_button = gr.Button("Login", size="sm")
407
  login_message = gr.Markdown(visible=False)
@@ -421,7 +400,7 @@ with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True
421
  prompt = gr.Textbox(
422
  label="Artistic Prompt",
423
  placeholder="Describe the style or theme for your QR code art (For best results, keep the prompt to 75 characters or less as seen below)",
424
- value="A high-res, photo-realistic minimalist rendering of Mount Fuji as a sharp, semi-realistic silhouette on the horizon, traditional Japanese woodblock prints, nature photography, 4k, bold",
425
  info="Describe the style or theme for your QR code art (For best results, keep the prompt to 75 characters or less as seen in the example)",
426
  lines=8,
427
  )
@@ -494,13 +473,14 @@ with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True
494
 
495
  with gr.Column():
496
  gr.Markdown("### Your Generated QR Code Art")
 
497
  result_image = gr.Image(
498
  label="Your Artistic QR Code",
499
  show_download_button=True,
500
  show_fullscreen_button=True,
501
  container=True
502
  )
503
- gr.Markdown("💾 Right-click and save to download your QR code art.")
504
 
505
  scan_button = gr.Button("Verify QR Code Works", visible=False)
506
  scan_result = gr.Textbox(label="Validation Result of QR Code", interactive=False, visible=False)
@@ -529,90 +509,86 @@ with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True
529
  with gr.Tab("Advanced Settings"):
530
  with gr.Accordion("Advanced Art Controls", open=True):
531
  with gr.Row():
532
- controlnet_conditioning_scale = gr.Slider(
533
  minimum=0.0,
534
  maximum=5.0,
535
  step=0.01,
536
- value=2,
537
- label="QR Code Visibility in Image",
538
  )
539
- with gr.Accordion("How Much QR Code Visibility is in Final Image (Click For Explanation)", open=False):
540
  gr.Markdown(
541
  """
542
- **QR Code Visibility** determines how much the QR code itself stands out in the final design. Think of it like balancing between how "artistic" the image looks and how "functional" the QR code is.
543
-
544
- - **Low settings (0.0-1)**: If you choose a lower value, the QR code will blend more into the art, and it might be hard to scan with a phone. This setting is great if you want the image to look amazing, but you might lose some of the scannability. Try this if you care more about art and less about the QR code being easily recognized.
545
-
546
- - **Medium settings (1-3)**: This is the sweet spot where the QR code remains clearly visible while still blending in with the art. You can still scan it easily with a phone, but it looks more creative. For most users, setting it around **1.1** is a great start to balance both art and function.
547
 
548
- - **High settings (3-5.0)**: If you need to make sure that the QR code is super easy to scan, even if it means the image looks less like art and more like a regular QR code, then choose a higher value. This is ideal when functionality is the main goal, and the artistic side can take a backseat.
 
 
549
 
550
- Start with **1.3** if you're unsure, and adjust up or down depending on whether you want the QR code to be more artistic or more functional.
551
  """
552
  )
553
 
554
  with gr.Row():
555
- strength = gr.Slider(
556
- minimum=0.0,
557
- maximum=5,
558
- step=0.10,
559
- value=2,
560
- label="Artistic Freedom for the AI When Generating",
561
  )
562
- with gr.Accordion("How Much Artistic Freedom the AI has When Generating Image (Click For Explanation)", open=False):
563
  gr.Markdown(
564
  """
565
- **Artistic Freedom** controls how much the AI is allowed to change the QR code's look to match your description. It's like telling the AI how creative it can get with your QR code:
566
-
567
- - **Low settings (0.10-2)**: If you set this low, the AI will make small changes and your QR code will look more like a regular, plain QR code. This is useful if you want something that is still creative but not too wild, keeping it simple and easy to scan.
568
-
569
- - **Medium settings (2-3)**: Here, the AI will add more artistic touches but keep the QR code recognizable. You get the best of both worlds—your QR code will have some creative flair, but it will still be easy to scan. For most cases, setting it to **0.6** is a great way to keep the code functional and artistic.
570
-
571
- - **High settings (3-5)**: If you set this high, the AI will go all-out creative. The QR code will look amazing, but it might be difficult to scan because the art can start to take over the code. This setting is perfect if you're aiming for a highly creative piece of art and don't mind if it's a bit harder to scan. Start at **0.9** to explore creative but functional designs.
572
  """
573
  )
574
 
575
  with gr.Row():
576
- guidance_scale = gr.Slider(
577
- minimum=0.0,
578
- maximum=100.0,
579
- step=0.25,
580
- value=7.5,
581
- label="How Closely the AI Follows the Prompt",
582
  )
583
- with gr.Accordion("How Closely the AI Follows the Prompt (Click For Explanation)", open=False):
584
  gr.Markdown(
585
  """
586
- **Follow the Prompt** tells the AI how closely it should follow your description when creating the QR code art. Think of it like giving the AI instructions on how strict or flexible it can be with your design ideas:
587
-
588
- - **Low settings (0-5)**: If you choose a lower value, the AI has more freedom to get creative on its own and may not stick too closely to your description. This is great if you want to see how the AI interprets your ideas in unexpected ways.
589
-
590
- - **Medium settings (5-15)**: This is a good balance where the AI will mostly follow your prompt but will also add some of its own creative touches. If you want to see some surprises but still want the design to look like what you described, start at around **7.5**.
591
-
592
- - **High settings (15+)**: If you choose a higher value, the AI will stick very closely to what you wrote in the description. This is good if you have a very specific idea and don't want the AI to change much. Just keep in mind that this might limit the AI's creativity.
593
 
594
- Start at **7.5** for a balanced approach where the AI follows your ideas but still adds some artistic flair.
595
  """
596
  )
597
 
598
  with gr.Row():
599
- sampler = gr.Dropdown(
600
- choices=list(SAMPLER_MAP.keys()),
601
- value="DPM++ Karras SDE",
602
- label="Art Style Used to Create the Image",
 
 
603
  )
604
- with gr.Accordion("Details on Art Style the AI Uses to Create the Image (Click For Explanation)", open=False):
605
  gr.Markdown(
606
  """
607
- **Art Style** changes how the AI creates the image, using different methods (or "samplers"). Each method has a different effect on how detailed or artistic the final QR code looks:
608
-
609
- - **DPM++ Karras SDE**: This is a great all-around option for creating high-quality, detailed images. It's a good place to start if you want a balance of sharpness and creativity.
610
-
611
- - **Euler**: This method creates very sharp, detailed images, making the QR code look crisp and clear. Choose this if you want a precise, well-defined design.
612
-
613
- - **DDIM**: This method is better if you want the QR code to have a more artistic, abstract style. It's great for when you want the QR code to look like a piece of modern art.
614
 
615
- Feel free to experiment with different samplers to see what works best for the look you're going for!
 
 
 
 
616
  """
617
  )
618
 
@@ -622,32 +598,123 @@ with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True
622
  maximum=9999999999,
623
  step=1,
624
  value=-1,
625
- label="Creative Seed for the Image Generation",
626
  )
627
- with gr.Accordion("How Creative Seed Works for Generating New and Unique Images (Click For Explanation)", open=False):
628
  gr.Markdown(
629
  """
630
- **Creative Seed** controls whether the AI creates a completely new design each time or sticks to a specific design. Think of it like a recipe: with the same seed number, you get the same "recipe" for your QR code every time.
631
-
632
- - **-1**: This setting makes the AI create something completely new every time you run it. Use this if you want to explore different design ideas with each attempt.
633
-
634
- - **Any other number**: If you set a specific number, the AI will always create the same image based on that number. This is useful if you find a design you like and want to recreate it exactly.
635
-
636
- Try **-1** if you want to explore and generate different designs. If you find something you really love, write down the seed number and use it again to recreate the same design.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
  """
638
  )
639
 
640
  with gr.Row():
641
- reference_image_strength = gr.Slider(
642
  minimum=0.0,
643
- maximum=5.0,
644
- step=0.05,
645
- value=0.6,
646
- label="Reference Image Influence",
647
- info="Controls how much the reference image influences the final result (0 = ignore, 5 = copy exactly)",
648
- visible=False # We'll make this visible when a reference image is uploaded
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
649
  )
 
 
 
 
 
 
 
 
 
 
 
650
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
  with gr.Tab("Image Editing"):
652
  with gr.Column():
653
  image_selector = gr.Dropdown(label="Select Image to Edit", choices=[], interactive=True, visible=False)
@@ -761,19 +828,16 @@ with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True
761
  prompt,
762
  negative_prompt,
763
  guidance_scale,
764
- controlnet_conditioning_scale,
765
- strength,
766
  seed,
767
- init_image,
768
- qr_code_image,
769
- use_qr_code_as_init_image,
770
- sampler,
771
- bg_color,
772
- qr_color,
773
- invert_final_image,
774
- controlnet_model_dropdown,
775
- diffusion_model_dropdown,
776
- reference_image_strength,
777
  ],
778
  outputs=[result_image, used_seed],
779
  concurrency_limit=20
@@ -794,7 +858,7 @@ with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True
794
  )
795
 
796
  # Load models on launch
797
- load_models_on_launch()
798
 
799
  blocks.queue(max_size=20)
800
- blocks.launch(share=False, show_api=True)
 
15
  from PIL import ImageOps, ImageEnhance, ImageFilter
16
  from huggingface_hub import hf_hub_download, snapshot_download
17
  from PIL import ImageEnhance
18
+ import replicate
 
 
 
 
 
 
 
 
 
 
 
 
19
  from dotenv import load_dotenv
20
 
21
  # Load environment variables from .env file
 
23
 
24
  USERNAME = os.getenv("USERNAME")
25
  PASSWORD = os.getenv("PASSWORD")
26
+ REPLICATE_API_TOKEN = os.getenv("REPLICATE_API_TOKEN")
27
+
28
+ # Set the Replicate API token
29
+ os.environ["REPLICATE_API_TOKEN"] = REPLICATE_API_TOKEN
30
 
31
  qrcode_generator = qrcode.QRCode(
32
  version=1,
 
53
  loaded_controlnet = None
54
  loaded_pipe = None
55
 
56
+ # def load_models_on_launch():
57
+ # global loaded_controlnet, loaded_pipe
58
+ # print("Loading models on launch...")
 
 
 
59
 
60
+ # Download the main repository
61
+ # main_repo_path = snapshot_download("monster-labs/control_v1p_sd15_qrcode_monster")
62
 
63
+ # Construct the path to the subfolder
64
+ # controlnet_path = os.path.join(main_repo_path, "v2")
65
+
66
+ # loaded_controlnet = ControlNetModel.from_pretrained(
67
+ # controlnet_path,
68
+ # torch_dtype=torch.float16
69
+ # ).to("mps")
70
+
71
+ # diffusion_path = snapshot_download(DIFFUSION_MODELS["GhostMix"])
72
+ # loaded_pipe = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(
73
+ # diffusion_path,
74
+ # controlnet=loaded_controlnet,
75
+ # torch_dtype=torch.float16,
76
+ # safety_checker=None,
77
+ # ).to("mps")
78
+ # print("Models loaded successfully!")
79
 
80
  # Modify the load_models function to use global variables
81
+ #def load_models(controlnet_model, diffusion_model):
82
+ # global loaded_controlnet, loaded_pipe
83
+ # if loaded_controlnet is None or loaded_pipe is None:
84
+ # load_models_on_launch()
85
+ # return loaded_pipe
86
 
87
  # Add new functions for image adjustments
88
  def adjust_image(image, brightness, contrast, saturation):
 
112
  return img
113
 
114
 
115
+ # SAMPLER_MAP = {
116
+ # "DPM++ Karras SDE": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True, algorithm_type="sde-dpmsolver++"),
117
+ # "DPM++ Karras": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True),
118
+ # "Heun": lambda config: HeunDiscreteScheduler.from_config(config),
119
+ # "Euler": lambda config: EulerDiscreteScheduler.from_config(config),
120
+ # "DDIM": lambda config: DDIMScheduler.from_config(config),
121
+ # "DEIS": lambda config: DEISMultistepScheduler.from_config(config),
122
+ #}
123
 
124
  def scan_qr_code(image):
125
  # Convert gradio image to PIL Image if necessary
 
180
  return inverted
181
 
182
 
183
+ #@spaces.GPU()
184
  def inference(
185
  qr_code_content: str,
186
  prompt: str,
187
  negative_prompt: str,
188
+ guidance_scale: float = 9.0,
189
+ qr_conditioning_scale: float = 1.47,
190
+ num_inference_steps: int = 20,
191
  seed: int = -1,
192
+ image_resolution: int = 512,
193
+ scheduler: str = "K_EULER",
194
+ eta: float = 0.0,
195
+ num_outputs: int = 1,
196
+ low_threshold: int = 100,
197
+ high_threshold: int = 200,
198
+ guess_mode: bool = False,
199
+ disable_safety_check: bool = False,
 
 
 
200
  ):
201
  try:
202
  progress = gr.Progress()
203
+ progress(0, desc="Generating QR code...")
204
+
205
+ # Generate QR code image
206
+ qr = qrcode.QRCode(
207
+ version=1,
208
+ error_correction=qrcode.constants.ERROR_CORRECT_H,
209
+ box_size=10,
210
+ border=4,
211
+ )
212
+ qr.add_data(qr_code_content)
213
+ qr.make(fit=True)
214
+ qr_image = qr.make_image(fill_color="black", back_color="white")
215
+
216
+ # Save QR code image to a temporary file
217
+ temp_qr_path = "temp_qr.png"
218
+ qr_image.save(temp_qr_path)
219
+
220
+ progress(0.3, desc="Running inference...")
221
+
222
+ # Ensure num_outputs is within the allowed range
223
+ num_outputs = max(1, min(num_outputs, 10))
224
+
225
+ # Ensure seed is an integer and not null
226
+ seed = int(seed) if seed != -1 else None
227
+
228
+ # Ensure high_threshold is at least 1
229
+ high_threshold = max(1, int(high_threshold))
230
+
231
+ # Prepare the input dictionary
232
+ input_dict = {
233
+ "prompt": prompt,
234
+ "qr_image": open(temp_qr_path, "rb"),
235
+ "negative_prompt": negative_prompt,
236
+ "guidance_scale": float(guidance_scale),
237
+ "qr_conditioning_scale": float(qr_conditioning_scale),
238
+ "num_inference_steps": int(num_inference_steps),
239
+ "image_resolution": int(image_resolution),
240
+ "scheduler": scheduler,
241
+ "eta": float(eta),
242
+ "num_outputs": num_outputs,
243
+ "low_threshold": int(low_threshold),
244
+ "high_threshold": high_threshold,
245
+ "guess_mode": guess_mode,
246
+ "disable_safety_check": disable_safety_check,
247
+ }
248
+
249
+ # Only add seed to input_dict if it's not None
250
+ if seed is not None:
251
+ input_dict["seed"] = seed
252
+
253
+ # Run inference using Replicate API
254
+ output = replicate.run(
255
+ "anotherjesse/multi-control:76d8414a702e66c84fe2e6e9c8cbdc12e53f950f255aae9ffa5caa7873b12de0",
256
+ input=input_dict
257
+ )
258
 
259
+ progress(0.9, desc="Processing results...")
260
 
261
+ # Download the generated image
262
+ response = requests.get(output[0])
263
+ img = Image.open(io.BytesIO(response.content))
264
 
265
+ # Clean up temporary file
266
+ os.remove(temp_qr_path)
 
 
 
 
 
 
 
 
267
 
268
+ progress(1.0, desc="Done!")
269
+ return img, seed if seed is not None else -1
270
+ except Exception as e:
271
+ print(f"Error in inference: {str(e)}")
272
+ return Image.new('RGB', (512, 512), color='white'), -1
273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
 
 
 
 
 
 
 
 
 
 
275
 
276
  def invert_init_image_display(image):
277
  if image is None:
 
340
  return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), gr.update(value="Login successful! You can now access the QR Code Art Generator tab.", visible=True)
341
  else:
342
  return gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), gr.update(value="Invalid username or password. Please try again.", visible=True)
343
+
344
  # Add login elements to the Gradio interface
345
  with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True) as blocks:
346
  generated_images = gr.State([])
 
378
  )
379
 
380
  with gr.Row():
381
+ username = gr.Textbox(label="Username", placeholder="Enter your username")
382
  with gr.Row():
383
+ password = gr.Textbox(label="Password", type="password", placeholder="Enter your password")
384
  with gr.Row():
385
  login_button = gr.Button("Login", size="sm")
386
  login_message = gr.Markdown(visible=False)
 
400
  prompt = gr.Textbox(
401
  label="Artistic Prompt",
402
  placeholder="Describe the style or theme for your QR code art (For best results, keep the prompt to 75 characters or less as seen below)",
403
+ value="A high-res, photo-realistic minimalist rendering of Mount Fuji as a sharp, semi-realistic silhouette on the horizon. The mountain conveys strength and motion with clean, crisp lines and natural flow. Features detailed snow textures, subtle ridge highlights, and a powerful yet serene atmosphere. Emphasizes strength with clarity and precision in texture and light.",
404
  info="Describe the style or theme for your QR code art (For best results, keep the prompt to 75 characters or less as seen in the example)",
405
  lines=8,
406
  )
 
473
 
474
  with gr.Column():
475
  gr.Markdown("### Your Generated QR Code Art")
476
+ gr.Markdown("Click the download button below the image to save your creation.")
477
  result_image = gr.Image(
478
  label="Your Artistic QR Code",
479
  show_download_button=True,
480
  show_fullscreen_button=True,
481
  container=True
482
  )
483
+ gr.Markdown("💾 Use the download button above the image to save your QR code art.")
484
 
485
  scan_button = gr.Button("Verify QR Code Works", visible=False)
486
  scan_result = gr.Textbox(label="Validation Result of QR Code", interactive=False, visible=False)
 
509
  with gr.Tab("Advanced Settings"):
510
  with gr.Accordion("Advanced Art Controls", open=True):
511
  with gr.Row():
512
+ qr_conditioning_scale = gr.Slider(
513
  minimum=0.0,
514
  maximum=5.0,
515
  step=0.01,
516
+ value=1.47,
517
+ label="QR Code Visibility",
518
  )
519
+ with gr.Accordion("QR Code Visibility Explanation", open=False):
520
  gr.Markdown(
521
  """
522
+ **QR Code Visibility** controls how prominent the QR code is in the final image:
 
 
 
 
523
 
524
+ - **Low (0.0-1.0)**: QR code blends more with the art, potentially harder to scan.
525
+ - **Medium (1.0-3.0)**: Balanced visibility, usually scannable while maintaining artistic quality.
526
+ - **High (3.0-5.0)**: QR code stands out more, easier to scan but less artistic.
527
 
528
+ Start with 1.47 for a good balance between art and functionality.
529
  """
530
  )
531
 
532
  with gr.Row():
533
+ guidance_scale = gr.Slider(
534
+ minimum=0.1,
535
+ maximum=30.0,
536
+ step=0.1,
537
+ value=9.0,
538
+ label="Prompt Adherence",
539
  )
540
+ with gr.Accordion("Prompt Adherence Explanation", open=False):
541
  gr.Markdown(
542
  """
543
+ **Prompt Adherence** determines how closely the AI follows your prompt:
544
+
545
+ - **Low (0.1-5.0)**: More creative freedom, may deviate from prompt.
546
+ - **Medium (5.0-15.0)**: Balanced between prompt and AI creativity.
547
+ - **High (15.0-30.0)**: Strictly follows the prompt, less creative freedom.
548
+
549
+ A value of 9.0 provides a good balance between creativity and prompt adherence.
550
  """
551
  )
552
 
553
  with gr.Row():
554
+ num_inference_steps = gr.Slider(
555
+ minimum=1,
556
+ maximum=100,
557
+ step=1,
558
+ value=20,
559
+ label="Generation Steps",
560
  )
561
+ with gr.Accordion("Generation Steps Explanation", open=False):
562
  gr.Markdown(
563
  """
564
+ **Generation Steps** affects the detail and quality of the generated image:
565
+
566
+ - **Low (1-10)**: Faster generation, less detailed results.
567
+ - **Medium (11-30)**: Good balance between speed and quality.
568
+ - **High (31-100)**: More detailed results, slower generation.
 
 
569
 
570
+ 20 steps is a good starting point for most generations.
571
  """
572
  )
573
 
574
  with gr.Row():
575
+ image_resolution = gr.Slider(
576
+ minimum=256,
577
+ maximum=1024,
578
+ step=64,
579
+ value=512,
580
+ label="Image Resolution",
581
  )
582
+ with gr.Accordion("Image Resolution Explanation", open=False):
583
  gr.Markdown(
584
  """
585
+ **Image Resolution** determines the size and detail of the generated image:
 
 
 
 
 
 
586
 
587
+ - **Low (256-384)**: Faster generation, less detailed.
588
+ - **Medium (512-768)**: Good balance of detail and generation time.
589
+ - **High (832-1024)**: More detailed, slower generation.
590
+
591
+ 512x512 is a good default for most use cases.
592
  """
593
  )
594
 
 
598
  maximum=9999999999,
599
  step=1,
600
  value=-1,
601
+ label="Generation Seed",
602
  )
603
+ with gr.Accordion("Generation Seed Explanation", open=False):
604
  gr.Markdown(
605
  """
606
+ **Generation Seed** controls the randomness of the generation:
607
+
608
+ - **-1**: Random seed each time, producing different results.
609
+ - **Any positive number**: Consistent results for the same inputs.
610
+
611
+ Use -1 to explore various designs, or set a specific seed to recreate a particular result.
612
+ """
613
+ )
614
+
615
+ with gr.Row():
616
+ scheduler = gr.Dropdown(
617
+ choices=["DDIM", "K_EULER", "DPMSolverMultistep", "K_EULER_ANCESTRAL", "PNDM", "KLMS"],
618
+ value="K_EULER",
619
+ label="Sampling Method",
620
+ )
621
+ with gr.Accordion("Sampling Method Explanation", open=False):
622
+ gr.Markdown(
623
+ """
624
+ **Sampling Method** affects the image generation process:
625
+
626
+ - **K_EULER**: Good balance of speed and quality.
627
+ - **DDIM**: Can produce sharper results but may be slower.
628
+ - **DPMSolverMultistep**: Often produces high-quality results.
629
+ - **K_EULER_ANCESTRAL**: Can introduce more variations.
630
+ - **PNDM**: Another quality-focused option.
631
+ - **KLMS**: Can produce smooth results.
632
+
633
+ Experiment with different methods to find what works best for your specific prompts.
634
  """
635
  )
636
 
637
  with gr.Row():
638
+ eta = gr.Slider(
639
  minimum=0.0,
640
+ maximum=1.0,
641
+ step=0.01,
642
+ value=0.0,
643
+ label="ETA (Noise Level)",
644
+ )
645
+ with gr.Accordion("ETA Explanation", open=False):
646
+ gr.Markdown(
647
+ """
648
+ **ETA (Noise Level)** controls the amount of noise in the generation process:
649
+
650
+ - **0.0**: No added noise, more deterministic results.
651
+ - **0.1-0.5**: Slight variations in output.
652
+ - **0.6-1.0**: More variations, potentially more creative results.
653
+
654
+ Start with 0.0 and increase if you want more variation in your outputs.
655
+ """
656
+ )
657
+
658
+ with gr.Row():
659
+ low_threshold = gr.Slider(
660
+ minimum=1,
661
+ maximum=255,
662
+ step=1,
663
+ value=100,
664
+ label="Edge Detection Low Threshold",
665
+ )
666
+ high_threshold = gr.Slider(
667
+ minimum=1,
668
+ maximum=255,
669
+ step=1,
670
+ value=200,
671
+ label="Edge Detection High Threshold",
672
+ )
673
+ with gr.Accordion("Edge Detection Thresholds Explanation", open=False):
674
+ gr.Markdown(
675
+ """
676
+ **Edge Detection Thresholds** affect how the QR code edges are processed:
677
+
678
+ - **Low Threshold**: Lower values detect more edges, higher values fewer.
679
+ - **High Threshold**: Determines which edges are strong. Higher values result in fewer strong edges.
680
+
681
+ Default values (100, 200) work well for most QR codes. Adjust if you need more or less edge definition.
682
+ """
683
+ )
684
+
685
+ with gr.Row():
686
+ guess_mode = gr.Checkbox(
687
+ label="Guess Mode",
688
+ value=False,
689
  )
690
+ with gr.Accordion("Guess Mode Explanation", open=False):
691
+ gr.Markdown(
692
+ """
693
+ **Guess Mode**, when enabled, allows the AI to interpret the input image more freely:
694
+
695
+ - **Unchecked**: AI follows the QR code structure more strictly.
696
+ - **Checked**: AI has more freedom to interpret the input, potentially leading to more creative results.
697
+
698
+ Use this if you want more artistic interpretations of your QR code.
699
+ """
700
+ )
701
 
702
+ with gr.Row():
703
+ disable_safety_check = gr.Checkbox(
704
+ label="Disable Safety Check",
705
+ value=False,
706
+ )
707
+ with gr.Accordion("Safety Check Explanation", open=False):
708
+ gr.Markdown(
709
+ """
710
+ **Disable Safety Check** removes content filtering from the generation process:
711
+
712
+ - **Unchecked**: Normal content filtering applied.
713
+ - **Checked**: No content filtering, may produce unexpected or inappropriate results.
714
+
715
+ Use with caution and only if necessary for your specific use case.
716
+ """
717
+ )
718
  with gr.Tab("Image Editing"):
719
  with gr.Column():
720
  image_selector = gr.Dropdown(label="Select Image to Edit", choices=[], interactive=True, visible=False)
 
828
  prompt,
829
  negative_prompt,
830
  guidance_scale,
831
+ qr_conditioning_scale,
832
+ num_inference_steps,
833
  seed,
834
+ image_resolution,
835
+ scheduler,
836
+ eta,
837
+ low_threshold,
838
+ high_threshold,
839
+ guess_mode,
840
+ disable_safety_check,
 
 
 
841
  ],
842
  outputs=[result_image, used_seed],
843
  concurrency_limit=20
 
858
  )
859
 
860
  # Load models on launch
861
+ #load_models_on_launch()
862
 
863
  blocks.queue(max_size=20)
864
+ blocks.launch(share=False, show_api=False)