Spaces:
Sleeping
Sleeping
File size: 7,265 Bytes
67fcd2f 98ce8b0 5f3c681 c58149c 22bea51 5f3c681 22bea51 67fcd2f 22bea51 5f3c681 22bea51 67fcd2f 5f3c681 67fcd2f 22bea51 5f3c681 22bea51 67fcd2f 5f3c681 22bea51 c58149c 98ce8b0 c58149c 98ce8b0 67fcd2f c58149c 98ce8b0 67fcd2f c58149c 98ce8b0 5f3c681 67fcd2f 22bea51 98ce8b0 c58149c 67fcd2f c58149c 67fcd2f 5f3c681 98ce8b0 5f3c681 67fcd2f 5f3c681 67fcd2f 22bea51 5f3c681 22bea51 c58149c 5f3c681 22bea51 98ce8b0 c58149c 5f3c681 67fcd2f 5f3c681 22bea51 67fcd2f c58149c 22bea51 5f3c681 22bea51 c58149c 5f3c681 67fcd2f 5f3c681 c58149c 67fcd2f 5f3c681 67fcd2f 5f3c681 c58149c 22bea51 5f3c681 22bea51 67fcd2f 5f3c681 67fcd2f 22bea51 98ce8b0 5f3c681 22bea51 5f3c681 67fcd2f 5f3c681 c58149c 67fcd2f 22bea51 67fcd2f 22bea51 c58149c 67fcd2f 5f3c681 c58149c 5f3c681 22bea51 67fcd2f 22bea51 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# app.py (v4, CPU-optimized + brede Gradio-compat)
# Neurale netwerken als tekenaars — Stable Diffusion + ControlNet (scribble)
# - Werkt op CPU (langzamer dan GPU, maar demowaardig)
# - Gebruikt gr.Sketchpad (compatibel met oudere Gradio-versies)
# - Geen queue-parameters (demo.queue() zonder args)
import os, random, numpy as np
from typing import Optional
from PIL import Image, ImageDraw
import gradio as gr
import torch
from diffusers import (
ControlNetModel,
StableDiffusionControlNetPipeline,
DPMSolverMultistepScheduler,
)
# Modellen (kun je via Space Secrets/Opsional env-vars overriden)
MODEL_BASE = os.environ.get("SD_BASE_MODEL", "runwayml/stable-diffusion-v1-5")
MODEL_CN = os.environ.get("CN_SCRIBBLE_MODEL", "lllyasviel/sd-controlnet-scribble")
DEVICE = "cpu" # geforceerd CPU
DTYPE = torch.float32
TARGET_SIZE = 512 # lager = sneller op CPU
DEFAULT_STEPS = 12 # CPU-vriendelijk
pipe: Optional[StableDiffusionControlNetPipeline] = None
def _lazy_load_pipeline():
global pipe
if pipe is not None:
return pipe
controlnet = ControlNetModel.from_pretrained(MODEL_CN, torch_dtype=DTYPE)
pipe = StableDiffusionControlNetPipeline.from_pretrained(
MODEL_BASE, controlnet=controlnet, torch_dtype=DTYPE, safety_checker=None
)
# Snellere scheduler → minder stappen nodig
pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
pipe = pipe.to(DEVICE)
pipe.enable_attention_slicing()
return pipe
def to_rgba(img):
"""Accepteer numpy of PIL en geef een PIL RGBA image terug."""
if img is None:
return None
if isinstance(img, np.ndarray):
if img.dtype != np.uint8:
img = img.astype(np.uint8)
return Image.fromarray(img).convert("RGBA")
if isinstance(img, Image.Image):
return img.convert("RGBA")
try:
return Image.open(img).convert("RGBA")
except Exception:
return None
def rgba_to_scribble(img) -> Image.Image:
"""Zet RGBA schets om naar zwart-op-wit, vierkant en resized (TARGET_SIZE)."""
img = to_rgba(img)
if img is None:
return None
# transparant → wit
bg = Image.new("RGBA", img.size, (255, 255, 255, 255))
img = Image.alpha_composite(bg, img)
# grijs + drempel
arr = np.array(img.convert("L"))
thr = max(25, int(arr.mean() * 0.9))
lines = arr < thr
out = np.full((*arr.shape, 3), 255, dtype=np.uint8)
out[lines] = (0, 0, 0)
scribble = Image.fromarray(out, "RGB")
# vierkant + resize
m = max(scribble.width, scribble.height)
sq = Image.new("RGB", (m, m), (255, 255, 255))
sq.paste(scribble, ((m - scribble.width) // 2, (m - scribble.height) // 2))
return sq.resize((TARGET_SIZE, TARGET_SIZE), Image.BICUBIC)
def run(drawing, prompt, negative_prompt,
guidance_scale=7.0, controlnet_conditioning_scale=1.0,
num_inference_steps=DEFAULT_STEPS, seed=-1):
if drawing is None:
raise gr.Error("Teken eerst iets of gebruik de voorbeeld-schets.")
cn_image = rgba_to_scribble(drawing)
if cn_image is None:
raise gr.Error("Schets niet leesbaar. Probeer opnieuw of upload PNG/JPG.")
if not prompt or not str(prompt).strip():
prompt = "clean pencil sketch, coherent completion, subtle shading, high quality"
if seed is None or int(seed) < 0:
seed = random.randint(0, 2**31 - 1)
gen = torch.Generator(device=DEVICE).manual_seed(int(seed))
p = _lazy_load_pipeline()
full_prompt = (
"black pencil sketch, clean lines, coherent shape completion, subtle shading, "
"consistent with the input scribble, " + prompt
)
result = p(
prompt=full_prompt,
negative_prompt=negative_prompt or "text, watermark, extra limbs, low quality, distorted face, nsfw",
image=cn_image,
width=cn_image.width, height=cn_image.height,
generator=gen, num_inference_steps=int(num_inference_steps),
guidance_scale=float(guidance_scale),
controlnet_conditioning_scale=float(controlnet_conditioning_scale),
)
image = result.images[0]
pad = 12
combo = Image.new("RGB", (cn_image.width * 2 + pad, cn_image.height), (245, 245, 245))
combo.paste(cn_image, (0, 0))
combo.paste(image, (cn_image.width + pad, 0))
return image, cn_image, combo, f"Seed: {seed}, steps: {num_inference_steps}"
def make_example_scribble() -> Image.Image:
"""Kleine voorbeeldschets (appelvorm) voor snelle test."""
w, h = 360, 360
img = Image.new("RGBA", (w, h), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
d.line([(100,300),(90,230),(110,170),(160,140),(200,140),
(260,170),(280,230),(260,300),(180,320),(100,300)],
fill=(0,0,0,255), width=12)
d.line([(200,140),(210,110)], fill=(0,0,0,255), width=10)
d.line([(210,110),(250,120),(265,150)], fill=(0,0,0,255), width=9)
return img
CSS = ".gradio-container{max-width:1100px} #combo img{border-radius:10px}"
with gr.Blocks(title="🖌️ Neurale netwerken als tekenaars (CPU v4)", css=CSS) as demo:
gr.Markdown("## 🖌️ Neurale netwerken als tekenaars (CPU)\nTeken links of klik **Voorbeeld-schets**; AI vult aan met Stable Diffusion + ControlNet (scribble).")
with gr.Row():
with gr.Column():
canvas = gr.Sketchpad(label="Schets (teken in zwart op transparant/wit)", height=420)
prompt = gr.Textbox(label="Prompt", value="realistische appel met blad, potloodschets")
negative_prompt = gr.Textbox(label="Negative prompt (optioneel)", value="tekst, watermerk, wazig")
with gr.Accordion("Geavanceerd", open=False):
guidance_scale = gr.Slider(5.0, 10.0, value=7.0, step=0.5, label="Guidance scale")
cn_strength = gr.Slider(0.6, 1.6, value=1.0, step=0.05, label="ControlNet conditioning scale")
steps = gr.Slider(6, 25, value=DEFAULT_STEPS, step=1, label="Aantal diffusion-steps")
seed = gr.Number(value=-1, precision=0, label="Seed (-1 = random)")
with gr.Row():
run_btn = gr.Button("Vervolledig ✨", variant="primary")
example_btn = gr.Button("Voorbeeld-schets", variant="secondary")
with gr.Column():
out_img = gr.Image(label="Vervolledigde tekening", interactive=False)
cn_prev = gr.Image(label="Scribble (input voor AI)", interactive=False)
combo = gr.Image(label="Vergelijking (links: input, rechts: AI)", elem_id="combo")
meta = gr.Markdown()
def fill_and_run(p, n, gs, cs, st, sd):
img = make_example_scribble()
a, b, c, d = run(img, p, n, gs, cs, st, sd)
return img, a, b, c, d
run_btn.click(run, inputs=[canvas, prompt, negative_prompt, guidance_scale, cn_strength, steps, seed],
outputs=[out_img, cn_prev, combo, meta])
example_btn.click(fill_and_run, inputs=[prompt, negative_prompt, guidance_scale, cn_strength, steps, seed],
outputs=[canvas, out_img, cn_prev, combo, meta])
demo.queue() # zonder parameters: compatibel met oudere Gradio-versies
if __name__ == "__main__":
demo.launch()
|