Open-source AI-generated comic-style image dataset for the German Federal Food Code (BLS 4.0)
Find a file
2026-05-09 12:02:59 +02:00
data Initial commit — BLS-Bilddatensatz mit comic_v4-Pipeline 2026-05-08 19:28:32 +02:00
iterations Konsolidiere Pipeline auf 3 Schritte in einem Tool, Sieger Bg-Removal: BiRefNet-massive 2026-05-08 21:27:08 +02:00
style Initial commit — BLS-Bilddatensatz mit comic_v4-Pipeline 2026-05-08 19:28:32 +02:00
.gitignore Add README, iteration showcase, comparison.md viewer 2026-05-08 19:39:48 +02:00
CLAUDE.md Konsolidiere Pipeline auf 3 Schritte in einem Tool, Sieger Bg-Removal: BiRefNet-massive 2026-05-08 21:27:08 +02:00
CONTRIBUTING.md sync CONTRIBUTING.md from moritz-meta 2026-05-09 12:02:59 +02:00
generate.py Konsolidiere Pipeline auf 3 Schritte in einem Tool, Sieger Bg-Removal: BiRefNet-massive 2026-05-08 21:27:08 +02:00
LICENSE Initial commit — BLS-Bilddatensatz mit comic_v4-Pipeline 2026-05-08 19:28:32 +02:00
README.md README-Showcase auf freigestellte Bilder (BiRefNet-massive, pink-composite) 2026-05-08 21:29:39 +02:00
viewer.py Konsolidiere Pipeline auf 3 Schritte in einem Tool, Sieger Bg-Removal: BiRefNet-massive 2026-05-08 21:27:08 +02:00

act-img-gen

Open-Source-Pipeline zur Erzeugung eines konsistent gestylten Bilddatensatzes für jedes Lebensmittel im Bundeslebensmittelschlüssel 4.0 (BLS — der vom Max Rubner-Institut gepflegte Lebensmittelkatalog Deutschlands, 7140 Items).

Bestandteil von ACT, einer Tracking-App für die deutsche Ernährungsdatenbank. ACT braucht für jedes Lebensmittel ein erkennbares, visuell konsistentes Icon — bei 7140 Items ist Stockfotografie keine Option, und kommerzielle Datasets gibt es für BLS nicht.

ACT-Hauptrepo: https://git.moritz.run/moritz/act


Sieger-Setup

Style comic_v4 — flacher Sticker ohne Outlines, englische Prompts mit 5 universellen Regeln
Prompter-LLM gpt-5-mini (OpenAI direkt, sync, reasoning_effort: "minimal")
Image-Modell gpt-image-2 quality low (272 Output-Tokens) via Batch API
Background-Removal birefnet-massive lokal via rembg (Apache 2.0, ~1.5 GB ONNX)
Auflösung 1024 × 1024 PNG mit Alpha-Kanal (transparenter Hintergrund)
Preis pro Bild ~$0.0044 (LLM ~$0.001 + Bild ~$0.003 im Batch-Tarif; Bg-Removal lokal = $0)
Komplettes BLS 4.0 (7140 Items) ~$31 API-Kosten + ~32h CPU-Zeit fürs Bg-Removal (oder ~3h auf GPU)

Drei Schritte

BLS-Item ──┐
           ▼                                    ┌─→ output/comic_v4/<SBLS>/prompt.md
[1] gpt-5-mini sync ───── englischer Prompt ────┘
                                                ├─→ output/comic_v4/<SBLS>/openai__gpt-image-2-low_raw.png
                                                │   (rohes API-PNG mit weißem Hintergrund, als Backup)
[2] gpt-image-2 batch ─── 1024×1024 PNG ────────┤
                                                └─→ output/comic_v4/<SBLS>/openai__gpt-image-2-low.png
                                                    (transparente Production-Datei für ACT)
[3] BiRefNet-massive ──── Hintergrund weg ──────┘

