Szenen aus der Figuren-Bibliothek: freigestellte Standbilder mit Posenwechsel, freigestellte Clips (WebM mit Alpha in /shared), Orte als vorberechnete Aquarell-SVGs, Untertitel statt Stimmen. Zeitplan aus den Sprechzeilen, damit ElevenLabs-Aufnahmen später nur die Dauer setzen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
37 lines
1.6 KiB
Python
37 lines
1.6 KiB
Python
# Standbilder freistellen (rembg), Leinwand bleibt erhalten.
|
|
# python3 werkzeuge/freistellen.py <zielordner> bild1.png bild2.png ...
|
|
# Freistellen ohne Zuschneiden (gleiche Leinwand -> Posen deckungsgleich)
|
|
import sys, os, time
|
|
import numpy as np
|
|
from PIL import Image, ImageFilter
|
|
from scipy import ndimage
|
|
from rembg import remove, new_session
|
|
s = new_session("isnet-general-use")
|
|
out_dir = sys.argv[1]
|
|
for src in sys.argv[2:]:
|
|
dst = os.path.join(out_dir, os.path.basename(src)[:-4] + ".png")
|
|
if os.path.exists(dst): continue
|
|
t = time.time()
|
|
im = Image.open(src).convert("RGB")
|
|
m = np.asarray(remove(im, session=s, only_mask=True)).astype(float)
|
|
hard = m > 110
|
|
lab, n = ndimage.label(hard)
|
|
if n == 0: print("LEER", src); continue
|
|
sizes = ndimage.sum(hard, lab, range(1, n + 1))
|
|
keep = np.zeros_like(hard)
|
|
for i, sz in enumerate(sizes): # alle großen Teile (Laterne, Bommel) behalten
|
|
if sz > 0.02 * sizes.max(): keep |= lab == i + 1
|
|
hard = keep
|
|
holes = ndimage.binary_fill_holes(hard) & ~hard
|
|
hl, hn = ndimage.label(holes)
|
|
for i in range(1, hn + 1):
|
|
if (hl == i).sum() < 400: hard |= hl == i
|
|
rgb = np.asarray(im).astype(float)
|
|
paper = (rgb.min(-1) > 228) & (rgb.max(-1) - rgb.min(-1) < 18)
|
|
plab, pn = ndimage.label(paper & hard)
|
|
for i in range(1, pn + 1):
|
|
if (plab == i).sum() > 600: hard &= ~(plab == i)
|
|
hard = ndimage.binary_erosion(hard, iterations=2)
|
|
a = Image.fromarray((hard * 255).astype("uint8")).filter(ImageFilter.GaussianBlur(0.8))
|
|
o = im.convert("RGBA"); o.putalpha(a); o.save(dst)
|
|
print(os.path.basename(dst), round(time.time() - t, 1), flush=True)
|