Code-Cooker / app.py
Severian's picture
Update app.py
8195d89 verified
raw
history blame
14.6 kB
import torch
import gradio as gr
from PIL import Image
import qrcode
from pathlib import Path
from multiprocessing import cpu_count
import requests
import io
import os
from PIL import Image
import spaces
from diffusers import (
StableDiffusionPipeline,
StableDiffusionControlNetImg2ImgPipeline,
StableDiffusionControlNetPipeline,
ControlNetModel,
DDIMScheduler,
DPMSolverMultistepScheduler,
DEISMultistepScheduler,
HeunDiscreteScheduler,
EulerDiscreteScheduler,
)
qrcode_generator = qrcode.QRCode(
version=1,
error_correction=qrcode.ERROR_CORRECT_H,
box_size=10,
border=4,
)
controlnet = ControlNetModel.from_pretrained(
"DionTimmer/controlnet_qrcode-control_v1p_sd15", torch_dtype=torch.float16
).to("cuda")
pipe = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(
#"digiplay/GhostMixV1.2VAE",
"benjamin-paine/stable-diffusion-v1-5",
controlnet = controlnet,
torch_dtype = torch.float16,
safety_checker = None,
).to("cuda")
#pipe.enable_xformers_memory_efficient_attention()
def resize_for_condition_image(input_image: Image.Image, resolution: int):
input_image = input_image.convert("RGB")
W, H = input_image.size
k = float(resolution) / min(H, W)
H *= k
W *= k
H = int(round(H / 64.0)) * 64
W = int(round(W / 64.0)) * 64
img = input_image.resize((W, H), resample=Image.LANCZOS)
return img
SAMPLER_MAP = {
"DPM++ Karras SDE": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True, algorithm_type="sde-dpmsolver++"),
"DPM++ Karras": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True),
"Heun": lambda config: HeunDiscreteScheduler.from_config(config),
"Euler": lambda config: EulerDiscreteScheduler.from_config(config),
"DDIM": lambda config: DDIMScheduler.from_config(config),
"DEIS": lambda config: DEISMultistepScheduler.from_config(config),
}
@spaces.GPU()
def inference(
qr_code_content: str,
prompt: str,
negative_prompt: str,
guidance_scale: float = 10.0,
controlnet_conditioning_scale: float = 2.0,
strength: float = 0.8,
seed: int = -1,
init_image: Image.Image | None = None,
qrcode_image: Image.Image | None = None,
use_qr_code_as_init_image = True,
sampler = "DPM++ Karras SDE",
):
if prompt is None or prompt == "":
raise gr.Error("Prompt is required")
if qrcode_image is None and qr_code_content == "":
raise gr.Error("QR Code Image or QR Code Content is required")
pipe.scheduler = SAMPLER_MAP[sampler](pipe.scheduler.config)
generator = torch.manual_seed(seed) if seed != -1 else torch.Generator()
if qr_code_content != "" or qrcode_image.size == (1, 1):
print("Generating QR Code from content")
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10,
border=4,
)
qr.add_data(qr_code_content)
qr.make(fit=True)
qrcode_image = qr.make_image(fill_color="black", back_color="white")
qrcode_image = resize_for_condition_image(qrcode_image, 768)
else:
print("Using QR Code Image")
qrcode_image = resize_for_condition_image(qrcode_image, 768)
# hack due to gradio examples
init_image = qrcode_image
out = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
image=qrcode_image,
control_image=qrcode_image, # type: ignore
width=768, # type: ignore
height=768, # type: ignore
guidance_scale=float(guidance_scale),
controlnet_conditioning_scale=float(controlnet_conditioning_scale), # type: ignore
generator=generator,
strength=float(strength),
num_inference_steps=50,
)
return out.images[0] # type: ignore
with gr.Blocks(css="""
body {
background-color: #000000;
color: #ffffff;
}
.gradio-container {
background-color: #000000;
}
.gr-button-primary {
background-color: #ff0000 !important;
border-color: #ff0000 !important;
}
.gr-button-primary:hover {
background-color: #cc0000 !important;
border-color: #cc0000 !important;
}
.gr-form {
background-color: #1a1a1a;
border: 1px solid #333333;
border-radius: 8px;
padding: 20px;
}
.gr-input, .gr-select {
background-color: #2a2a2a;
border-color: #444444;
color: #ffffff;
}
.gr-input:focus, .gr-select:focus {
border-color: #ff0000;
}
.gr-form-label {
color: #ff0000;
}
""") as blocks:
gr.Markdown(
"""
![Yamamoto Logo](https://cdn-uploads.huggingface.co/production/uploads/64740cf7485a7c8e1bd51ac9/_VyYxp5qE_nRZ_LJqBxmL.webp)
# 🎨 Yamamoto QR Code Art Generator
## Transform Your QR Codes into Brand Masterpieces
Welcome to Yamamoto's innovative QR Code Art Generator! This cutting-edge tool empowers our creative team to craft
visually stunning, on-brand QR codes that perfectly blend functionality with artistic expression.
## 🚀 How It Works:
1. **Enter Your QR Code Content**: Start by inputting the URL or text for your QR code.
2. **Craft Your Prompt**: Describe the artistic style or theme you envision for your QR code.
3. **Fine-tune with Advanced Settings**: Adjust parameters to perfect your creation (see tips below).
4. **Generate and Iterate**: Click 'Run' to create your art, then refine as needed.
## 🌟 Tips for Spectacular Results:
- **Artistic Freedom**: Set between 0.8 and 0.95 for a balance of creativity and scannability.
- **QR Code Visibility**: Aim for 0.6 to 2.0 to ensure your code is both artistic and functional.
- **Prompt Crafting**: Use vivid, specific descriptions that align with your brand identity.
- **Experimentation**: Don't hesitate to try different settings and prompts to find your perfect style!
## 🎭 Prompt Ideas to Spark Your Creativity:
- "A serene Japanese garden with cherry blossoms and a koi pond"
- "A futuristic cityscape with neon lights and flying cars"
- "An abstract painting with swirling colors and geometric shapes"
- "A vintage-style travel poster featuring iconic landmarks"
Remember, the magic lies in the details of your prompt and the fine-tuning of your settings.
Happy creating!
""",
)
with gr.Row():
with gr.Column():
qr_code_content = gr.Textbox(
label="QR Code Content",
placeholder="Enter URL or text for your QR code",
info="This is what your QR code will link to or display when scanned.",
)
with gr.Accordion(label="QR Code Image (Optional)", open=False):
qr_code_image = gr.Image(
label="QR Code Image (Optional). Leave blank to automatically generate QR code",
type="pil",
)
prompt = gr.Textbox(
label="Artistic Prompt",
placeholder="Describe the style or theme for your QR code art",
info="Be specific and creative! This guides the AI in creating your unique QR art.",
)
negative_prompt = gr.Textbox(
label="Elements to Avoid",
placeholder="Describe what you don't want in the image",
value="ugly, disfigured, low quality, blurry, nsfw",
info="List elements or styles you want to avoid in your QR code art.",
)
use_qr_code_as_init_image = gr.Checkbox(
label="Use QR code as init image",
value=True,
interactive=False,
info="Whether init image should be QR code. Unclick to pass init image or generate init image with Stable Diffusion 2.1"
)
with gr.Accordion(label="Init Images (Optional)", open=False, visible=True) as init_image_acc:
init_image = gr.Image(label="Init Image (Optional). Leave blank to generate image with AI", type="pil")
with gr.Accordion("Advanced Artistic Controls", open=True):
controlnet_conditioning_scale = gr.Slider(
minimum=0.0,
maximum=5.0,
step=0.01,
value=1.1,
label="QR Code Visibility",
)
gr.Markdown(
"""Balance between QR code clarity and artistic integration:
- Lower (0.0-0.5): Subtle, may be hard to scan
- Middle (0.6-1.5): Good blend of art and function
- Higher (1.6-5.0): Very clear QR code, less artistic freedom
- Start at 1.1 and adjust to find your perfect balance."""
)
strength = gr.Slider(
minimum=0.0,
maximum=1.0,
step=0.01,
value=0.9,
label="Artistic Freedom",
)
gr.Markdown(
"""Controls how much the AI can alter the QR code:
- Lower (0.0-0.3): Minimal changes, closer to standard QR
- Middle (0.4-0.7): Balanced artistic elements
- Higher (0.8-1.0): Maximum creativity, may affect scannability
- Begin with 0.9 for a creative yet functional result."""
)
guidance_scale = gr.Slider(
minimum=0.0,
maximum=50.0,
step=0.25,
value=7.5,
label="Prompt Adherence",
)
gr.Markdown(
"""Determines how closely the AI follows your prompt:
- Lower (0-5): More AI creativity, less prompt influence
- Middle (5-15): Balanced between prompt and AI interpretation
- Higher (15+): Strictly follows prompt, less variation
- Start at 7.5 and adjust based on your desired outcome."""
)
sampler = gr.Dropdown(
choices=list(SAMPLER_MAP.keys()),
value="DPM++ Karras SDE",
label="Image Generation Technique",
)
gr.Markdown(
"""Different methods for creating your QR art:
- DPM++ Karras SDE: Versatile, high-quality results
- Euler: Sharp, detailed images
- DDIM: Good for abstract or artistic styles
- Experiment to find what works best for your vision!"""
)
seed = gr.Slider(
minimum=-1,
maximum=9999999999,
step=1,
value=-1,
label="Creative Seed",
randomize=False,
)
gr.Markdown(
"""Controls the randomness in art creation:
- -1: New, unique creation each time
- Any other number: Recreates the same image consistently
- Use -1 to explore, or set a specific number to refine a design you like.""",
)
with gr.Row():
run_btn = gr.Button("🎨 Create Your QR Art", variant="primary")
with gr.Column():
result_image = gr.Image(label="Your Artistic QR Code")
gr.Markdown(
"""
### 🔍 Analyzing Your Creation
- Is the QR code scannable? Test it with your phone's camera.
- Does the art style match your prompt? If not, try adjusting the 'Prompt Adherence'.
- Want more artistic flair? Increase the 'Artistic Freedom'.
- Need a clearer QR code? Raise the 'QR Code Visibility'.
Remember, creating the perfect QR art is a journey of experimentation and refinement.
Enjoy the process of bringing your unique vision to life!
"""
)
run_btn.click(
inference,
inputs=[
qr_code_content,
prompt,
negative_prompt,
guidance_scale,
controlnet_conditioning_scale,
strength,
seed,
init_image,
qr_code_image,
use_qr_code_as_init_image,
sampler,
],
outputs=[result_image],
concurrency_limit=20
)
gr.Examples(
examples=[
[
"https://huggingface.co/",
"A sky view of a colorful lakes and rivers flowing through the desert",
"ugly, disfigured, low quality, blurry, nsfw",
7.5,
1.3,
0.9,
5392011833,
None,
None,
True,
"DPM++ Karras SDE",
],
[
"https://huggingface.co/",
"Bright sunshine coming through the cracks of a wet, cave wall of big rocks",
"ugly, disfigured, low quality, blurry, nsfw",
7.5,
1.11,
0.9,
2523992465,
None,
None,
True,
"DPM++ Karras SDE",
],
[
"https://huggingface.co/",
"Sky view of highly aesthetic, ancient greek thermal baths in beautiful nature",
"ugly, disfigured, low quality, blurry, nsfw",
7.5,
1.5,
0.9,
2523992465,
None,
None,
True,
"DPM++ Karras SDE",
],
],
fn=inference,
inputs=[
qr_code_content,
prompt,
negative_prompt,
guidance_scale,
controlnet_conditioning_scale,
strength,
seed,
init_image,
qr_code_image,
use_qr_code_as_init_image,
sampler,
],
outputs=[result_image],
cache_examples=False,
)
blocks.queue(max_size=20,api_open=False)
blocks.launch(share=bool(os.environ.get("SHARE", False)), show_api=True)