20 Sieger-Beispiele aus data/benchmark_items.csv (Bezeichnungen exakt aus BLS 4.0). Hot-pink Hintergrund ist nicht Teil der Production-Bilder — ist nur eingeblendet, damit man sieht wo die Transparenz funktioniert. Die echten Production-PNGs haben Alpha-Kanal und sind hintergrundlos für ACT. Vollständiger Algorithmen-Vergleich (PIL vs. ISNet vs. BiRefNet-general vs. BiRefNet-massive) in iterations/comparison.md:

Weizenvollkornknäckebrot mit Ölsamen, Hartkäse und Möhre Roggen Backschrot, Type 1800 Vollkorncroissant (Plunderteig) Teigwaren eifrei, gekocht Maracujanektar/Passionsfruchtnektar
Wurzelpetersilie gebraten ohne Fett (Pfanne) Erdnussmus Hallimasch gebraten ohne Fett (Pfanne) H-Vollmilch 3,5 % Fett, laktosefrei, ultrahocherhitzt Kaffee (Getränk) mit Mandeldrink, ungesüßt
Stout Sauerrahmbutter Mohnfüllung für Gebäck/Torten Speiseeis Nuss, in Waffeltüte Europäische Auster tiefgefroren, gratiniert ohne Fett (Ofen)
Rind Leberhack, gebraten ohne Fett (Pfanne) Schnecken tiefgefroren, gekocht Rheinische Bratwurst gebraten ohne Fett (Pfanne) Vollkornpfannkuchen/Vollkorneierkuchen, ungesüßt, mit Milch 3,5 % Fett, gebraten Omelett gebraten, gefüllt mit blanchiertem Gemüse und Kochschinken

Verwendung

# Voraussetzungen:
#   - OPENAI_API_KEY in .env
#   - Python-Deps: requests Pillow rembg[cpu] numpy scipy onnxruntime
#   - Verifizierte OpenAI-Org (gpt-image-2 freigeschaltet)

python3 generate.py --dry-run         # Kostenschätzung
python3 generate.py                   # Submit Batch (Schritt 1+2)
python3 generate.py --fetch latest    # Bilder abholen + Bg-Removal (Schritt 2+3)

python3 generate.py --postprocess     # Schritt 3 nachträglich auf alten Bildern

python3 viewer.py                     # interaktiver HTML-Viewer mit Lightbox

Drei-Schritt-Pipeline läuft mit einem einzigen Tool (generate.py). Submit gibt eine Batch-ID zurück; --fetch erledigt automatisch sowohl Image-Download als auch Hintergrund-Removal in einem Lauf. --no-postprocess falls man Schritt 3 überspringen möchte.

Items kommen aus data/benchmark_items.csv (20 zufällige BLS-Items mit Seed 42 für die Iteration). Für den vollen 7140-Lauf muss diese CSV durch eine Vollliste ersetzt werden — Spalten: sbls,name_de,name_en,hauptgruppe.


Warum das so kompliziert war

Erste Iteration (siehe iterations/openai-prototype/) war ein einzelner Studio-Foto-Prompt, an alle Items gleich verschickt. Resultat: Schweinshaxe vor reinweißem Hintergrund sah grotesk aus, Apfelkompott kam ohne Schüssel auf den nackten Boden. Plus: gpt-image @ photo-quality kostet ~$0.04 pro Bild. Bei 7140 Items wären das mindestens $300 für eine Stilvariante, und das Ergebnis war optisch unbrauchbar.

Drei Erkenntnisse daraus:

  1. Der Stil muss flach sein, nicht foto. Sonst überdramatisieren die Modelle Items, die im echten Leben nüchtern aussehen (Joghurt, rohes Fleisch, Suppe). Comic-Sticker schluckt das.
  2. Pro Item braucht's einen eigenen Prompt, der die "Anrichtung" entscheidet (Glas? Schüssel? freistehend?). Ein cheap LLM davor löst das günstig.
  3. Der Hintergrund muss raus — die App hat dunkle und helle Themes, und ein weißer Block hinter jedem Item sieht überall furchtbar aus.

Die folgende Iteration hat systematisch durch alle drei Achsen gegrast.

