Spaces:
Running
on
Zero
Running
on
Zero
updating params
Browse files
app.py
CHANGED
|
@@ -22,6 +22,7 @@ hf_hub_download(repo_id="comfyanonymous/ControlNet-v1-1_fp16_safetensors", filen
|
|
| 22 |
hf_hub_download(repo_id="Lykon/dreamshaper-7", filename="vae/diffusion_pytorch_model.fp16.safetensors", local_dir="models")
|
| 23 |
hf_hub_download(repo_id="stabilityai/sd-vae-ft-mse-original", filename="vae-ft-mse-840000-ema-pruned.safetensors", local_dir="models/vae")
|
| 24 |
hf_hub_download(repo_id="lllyasviel/Annotators", filename="RealESRGAN_x4plus.pth", local_dir="models/upscale_models")
|
|
|
|
| 25 |
|
| 26 |
def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
|
| 27 |
"""Returns the value at the given index of a sequence or mapping.
|
|
@@ -176,7 +177,7 @@ valid_models = [
|
|
| 176 |
model_management.load_models_gpu(valid_models)
|
| 177 |
|
| 178 |
@spaces.GPU(duration=30)
|
| 179 |
-
def generate_qr_code_unified(prompt: str, text_input: str, input_type: str = "URL", image_size: int = 512, border_size: int = 4, error_correction: str = "Medium (15%)", module_size: int = 12, module_drawer: str = "Square", use_custom_seed: bool = False, seed: int = 0, pipeline: str = "standard", freeu_b1: float = 1.
|
| 180 |
# Only manipulate the text if it's a URL input type
|
| 181 |
qr_text = text_input
|
| 182 |
if input_type == "URL":
|
|
@@ -190,17 +191,17 @@ def generate_qr_code_unified(prompt: str, text_input: str, input_type: str = "UR
|
|
| 190 |
|
| 191 |
with torch.inference_mode():
|
| 192 |
if pipeline == "standard":
|
| 193 |
-
yield from _pipeline_standard(prompt, qr_text, input_type, image_size, border_size, error_correction, module_size, module_drawer, actual_seed)
|
| 194 |
else: # artistic
|
| 195 |
-
yield from _pipeline_artistic(prompt, qr_text, input_type, image_size, border_size, error_correction, module_size, module_drawer, actual_seed, freeu_b1, freeu_b2, freeu_s1, freeu_s2, enable_sag, sag_scale, sag_blur_sigma)
|
| 196 |
|
| 197 |
-
def generate_standard_qr(prompt: str, text_input: str, input_type: str = "URL", image_size: int = 512, border_size: int = 4, error_correction: str = "Medium (15%)", module_size: int = 12, module_drawer: str = "Square", use_custom_seed: bool = False, seed: int = 0):
|
| 198 |
"""Wrapper function for standard QR generation"""
|
| 199 |
-
yield from generate_qr_code_unified(prompt, text_input, input_type, image_size, border_size, error_correction, module_size, module_drawer, use_custom_seed, seed, pipeline="standard")
|
| 200 |
|
| 201 |
-
def generate_artistic_qr(prompt: str, text_input: str, input_type: str = "URL", image_size: int = 512, border_size: int = 4, error_correction: str = "Medium (15%)", module_size: int = 12, module_drawer: str = "Square", use_custom_seed: bool = False, seed: int = 0, freeu_b1: float = 1.
|
| 202 |
"""Wrapper function for artistic QR generation with FreeU and SAG parameters"""
|
| 203 |
-
yield from generate_qr_code_unified(prompt, text_input, input_type, image_size, border_size, error_correction, module_size, module_drawer, use_custom_seed, seed, pipeline="artistic", freeu_b1=freeu_b1, freeu_b2=freeu_b2, freeu_s1=freeu_s1, freeu_s2=freeu_s2, enable_sag=enable_sag, sag_scale=sag_scale, sag_blur_sigma=sag_blur_sigma)
|
| 204 |
|
| 205 |
def add_noise_to_border_only(image_tensor, seed: int, border_size: int, image_size: int, module_size: int = 12):
|
| 206 |
"""
|
|
@@ -289,7 +290,7 @@ def add_noise_to_border_only(image_tensor, seed: int, border_size: int, image_si
|
|
| 289 |
# Convert back to tensor
|
| 290 |
return torch.from_numpy(img_np).to(image_tensor.device)
|
| 291 |
|
| 292 |
-
def _pipeline_standard(prompt: str, qr_text: str, input_type: str, image_size: int, border_size: int, error_correction: str, module_size: int, module_drawer: str, seed: int):
|
| 293 |
emptylatentimage_5 = emptylatentimage.generate(
|
| 294 |
width=image_size, height=image_size, batch_size=1
|
| 295 |
)
|
|
@@ -433,14 +434,35 @@ def _pipeline_standard(prompt: str, qr_text: str, input_type: str, image_size: i
|
|
| 433 |
vae=get_value_at_index(checkpointloadersimple_4, 2),
|
| 434 |
)
|
| 435 |
|
| 436 |
-
# 3)
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
# Generate QR code
|
| 445 |
qr_protocol = "None" if input_type == "Plain Text" else "Https"
|
| 446 |
|
|
@@ -521,7 +543,7 @@ def _pipeline_artistic(prompt: str, qr_text: str, input_type: str, image_size: i
|
|
| 521 |
|
| 522 |
# First ControlNet pass (using QR with border cubics)
|
| 523 |
controlnet_apply = controlnetapplyadvanced.apply_controlnet(
|
| 524 |
-
strength=
|
| 525 |
start_percent=0,
|
| 526 |
end_percent=1,
|
| 527 |
positive=get_value_at_index(positive_prompt, 0),
|
|
@@ -540,7 +562,7 @@ def _pipeline_artistic(prompt: str, qr_text: str, input_type: str, image_size: i
|
|
| 540 |
|
| 541 |
# Second ControlNet pass (using tile processed from QR with border cubics)
|
| 542 |
controlnet_apply = controlnetapplyadvanced.apply_controlnet(
|
| 543 |
-
strength=
|
| 544 |
start_percent=0,
|
| 545 |
end_percent=1,
|
| 546 |
positive=get_value_at_index(controlnet_apply, 0),
|
|
@@ -598,41 +620,18 @@ def _pipeline_artistic(prompt: str, qr_text: str, input_type: str, image_size: i
|
|
| 598 |
first_pass_np = (first_pass_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 599 |
first_pass_np = first_pass_np[0]
|
| 600 |
first_pass_pil = Image.fromarray(first_pass_np)
|
| 601 |
-
step_msg = "First enhancement pass complete (step 3/5)...
|
| 602 |
yield first_pass_pil, step_msg
|
| 603 |
|
| 604 |
-
#
|
| 605 |
-
upscaled = imageupscalewithmodel.upscale(
|
| 606 |
-
upscale_model=get_value_at_index(upscalemodelloader_30, 0),
|
| 607 |
-
image=get_value_at_index(decoded, 0),
|
| 608 |
-
)
|
| 609 |
-
|
| 610 |
-
# Resize to target size
|
| 611 |
-
resized = imagescale.upscale(
|
| 612 |
-
upscale_method="area",
|
| 613 |
-
width=image_size*2,
|
| 614 |
-
height=image_size*2,
|
| 615 |
-
crop="disabled",
|
| 616 |
-
image=get_value_at_index(upscaled, 0),
|
| 617 |
-
)
|
| 618 |
-
|
| 619 |
-
# Show upscaled result
|
| 620 |
-
upscaled_tensor = get_value_at_index(resized, 0)
|
| 621 |
-
upscaled_np = (upscaled_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 622 |
-
upscaled_np = upscaled_np[0]
|
| 623 |
-
upscaled_pil = Image.fromarray(upscaled_np)
|
| 624 |
-
step_msg = "Image upscaled (step 4/5)... final refinement pass" if border_size > 0 else "Image upscaled (step 3/4)... final refinement pass"
|
| 625 |
-
yield upscaled_pil, step_msg
|
| 626 |
-
|
| 627 |
-
# Final ControlNet pass (second pass - upscaled refinement)
|
| 628 |
controlnet_apply_final = controlnetapplyadvanced.apply_controlnet(
|
| 629 |
-
strength=
|
| 630 |
start_percent=0,
|
| 631 |
end_percent=1,
|
| 632 |
positive=get_value_at_index(positive_prompt, 0),
|
| 633 |
negative=get_value_at_index(negative_prompt, 0),
|
| 634 |
control_net=get_value_at_index(tile_controlnet, 0),
|
| 635 |
-
image=get_value_at_index(
|
| 636 |
vae=get_value_at_index(checkpointloadersimple_artistic, 2),
|
| 637 |
)
|
| 638 |
|
|
@@ -663,16 +662,40 @@ def _pipeline_artistic(prompt: str, qr_text: str, input_type: str, image_size: i
|
|
| 663 |
vae=get_value_at_index(checkpointloadersimple_artistic, 2),
|
| 664 |
)
|
| 665 |
|
| 666 |
-
#
|
| 667 |
-
|
| 668 |
-
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
|
| 672 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 673 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 674 |
|
| 675 |
-
|
|
|
|
| 676 |
|
| 677 |
# Start your Gradio app
|
| 678 |
with gr.Blocks() as app:
|
|
@@ -771,21 +794,6 @@ if __name__ == "__main__":
|
|
| 771 |
info="Select the style of the QR code modules (squares). See examples below. Different styles can give your QR code a unique look while maintaining scannability."
|
| 772 |
)
|
| 773 |
|
| 774 |
-
# Add seed controls
|
| 775 |
-
use_custom_seed = gr.Checkbox(
|
| 776 |
-
label="Use Custom Seed",
|
| 777 |
-
value=False,
|
| 778 |
-
info="Enable to use a specific seed for reproducible results"
|
| 779 |
-
)
|
| 780 |
-
seed = gr.Slider(
|
| 781 |
-
minimum=0,
|
| 782 |
-
maximum=2000000,
|
| 783 |
-
step=1,
|
| 784 |
-
value=0,
|
| 785 |
-
label="Seed",
|
| 786 |
-
info="Seed value for reproducibility. Same seed with same settings will produce the same result."
|
| 787 |
-
)
|
| 788 |
-
|
| 789 |
# Add style examples with labels
|
| 790 |
gr.Markdown("### Style Examples:")
|
| 791 |
|
|
@@ -813,6 +821,28 @@ if __name__ == "__main__":
|
|
| 813 |
gr.Markdown("**Horizontal Bars**", show_label=False)
|
| 814 |
gr.Image("custom_nodes/ComfyQR/img/horizontal-bars.png", width=100, show_label=False, show_download_button=False)
|
| 815 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 816 |
# The generate button
|
| 817 |
generate_btn = gr.Button("Generate Standard QR", variant="primary")
|
| 818 |
|
|
@@ -828,7 +858,7 @@ if __name__ == "__main__":
|
|
| 828 |
# When clicking the button, it will trigger the main function
|
| 829 |
generate_btn.click(
|
| 830 |
fn=generate_standard_qr,
|
| 831 |
-
inputs=[prompt_input, text_input, input_type, image_size, border_size, error_correction, module_size, module_drawer, use_custom_seed, seed],
|
| 832 |
outputs=[output_image, error_message]
|
| 833 |
)
|
| 834 |
|
|
@@ -985,9 +1015,9 @@ if __name__ == "__main__":
|
|
| 985 |
minimum=512,
|
| 986 |
maximum=1024,
|
| 987 |
step=64,
|
| 988 |
-
value=
|
| 989 |
label="Image Size",
|
| 990 |
-
info="Base size of the generated image. Final output will be 2x this size (e.g.,
|
| 991 |
)
|
| 992 |
|
| 993 |
# Add border size slider for artistic QR
|
|
@@ -995,7 +1025,7 @@ if __name__ == "__main__":
|
|
| 995 |
minimum=0,
|
| 996 |
maximum=8,
|
| 997 |
step=1,
|
| 998 |
-
value=
|
| 999 |
label="QR Code Border Size",
|
| 1000 |
info="Number of modules (squares) to use as border around the QR code. Higher values add more whitespace."
|
| 1001 |
)
|
|
@@ -1003,9 +1033,9 @@ if __name__ == "__main__":
|
|
| 1003 |
# Add error correction dropdown for artistic QR
|
| 1004 |
artistic_error_correction = gr.Dropdown(
|
| 1005 |
choices=["Low (7%)", "Medium (15%)", "Quartile (25%)", "High (30%)"],
|
| 1006 |
-
value="
|
| 1007 |
label="Error Correction Level",
|
| 1008 |
-
info="Higher error correction makes the QR code more scannable when damaged or obscured, but increases its size and complexity.
|
| 1009 |
)
|
| 1010 |
|
| 1011 |
# Add module size slider for artistic QR
|
|
@@ -1013,9 +1043,9 @@ if __name__ == "__main__":
|
|
| 1013 |
minimum=4,
|
| 1014 |
maximum=16,
|
| 1015 |
step=1,
|
| 1016 |
-
value=
|
| 1017 |
label="QR Module Size",
|
| 1018 |
-
info="Pixel width of the smallest QR code unit. Larger values improve readability but require a larger image size.
|
| 1019 |
)
|
| 1020 |
|
| 1021 |
# Add module drawer dropdown with style examples for artistic QR
|
|
@@ -1026,17 +1056,51 @@ if __name__ == "__main__":
|
|
| 1026 |
info="Select the style of the QR code modules (squares). See examples below. Different styles can give your QR code a unique look while maintaining scannability."
|
| 1027 |
)
|
| 1028 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1029 |
# Add seed controls for artistic QR
|
| 1030 |
artistic_use_custom_seed = gr.Checkbox(
|
| 1031 |
label="Use Custom Seed",
|
| 1032 |
-
value=
|
| 1033 |
info="Enable to use a specific seed for reproducible results"
|
| 1034 |
)
|
| 1035 |
artistic_seed = gr.Slider(
|
| 1036 |
minimum=0,
|
| 1037 |
maximum=2000000,
|
| 1038 |
step=1,
|
| 1039 |
-
value=
|
| 1040 |
label="Seed",
|
| 1041 |
info="Seed value for reproducibility. Same seed with same settings will produce the same result."
|
| 1042 |
)
|
|
@@ -1047,9 +1111,9 @@ if __name__ == "__main__":
|
|
| 1047 |
minimum=1.0,
|
| 1048 |
maximum=1.6,
|
| 1049 |
step=0.01,
|
| 1050 |
-
value=1.
|
| 1051 |
label="FreeU B1 (Backbone 1)",
|
| 1052 |
-
info="Backbone feature enhancement for first layer. Higher values improve detail but may reduce blending. Range: 1.0-1.6, Default: 1.
|
| 1053 |
)
|
| 1054 |
freeu_b2 = gr.Slider(
|
| 1055 |
minimum=1.0,
|
|
@@ -1063,33 +1127,33 @@ if __name__ == "__main__":
|
|
| 1063 |
minimum=0.0,
|
| 1064 |
maximum=1.5,
|
| 1065 |
step=0.01,
|
| 1066 |
-
value=
|
| 1067 |
label="FreeU S1 (Skip 1)",
|
| 1068 |
-
info="Skip connection dampening for first layer. Lower values hide QR structure more. Range: 0.0-1.5, Default:
|
| 1069 |
)
|
| 1070 |
freeu_s2 = gr.Slider(
|
| 1071 |
minimum=0.0,
|
| 1072 |
maximum=1.5,
|
| 1073 |
step=0.01,
|
| 1074 |
-
value=
|
| 1075 |
label="FreeU S2 (Skip 2)",
|
| 1076 |
-
info="Skip connection dampening for second layer. Balances scannability. Range: 0.0-1.5, Default:
|
| 1077 |
)
|
| 1078 |
|
| 1079 |
# SAG (Self-Attention Guidance) Parameters
|
| 1080 |
gr.Markdown("### SAG (Self-Attention Guidance)")
|
| 1081 |
enable_sag = gr.Checkbox(
|
| 1082 |
label="Enable SAG",
|
| 1083 |
-
value=
|
| 1084 |
info="Enable Self-Attention Guidance for improved structural coherence and artistic blending"
|
| 1085 |
)
|
| 1086 |
sag_scale = gr.Slider(
|
| 1087 |
minimum=0.0,
|
| 1088 |
maximum=3.0,
|
| 1089 |
step=0.1,
|
| 1090 |
-
value=
|
| 1091 |
label="SAG Scale",
|
| 1092 |
-
info="Guidance strength. Higher values provide more structural coherence. Range: 0.0-3.0, Default:
|
| 1093 |
)
|
| 1094 |
sag_blur_sigma = gr.Slider(
|
| 1095 |
minimum=0.0,
|
|
@@ -1100,33 +1164,6 @@ if __name__ == "__main__":
|
|
| 1100 |
info="Blur amount for artistic blending. Higher values create softer, more artistic effects. Range: 0.0-5.0, Default: 1.5"
|
| 1101 |
)
|
| 1102 |
|
| 1103 |
-
# Add style examples with labels
|
| 1104 |
-
gr.Markdown("### Style Examples:")
|
| 1105 |
-
|
| 1106 |
-
# First row of examples
|
| 1107 |
-
with gr.Row():
|
| 1108 |
-
with gr.Column(scale=1, min_width=0):
|
| 1109 |
-
gr.Markdown("**Square**", show_label=False)
|
| 1110 |
-
gr.Image("custom_nodes/ComfyQR/img/square.png", width=100, show_label=False, show_download_button=False)
|
| 1111 |
-
with gr.Column(scale=1, min_width=0):
|
| 1112 |
-
gr.Markdown("**Gapped Square**", show_label=False)
|
| 1113 |
-
gr.Image("custom_nodes/ComfyQR/img/gapped_square.png", width=100, show_label=False, show_download_button=False)
|
| 1114 |
-
with gr.Column(scale=1, min_width=0):
|
| 1115 |
-
gr.Markdown("**Circle**", show_label=False)
|
| 1116 |
-
gr.Image("custom_nodes/ComfyQR/img/circle.png", width=100, show_label=False, show_download_button=False)
|
| 1117 |
-
|
| 1118 |
-
# Second row of examples
|
| 1119 |
-
with gr.Row():
|
| 1120 |
-
with gr.Column(scale=1, min_width=0):
|
| 1121 |
-
gr.Markdown("**Rounded**", show_label=False)
|
| 1122 |
-
gr.Image("custom_nodes/ComfyQR/img/rounded.png", width=100, show_label=False, show_download_button=False)
|
| 1123 |
-
with gr.Column(scale=1, min_width=0):
|
| 1124 |
-
gr.Markdown("**Vertical Bars**", show_label=False)
|
| 1125 |
-
gr.Image("custom_nodes/ComfyQR/img/vertical-bars.png", width=100, show_label=False, show_download_button=False)
|
| 1126 |
-
with gr.Column(scale=1, min_width=0):
|
| 1127 |
-
gr.Markdown("**Horizontal Bars**", show_label=False)
|
| 1128 |
-
gr.Image("custom_nodes/ComfyQR/img/horizontal-bars.png", width=100, show_label=False, show_download_button=False)
|
| 1129 |
-
|
| 1130 |
# The generate button for artistic QR
|
| 1131 |
artistic_generate_btn = gr.Button("Generate Artistic QR", variant="primary")
|
| 1132 |
|
|
@@ -1142,7 +1179,7 @@ if __name__ == "__main__":
|
|
| 1142 |
# When clicking the button, it will trigger the artistic function
|
| 1143 |
artistic_generate_btn.click(
|
| 1144 |
fn=generate_artistic_qr,
|
| 1145 |
-
inputs=[artistic_prompt_input, artistic_text_input, artistic_input_type, artistic_image_size, artistic_border_size, artistic_error_correction, artistic_module_size, artistic_module_drawer, artistic_use_custom_seed, artistic_seed, freeu_b1, freeu_b2, freeu_s1, freeu_s2, enable_sag, sag_scale, sag_blur_sigma],
|
| 1146 |
outputs=[artistic_output_image, artistic_error_message]
|
| 1147 |
)
|
| 1148 |
|
|
|
|
| 22 |
hf_hub_download(repo_id="Lykon/dreamshaper-7", filename="vae/diffusion_pytorch_model.fp16.safetensors", local_dir="models")
|
| 23 |
hf_hub_download(repo_id="stabilityai/sd-vae-ft-mse-original", filename="vae-ft-mse-840000-ema-pruned.safetensors", local_dir="models/vae")
|
| 24 |
hf_hub_download(repo_id="lllyasviel/Annotators", filename="RealESRGAN_x4plus.pth", local_dir="models/upscale_models")
|
| 25 |
+
hf_hub_download(repo_id="lykon/RealESRGAN_x4plus", filename="RealESRGAN_x4plus.pth", local_dir="models/upscale_models")
|
| 26 |
|
| 27 |
def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
|
| 28 |
"""Returns the value at the given index of a sequence or mapping.
|
|
|
|
| 177 |
model_management.load_models_gpu(valid_models)
|
| 178 |
|
| 179 |
@spaces.GPU(duration=30)
|
| 180 |
+
def generate_qr_code_unified(prompt: str, text_input: str, input_type: str = "URL", image_size: int = 512, border_size: int = 4, error_correction: str = "Medium (15%)", module_size: int = 12, module_drawer: str = "Square", use_custom_seed: bool = False, seed: int = 0, pipeline: str = "standard", enable_upscale: bool = False, freeu_b1: float = 1.4, freeu_b2: float = 1.3, freeu_s1: float = 0.0, freeu_s2: float = 1.3, enable_sag: bool = True, sag_scale: float = 0.5, sag_blur_sigma: float = 1.5, controlnet_strength_first: float = 0.45, controlnet_strength_final: float = 0.7):
|
| 181 |
# Only manipulate the text if it's a URL input type
|
| 182 |
qr_text = text_input
|
| 183 |
if input_type == "URL":
|
|
|
|
| 191 |
|
| 192 |
with torch.inference_mode():
|
| 193 |
if pipeline == "standard":
|
| 194 |
+
yield from _pipeline_standard(prompt, qr_text, input_type, image_size, border_size, error_correction, module_size, module_drawer, actual_seed, enable_upscale)
|
| 195 |
else: # artistic
|
| 196 |
+
yield from _pipeline_artistic(prompt, qr_text, input_type, image_size, border_size, error_correction, module_size, module_drawer, actual_seed, enable_upscale, freeu_b1, freeu_b2, freeu_s1, freeu_s2, enable_sag, sag_scale, sag_blur_sigma, controlnet_strength_first, controlnet_strength_final)
|
| 197 |
|
| 198 |
+
def generate_standard_qr(prompt: str, text_input: str, input_type: str = "URL", image_size: int = 512, border_size: int = 4, error_correction: str = "Medium (15%)", module_size: int = 12, module_drawer: str = "Square", use_custom_seed: bool = False, seed: int = 0, enable_upscale: bool = False):
|
| 199 |
"""Wrapper function for standard QR generation"""
|
| 200 |
+
yield from generate_qr_code_unified(prompt, text_input, input_type, image_size, border_size, error_correction, module_size, module_drawer, use_custom_seed, seed, pipeline="standard", enable_upscale=enable_upscale)
|
| 201 |
|
| 202 |
+
def generate_artistic_qr(prompt: str, text_input: str, input_type: str = "URL", image_size: int = 512, border_size: int = 4, error_correction: str = "Medium (15%)", module_size: int = 12, module_drawer: str = "Square", use_custom_seed: bool = False, seed: int = 0, enable_upscale: bool = True, freeu_b1: float = 1.4, freeu_b2: float = 1.3, freeu_s1: float = 0.0, freeu_s2: float = 1.3, enable_sag: bool = True, sag_scale: float = 0.5, sag_blur_sigma: float = 1.5, controlnet_strength_first: float = 0.45, controlnet_strength_final: float = 0.7):
|
| 203 |
"""Wrapper function for artistic QR generation with FreeU and SAG parameters"""
|
| 204 |
+
yield from generate_qr_code_unified(prompt, text_input, input_type, image_size, border_size, error_correction, module_size, module_drawer, use_custom_seed, seed, pipeline="artistic", enable_upscale=enable_upscale, freeu_b1=freeu_b1, freeu_b2=freeu_b2, freeu_s1=freeu_s1, freeu_s2=freeu_s2, enable_sag=enable_sag, sag_scale=sag_scale, sag_blur_sigma=sag_blur_sigma, controlnet_strength_first=controlnet_strength_first, controlnet_strength_final=controlnet_strength_final)
|
| 205 |
|
| 206 |
def add_noise_to_border_only(image_tensor, seed: int, border_size: int, image_size: int, module_size: int = 12):
|
| 207 |
"""
|
|
|
|
| 290 |
# Convert back to tensor
|
| 291 |
return torch.from_numpy(img_np).to(image_tensor.device)
|
| 292 |
|
| 293 |
+
def _pipeline_standard(prompt: str, qr_text: str, input_type: str, image_size: int, border_size: int, error_correction: str, module_size: int, module_drawer: str, seed: int, enable_upscale: bool = False):
|
| 294 |
emptylatentimage_5 = emptylatentimage.generate(
|
| 295 |
width=image_size, height=image_size, batch_size=1
|
| 296 |
)
|
|
|
|
| 434 |
vae=get_value_at_index(checkpointloadersimple_4, 2),
|
| 435 |
)
|
| 436 |
|
| 437 |
+
# 3) Optionally upscale if enabled
|
| 438 |
+
if enable_upscale:
|
| 439 |
+
# Show pre-upscale result
|
| 440 |
+
pre_upscale_tensor = get_value_at_index(vaedecode_21, 0)
|
| 441 |
+
pre_upscale_np = (pre_upscale_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 442 |
+
pre_upscale_np = pre_upscale_np[0]
|
| 443 |
+
pre_upscale_pil = Image.fromarray(pre_upscale_np)
|
| 444 |
+
yield pre_upscale_pil, "Enhancement complete (step 3/4)... upscaling image"
|
| 445 |
+
|
| 446 |
+
# Upscale the final image
|
| 447 |
+
upscaled = imageupscalewithmodel.upscale(
|
| 448 |
+
upscale_model=get_value_at_index(upscalemodelloader_30, 0),
|
| 449 |
+
image=get_value_at_index(vaedecode_21, 0),
|
| 450 |
+
)
|
| 451 |
+
|
| 452 |
+
image_tensor = get_value_at_index(upscaled, 0)
|
| 453 |
+
image_np = (image_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 454 |
+
image_np = image_np[0]
|
| 455 |
+
pil_image = Image.fromarray(image_np)
|
| 456 |
+
yield pil_image, f"No errors, all good! Final QR art generated and upscaled. (step 4/4) | Seed: {seed}"
|
| 457 |
+
else:
|
| 458 |
+
# No upscaling
|
| 459 |
+
image_tensor = get_value_at_index(vaedecode_21, 0)
|
| 460 |
+
image_np = (image_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 461 |
+
image_np = image_np[0]
|
| 462 |
+
pil_image = Image.fromarray(image_np)
|
| 463 |
+
yield pil_image, f"No errors, all good! Final QR art generated. | Seed: {seed}"
|
| 464 |
+
|
| 465 |
+
def _pipeline_artistic(prompt: str, qr_text: str, input_type: str, image_size: int, border_size: int, error_correction: str, module_size: int, module_drawer: str, seed: int, enable_upscale: bool = True, freeu_b1: float = 1.4, freeu_b2: float = 1.3, freeu_s1: float = 0.0, freeu_s2: float = 1.3, enable_sag: bool = True, sag_scale: float = 0.5, sag_blur_sigma: float = 1.5, controlnet_strength_first: float = 0.45, controlnet_strength_final: float = 0.7):
|
| 466 |
# Generate QR code
|
| 467 |
qr_protocol = "None" if input_type == "Plain Text" else "Https"
|
| 468 |
|
|
|
|
| 543 |
|
| 544 |
# First ControlNet pass (using QR with border cubics)
|
| 545 |
controlnet_apply = controlnetapplyadvanced.apply_controlnet(
|
| 546 |
+
strength=controlnet_strength_first,
|
| 547 |
start_percent=0,
|
| 548 |
end_percent=1,
|
| 549 |
positive=get_value_at_index(positive_prompt, 0),
|
|
|
|
| 562 |
|
| 563 |
# Second ControlNet pass (using tile processed from QR with border cubics)
|
| 564 |
controlnet_apply = controlnetapplyadvanced.apply_controlnet(
|
| 565 |
+
strength=controlnet_strength_first,
|
| 566 |
start_percent=0,
|
| 567 |
end_percent=1,
|
| 568 |
positive=get_value_at_index(controlnet_apply, 0),
|
|
|
|
| 620 |
first_pass_np = (first_pass_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 621 |
first_pass_np = first_pass_np[0]
|
| 622 |
first_pass_pil = Image.fromarray(first_pass_np)
|
| 623 |
+
step_msg = "First enhancement pass complete (step 3/5)... final refinement pass" if border_size > 0 else "First enhancement pass complete (step 2/4)... final refinement pass"
|
| 624 |
yield first_pass_pil, step_msg
|
| 625 |
|
| 626 |
+
# Final ControlNet pass (second pass - refinement)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 627 |
controlnet_apply_final = controlnetapplyadvanced.apply_controlnet(
|
| 628 |
+
strength=controlnet_strength_final,
|
| 629 |
start_percent=0,
|
| 630 |
end_percent=1,
|
| 631 |
positive=get_value_at_index(positive_prompt, 0),
|
| 632 |
negative=get_value_at_index(negative_prompt, 0),
|
| 633 |
control_net=get_value_at_index(tile_controlnet, 0),
|
| 634 |
+
image=get_value_at_index(decoded, 0),
|
| 635 |
vae=get_value_at_index(checkpointloadersimple_artistic, 2),
|
| 636 |
)
|
| 637 |
|
|
|
|
| 662 |
vae=get_value_at_index(checkpointloadersimple_artistic, 2),
|
| 663 |
)
|
| 664 |
|
| 665 |
+
# Optionally upscale if enabled
|
| 666 |
+
if enable_upscale:
|
| 667 |
+
# Show result before upscaling
|
| 668 |
+
pre_upscale_tensor = get_value_at_index(final_decoded, 0)
|
| 669 |
+
pre_upscale_np = (pre_upscale_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 670 |
+
pre_upscale_np = pre_upscale_np[0]
|
| 671 |
+
pre_upscale_pil = Image.fromarray(pre_upscale_np)
|
| 672 |
+
step_msg = "Final refinement complete (step 4/5)... upscaling image" if border_size > 0 else "Final refinement complete (step 3/4)... upscaling image"
|
| 673 |
+
yield pre_upscale_pil, step_msg
|
| 674 |
+
|
| 675 |
+
# Upscale image with model (after final samples, before returning)
|
| 676 |
+
upscaled = imageupscalewithmodel.upscale(
|
| 677 |
+
upscale_model=get_value_at_index(upscalemodelloader_30, 0),
|
| 678 |
+
image=get_value_at_index(final_decoded, 0),
|
| 679 |
+
)
|
| 680 |
|
| 681 |
+
# Convert upscaled image to PIL Image and return
|
| 682 |
+
image_tensor = get_value_at_index(upscaled, 0)
|
| 683 |
+
image_np = (image_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 684 |
+
image_np = image_np[0]
|
| 685 |
+
final_image = Image.fromarray(image_np)
|
| 686 |
+
step_msg = f"No errors, all good! Final artistic QR code generated and upscaled. (step 5/5) | Seed: {seed}" if border_size > 0 else f"No errors, all good! Final artistic QR code generated and upscaled. (step 4/4) | Seed: {seed}"
|
| 687 |
+
yield final_image, step_msg
|
| 688 |
+
else:
|
| 689 |
+
# No upscaling
|
| 690 |
+
image_tensor = get_value_at_index(final_decoded, 0)
|
| 691 |
+
image_np = (image_tensor.cpu().numpy() * 255).astype(np.uint8)
|
| 692 |
+
image_np = image_np[0]
|
| 693 |
+
final_image = Image.fromarray(image_np)
|
| 694 |
+
step_msg = f"No errors, all good! Final artistic QR code generated. (step 4/4) | Seed: {seed}" if border_size > 0 else f"No errors, all good! Final artistic QR code generated. (step 3/3) | Seed: {seed}"
|
| 695 |
+
yield final_image, step_msg
|
| 696 |
|
| 697 |
+
|
| 698 |
+
if __name__ == "__main__" and not os.environ.get('QR_TESTING_MODE'):
|
| 699 |
|
| 700 |
# Start your Gradio app
|
| 701 |
with gr.Blocks() as app:
|
|
|
|
| 794 |
info="Select the style of the QR code modules (squares). See examples below. Different styles can give your QR code a unique look while maintaining scannability."
|
| 795 |
)
|
| 796 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 797 |
# Add style examples with labels
|
| 798 |
gr.Markdown("### Style Examples:")
|
| 799 |
|
|
|
|
| 821 |
gr.Markdown("**Horizontal Bars**", show_label=False)
|
| 822 |
gr.Image("custom_nodes/ComfyQR/img/horizontal-bars.png", width=100, show_label=False, show_download_button=False)
|
| 823 |
|
| 824 |
+
# Add upscale checkbox
|
| 825 |
+
enable_upscale = gr.Checkbox(
|
| 826 |
+
label="Enable Upscaling",
|
| 827 |
+
value=False,
|
| 828 |
+
info="Enable upscaling with RealESRGAN for higher quality output (disabled by default for standard pipeline)"
|
| 829 |
+
)
|
| 830 |
+
|
| 831 |
+
# Add seed controls
|
| 832 |
+
use_custom_seed = gr.Checkbox(
|
| 833 |
+
label="Use Custom Seed",
|
| 834 |
+
value=True,
|
| 835 |
+
info="Enable to use a specific seed for reproducible results"
|
| 836 |
+
)
|
| 837 |
+
seed = gr.Slider(
|
| 838 |
+
minimum=0,
|
| 839 |
+
maximum=2000000,
|
| 840 |
+
step=1,
|
| 841 |
+
value=718313,
|
| 842 |
+
label="Seed",
|
| 843 |
+
info="Seed value for reproducibility. Same seed with same settings will produce the same result."
|
| 844 |
+
)
|
| 845 |
+
|
| 846 |
# The generate button
|
| 847 |
generate_btn = gr.Button("Generate Standard QR", variant="primary")
|
| 848 |
|
|
|
|
| 858 |
# When clicking the button, it will trigger the main function
|
| 859 |
generate_btn.click(
|
| 860 |
fn=generate_standard_qr,
|
| 861 |
+
inputs=[prompt_input, text_input, input_type, image_size, border_size, error_correction, module_size, module_drawer, use_custom_seed, seed, enable_upscale],
|
| 862 |
outputs=[output_image, error_message]
|
| 863 |
)
|
| 864 |
|
|
|
|
| 1015 |
minimum=512,
|
| 1016 |
maximum=1024,
|
| 1017 |
step=64,
|
| 1018 |
+
value=704,
|
| 1019 |
label="Image Size",
|
| 1020 |
+
info="Base size of the generated image. Final output will be 2x this size (e.g., 704 → 1408) due to the two-step enhancement process. Higher values use more VRAM and take longer to process."
|
| 1021 |
)
|
| 1022 |
|
| 1023 |
# Add border size slider for artistic QR
|
|
|
|
| 1025 |
minimum=0,
|
| 1026 |
maximum=8,
|
| 1027 |
step=1,
|
| 1028 |
+
value=6,
|
| 1029 |
label="QR Code Border Size",
|
| 1030 |
info="Number of modules (squares) to use as border around the QR code. Higher values add more whitespace."
|
| 1031 |
)
|
|
|
|
| 1033 |
# Add error correction dropdown for artistic QR
|
| 1034 |
artistic_error_correction = gr.Dropdown(
|
| 1035 |
choices=["Low (7%)", "Medium (15%)", "Quartile (25%)", "High (30%)"],
|
| 1036 |
+
value="High (30%)",
|
| 1037 |
label="Error Correction Level",
|
| 1038 |
+
info="Higher error correction makes the QR code more scannable when damaged or obscured, but increases its size and complexity. High (30%) is recommended for artistic QR codes."
|
| 1039 |
)
|
| 1040 |
|
| 1041 |
# Add module size slider for artistic QR
|
|
|
|
| 1043 |
minimum=4,
|
| 1044 |
maximum=16,
|
| 1045 |
step=1,
|
| 1046 |
+
value=16,
|
| 1047 |
label="QR Module Size",
|
| 1048 |
+
info="Pixel width of the smallest QR code unit. Larger values improve readability but require a larger image size. 16 is a good starting point."
|
| 1049 |
)
|
| 1050 |
|
| 1051 |
# Add module drawer dropdown with style examples for artistic QR
|
|
|
|
| 1056 |
info="Select the style of the QR code modules (squares). See examples below. Different styles can give your QR code a unique look while maintaining scannability."
|
| 1057 |
)
|
| 1058 |
|
| 1059 |
+
# Add style examples with labels
|
| 1060 |
+
gr.Markdown("### Style Examples:")
|
| 1061 |
+
|
| 1062 |
+
# First row of examples
|
| 1063 |
+
with gr.Row():
|
| 1064 |
+
with gr.Column(scale=1, min_width=0):
|
| 1065 |
+
gr.Markdown("**Square**", show_label=False)
|
| 1066 |
+
gr.Image("custom_nodes/ComfyQR/img/square.png", width=100, show_label=False, show_download_button=False)
|
| 1067 |
+
with gr.Column(scale=1, min_width=0):
|
| 1068 |
+
gr.Markdown("**Gapped Square**", show_label=False)
|
| 1069 |
+
gr.Image("custom_nodes/ComfyQR/img/gapped_square.png", width=100, show_label=False, show_download_button=False)
|
| 1070 |
+
with gr.Column(scale=1, min_width=0):
|
| 1071 |
+
gr.Markdown("**Circle**", show_label=False)
|
| 1072 |
+
gr.Image("custom_nodes/ComfyQR/img/circle.png", width=100, show_label=False, show_download_button=False)
|
| 1073 |
+
|
| 1074 |
+
# Second row of examples
|
| 1075 |
+
with gr.Row():
|
| 1076 |
+
with gr.Column(scale=1, min_width=0):
|
| 1077 |
+
gr.Markdown("**Rounded**", show_label=False)
|
| 1078 |
+
gr.Image("custom_nodes/ComfyQR/img/rounded.png", width=100, show_label=False, show_download_button=False)
|
| 1079 |
+
with gr.Column(scale=1, min_width=0):
|
| 1080 |
+
gr.Markdown("**Vertical Bars**", show_label=False)
|
| 1081 |
+
gr.Image("custom_nodes/ComfyQR/img/vertical-bars.png", width=100, show_label=False, show_download_button=False)
|
| 1082 |
+
with gr.Column(scale=1, min_width=0):
|
| 1083 |
+
gr.Markdown("**Horizontal Bars**", show_label=False)
|
| 1084 |
+
gr.Image("custom_nodes/ComfyQR/img/horizontal-bars.png", width=100, show_label=False, show_download_button=False)
|
| 1085 |
+
|
| 1086 |
+
# Add upscale checkbox
|
| 1087 |
+
artistic_enable_upscale = gr.Checkbox(
|
| 1088 |
+
label="Enable Upscaling",
|
| 1089 |
+
value=True,
|
| 1090 |
+
info="Enable upscaling with RealESRGAN for higher quality output (enabled by default for artistic pipeline)"
|
| 1091 |
+
)
|
| 1092 |
+
|
| 1093 |
# Add seed controls for artistic QR
|
| 1094 |
artistic_use_custom_seed = gr.Checkbox(
|
| 1095 |
label="Use Custom Seed",
|
| 1096 |
+
value=True,
|
| 1097 |
info="Enable to use a specific seed for reproducible results"
|
| 1098 |
)
|
| 1099 |
artistic_seed = gr.Slider(
|
| 1100 |
minimum=0,
|
| 1101 |
maximum=2000000,
|
| 1102 |
step=1,
|
| 1103 |
+
value=718313,
|
| 1104 |
label="Seed",
|
| 1105 |
info="Seed value for reproducibility. Same seed with same settings will produce the same result."
|
| 1106 |
)
|
|
|
|
| 1111 |
minimum=1.0,
|
| 1112 |
maximum=1.6,
|
| 1113 |
step=0.01,
|
| 1114 |
+
value=1.4,
|
| 1115 |
label="FreeU B1 (Backbone 1)",
|
| 1116 |
+
info="Backbone feature enhancement for first layer. Higher values improve detail but may reduce blending. Range: 1.0-1.6, Default: 1.4"
|
| 1117 |
)
|
| 1118 |
freeu_b2 = gr.Slider(
|
| 1119 |
minimum=1.0,
|
|
|
|
| 1127 |
minimum=0.0,
|
| 1128 |
maximum=1.5,
|
| 1129 |
step=0.01,
|
| 1130 |
+
value=0.0,
|
| 1131 |
label="FreeU S1 (Skip 1)",
|
| 1132 |
+
info="Skip connection dampening for first layer. Lower values hide QR structure more. Range: 0.0-1.5, Default: 0.0"
|
| 1133 |
)
|
| 1134 |
freeu_s2 = gr.Slider(
|
| 1135 |
minimum=0.0,
|
| 1136 |
maximum=1.5,
|
| 1137 |
step=0.01,
|
| 1138 |
+
value=1.3,
|
| 1139 |
label="FreeU S2 (Skip 2)",
|
| 1140 |
+
info="Skip connection dampening for second layer. Balances scannability. Range: 0.0-1.5, Default: 1.3"
|
| 1141 |
)
|
| 1142 |
|
| 1143 |
# SAG (Self-Attention Guidance) Parameters
|
| 1144 |
gr.Markdown("### SAG (Self-Attention Guidance)")
|
| 1145 |
enable_sag = gr.Checkbox(
|
| 1146 |
label="Enable SAG",
|
| 1147 |
+
value=True,
|
| 1148 |
info="Enable Self-Attention Guidance for improved structural coherence and artistic blending"
|
| 1149 |
)
|
| 1150 |
sag_scale = gr.Slider(
|
| 1151 |
minimum=0.0,
|
| 1152 |
maximum=3.0,
|
| 1153 |
step=0.1,
|
| 1154 |
+
value=0.5,
|
| 1155 |
label="SAG Scale",
|
| 1156 |
+
info="Guidance strength. Higher values provide more structural coherence. Range: 0.0-3.0, Default: 0.5"
|
| 1157 |
)
|
| 1158 |
sag_blur_sigma = gr.Slider(
|
| 1159 |
minimum=0.0,
|
|
|
|
| 1164 |
info="Blur amount for artistic blending. Higher values create softer, more artistic effects. Range: 0.0-5.0, Default: 1.5"
|
| 1165 |
)
|
| 1166 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1167 |
# The generate button for artistic QR
|
| 1168 |
artistic_generate_btn = gr.Button("Generate Artistic QR", variant="primary")
|
| 1169 |
|
|
|
|
| 1179 |
# When clicking the button, it will trigger the artistic function
|
| 1180 |
artistic_generate_btn.click(
|
| 1181 |
fn=generate_artistic_qr,
|
| 1182 |
+
inputs=[artistic_prompt_input, artistic_text_input, artistic_input_type, artistic_image_size, artistic_border_size, artistic_error_correction, artistic_module_size, artistic_module_drawer, artistic_use_custom_seed, artistic_seed, artistic_enable_upscale, freeu_b1, freeu_b2, freeu_s1, freeu_s2, enable_sag, sag_scale, sag_blur_sigma],
|
| 1183 |
outputs=[artistic_output_image, artistic_error_message]
|
| 1184 |
)
|
| 1185 |
|