Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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 |
-
|
72 |
-
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
|
|
|
|
|
|
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 |
-
|
192 |
def inference(
|
193 |
qr_code_content: str,
|
194 |
prompt: str,
|
195 |
negative_prompt: str,
|
196 |
-
guidance_scale: float =
|
197 |
-
|
198 |
-
|
199 |
seed: int = -1,
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
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 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
|
225 |
-
|
226 |
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
|
231 |
-
|
232 |
-
|
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 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
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"
|
403 |
with gr.Row():
|
404 |
-
password = gr.Textbox(label="Password", type="password", placeholder="Enter your password"
|
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
|
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("💾
|
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 |
-
|
533 |
minimum=0.0,
|
534 |
maximum=5.0,
|
535 |
step=0.01,
|
536 |
-
value=
|
537 |
-
label="QR Code Visibility
|
538 |
)
|
539 |
-
with gr.Accordion("
|
540 |
gr.Markdown(
|
541 |
"""
|
542 |
-
**QR Code Visibility**
|
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 |
-
- **
|
|
|
|
|
549 |
|
550 |
-
Start with
|
551 |
"""
|
552 |
)
|
553 |
|
554 |
with gr.Row():
|
555 |
-
|
556 |
-
minimum=0.
|
557 |
-
maximum=
|
558 |
-
step=0.
|
559 |
-
value=
|
560 |
-
label="
|
561 |
)
|
562 |
-
with gr.Accordion("
|
563 |
gr.Markdown(
|
564 |
"""
|
565 |
-
**
|
566 |
-
|
567 |
-
- **Low
|
568 |
-
|
569 |
-
- **
|
570 |
-
|
571 |
-
|
572 |
"""
|
573 |
)
|
574 |
|
575 |
with gr.Row():
|
576 |
-
|
577 |
-
minimum=
|
578 |
-
maximum=100
|
579 |
-
step=
|
580 |
-
value=
|
581 |
-
label="
|
582 |
)
|
583 |
-
with gr.Accordion("
|
584 |
gr.Markdown(
|
585 |
"""
|
586 |
-
**
|
587 |
-
|
588 |
-
- **Low
|
589 |
-
|
590 |
-
- **
|
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 |
-
|
595 |
"""
|
596 |
)
|
597 |
|
598 |
with gr.Row():
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
|
|
|
|
603 |
)
|
604 |
-
with gr.Accordion("
|
605 |
gr.Markdown(
|
606 |
"""
|
607 |
-
**
|
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 |
-
|
|
|
|
|
|
|
|
|
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="
|
626 |
)
|
627 |
-
with gr.Accordion("
|
628 |
gr.Markdown(
|
629 |
"""
|
630 |
-
**
|
631 |
-
|
632 |
-
- **-1**:
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
637 |
"""
|
638 |
)
|
639 |
|
640 |
with gr.Row():
|
641 |
-
|
642 |
minimum=0.0,
|
643 |
-
maximum=
|
644 |
-
step=0.
|
645 |
-
value=0.
|
646 |
-
label="
|
647 |
-
|
648 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
765 |
-
|
766 |
seed,
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
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=
|
|
|
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)
|