Was alles probiert wurde

Image-Modelle (alle auf 20 Benchmark-Items)

Modell Provider Kosten/Bild Verwurf-Grund
recraft/recraft-v4 OpenRouter $0.040 sehr teuer, keine Style-Konsistenz
sourceful/riverflow-v2-fast OpenRouter $0.020 uneinheitlicher Look zwischen Items
openai/gpt-5-image-mini OpenRouter $0.044 OpenRouter-Bundle: GPT-5-mini wrappt gpt-image-1-mini → 2.5× teurer als Direkt-API
openai/gpt-image-1-mini @ high OpenAI direkt $0.017 cremefarbener Hintergrund-Bias statt cleanem Weiß
openai/gpt-image-2 @ medium OpenAI Batch $0.030 7× teurer als low ohne sichtbaren Mehrwert beim flachen Sticker
openai/gpt-image-2 @ low OpenAI Batch $0.003 Sieger — sauberes Weiß, gute Anweisungs-Befolgung

Style-Spezifikationen (style/)

Alle Stile sind dieselben Kompositions-/Anrichtungsregeln, nur der Zeichen-Look + die Prompt-Sprache ändern sich:

Style Look Prompt-Sprache Status
comic_v1 Comic mit Outlines Deutsch (Kimi K2.6) verworfen — Outlines verschmutzten kleine Items
comic_v2 Flat ohne Outlines Deutsch (Kimi K2.6) besser, aber auf Englisch nochmal sichtbar besser
comic_v3 Flat ohne Outlines Englisch (gpt-5-mini) großer Sprung in Anweisungs-Befolgung
comic_v5 Soft-3D mit Verlauf Englisch nett, aber lenkt vom Item ab
comic_v6 Claymation 3D-Render Englisch sah aus wie WWDC-Pics — schön, aber zu "designed" für eine neutrale Lebensmittel-DB
comic_v7 Pixel-Art 16-bit Englisch distinktiv, aber zu retro für eine moderne Health-App
comic_v8 Neon-Cyber dezent Englisch dito — visuelles Nischen-Statement
comic_v4 Flat ohne Outlines Englisch + 5 universelle Regeln Sieger

Was comic_v4 über comic_v3 hinaus addiert sind fünf universelle Prompt-Regeln, die das Image-Modell sauberer steuern (Details in style/comic_v4.md):

  • A — Nicht-visuelle Eigenschaften weglassen ("egg-free pasta" verwirrt das Bildmodell).
  • B — Zusammengesetzte Items als Einheit darstellen ("Knäckebrot mit Käse und Möhre" → ein composed bite, nicht drei separate Zutaten).
  • C — Mehrdeutige Items: eine Konsumform wählen und committen, keine "either/or"-Formulierungen.
  • D — Visuell beschreiben statt Fachbegriff aneinanderreihen ("Roggenmischbrot" → "round dark rye-and-wheat loaf with crusty surface").
  • E — Farbe explizit nennen wo nicht offensichtlich ("Quark" → "white", "Sauerkraut" → "pale yellowish-white").

Prompter-LLM (Erzeugung des Bild-Prompts pro Item)

LLM Provider $/Prompt Verwurf-Grund
moonshotai/kimi-k2.6 OpenRouter ~$0.002 unnötiger Provider-Hop, OpenAI-Stack ohnehin nötig
gpt-5-mini OpenAI direkt ~$0.001 Sieger — günstiger und ein-Provider-Setup

reasoning_effort: "minimal" ist Pflicht — sonst rechnet die gpt-5-Familie hidden reasoning tokens für eine strukturierte Aufgabe, die kein Reasoning braucht (~5× teurer).

Background-Removal-Algorithmen

OpenAIs gpt-image-2 unterstützt background: "transparent" nicht (nur gpt-image-1/-1.5). Also Post-Processing nötig. Vier getestet auf den 20 Sieger-Bildern (in iterations/comparison.md mit pinkem Hintergrund visualisiert):

Algo Speed/Bild (CPU) 7140 Items Knäckebrot-Test Milchglas-Test
PIL Flood-Fill (kein ML) 5 ms ~1 min leichte Halos bei AA-Kanten
birefnet-general 17 s ~33 h ✗ komplett gegessen ok
isnet-general-use 1.2 s ~2.4 h leichte Halos
birefnet-massive 16 s ~32 h sauber, auch bei weißem Innen-Item

birefnet-massive gewinnt klar bei semantischer Trennung "Item vs. Hintergrund" — bricht weder bei tatsächlich weißen Vordergrund-Items (Quark, Milch, Hartkäse) noch bei dünnen Items (Knäckebrot) ein. Geschwindigkeit auf CPU ist zwar langsam, aber ein einmal-Vorgang.

Sync vs. Batch

OpenAI's Batch API gibt 50 % Rabatt auf alles, asynchron mit max. 24h Bearbeitungsfenster (in der Praxis 530 Min für die Größenordnung hier). Da der ganze Production-Lauf nicht echtzeitfähig sein muss, ist Batch ein no-brainer.


Vollständiger Vergleich

Alle 19 (Style × Image-Modell × Prompter)-Kombinationen plus die 4 Background-Removal-Algorithmen mit eingebetteten Bildern direkt im Repo sichtbar:

iterations/comparison.md

(Bilder sind 256-px-Thumbnails, vollauflösende Originale wurden für Repo-Größe nicht mitgeshippt — können via python3 generate.py mit dem zugehörigen Style neu generiert werden, Prompts liegen unter iterations/output/<style>/<sbls>/prompt.md.)


Layout

generate.py                Drei-Schritt-Pipeline (Submit + Fetch + Bg-Removal)
viewer.py                  Interaktiver HTML-Viewer (Drag-Drop-Sortierung, Lightbox)
data/
  sample_benchmark.py        Stratified random sample aus BLS xlsx
  benchmark_items.csv        20 Test-Items (Seed 42, getrackt)
style/
  comic_v4.md                Sieger-Style-Spec (verbindlich, unverändert)
output/                    Generierter Output (gitignored)
  comic_v4/<SBLS>/
    manifest.json
    prompt.md
    openai__gpt-image-2-low.png       finale Production-Datei (transparent)
    openai__gpt-image-2-low_raw.png   rohes API-PNG (mit weißem Hintergrund)
iterations/                Verworfene Stile + Vergleichsbilder als Doku (getrackt)
  README.md                  Erklärt das Iterationsmaterial
  comparison.md              Markdown-Viewer mit allen Iterations-Bildern
  build_comparison_md.py     Generator für comparison.md
  styles/                    7 verworfene Style-Specs (v1, v2, v3, v5v8)
  output/                    256-px-Thumbnails der Iteration-Bilder
  unbackground.py            Plan B (PIL Flood-Fill) — historisch
  unbackground_ml.py         Plan C+ (rembg, parametrisierbar) — historisch
  test_transparent.py        Test der OpenAI-nativen Alpha-Variante (failed)
  openai-prototype/          Erster fehlgeschlagener Photo-Studio-Versuch
LICENSE                    MIT
CLAUDE.md                  Architektur-Notizen für Claude Code (Tooling)

Lizenz

Code unter MIT (siehe LICENSE).

Die generierten Bilder selbst sind als kreatives Output von OpenAIs gpt-image-2 zu betrachten — siehe OpenAIs Terms of Use zur kommerziellen Verwendung.

Die zugrundeliegenden BLS-Item-Bezeichnungen stammen aus dem Bundeslebensmittelschlüssel 4.0 (Max Rubner-Institut, lizenzpflichtig). Die BLS-Quelldatei selbst (xlsx) ist nicht Teil dieses Repos — nur die 20 Benchmark-Item-Namen + SBLS-Codes sind in data/benchmark_items.csv enthalten, was unter dem Doktrin "kurze Identifikationsdaten zur Demonstration" fällt. Wer den vollen 7140-Item-Lauf durchführen möchte, braucht eine eigene BLS 4.0-Lizenz.