📝 Nočna Session Setup - Asset Generation Infrastructure
- Created overnight generation system
- Added master character references (Gronk, Kai)
- Implemented auto-commit for all generated assets
- Created comprehensive documentation and changelogs
- Setup FULL generator (850+ assets without NPCs)
- Added progress tracking and status check scripts
Ready for overnight mass generation 🌙
This commit is contained in:
201
scripts/test_category_samples.py
Normal file
201
scripts/test_category_samples.py
Normal file
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
🧪 CATEGORY TEST SAMPLES
|
||||
Po 1 stvar iz vsake kategorije - kvalitetni check pred množično generacijo
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
import requests
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
from rembg import remove
|
||||
from PIL import Image
|
||||
except ImportError:
|
||||
os.system("pip3 install --user rembg pillow onnxruntime")
|
||||
from rembg import remove
|
||||
from PIL import Image
|
||||
|
||||
COMFYUI_URL = "http://127.0.0.1:8000"
|
||||
OUTPUT_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/images")
|
||||
REPO_DIR = Path("/Users/davidkotnik/repos/novafarma")
|
||||
|
||||
STYLE = "2D indie game sprite, cartoon vector style, clean smooth outlines, full body visible, isolated on pure white background"
|
||||
NEGATIVE = "pixel art, pixelated, 3d render, realistic photo, anime, blurry, watermark, text, green background"
|
||||
|
||||
# 🧪 TEST SAMPLES - Po 1 iz vsake kategorije (BREZ NPCs!)
|
||||
TEST_SAMPLES = [
|
||||
# Živali
|
||||
("zivali", "rabbit_white", "white rabbit animal, long ears, fluffy tail, cute, side view"),
|
||||
|
||||
# Bosses
|
||||
("bosses", "boss_dragon_ice", "Ice Dragon boss, massive blue dragon, frost breath, ice scales, menacing, full body"),
|
||||
|
||||
# Items - Tool
|
||||
("items", "tool_pickaxe_iron", "iron pickaxe tool, metal head, wooden handle, mining equipment"),
|
||||
|
||||
# Items - Weapon
|
||||
("items", "weapon_bow_wood", "wooden bow with arrow, hunting weapon, medieval style"),
|
||||
|
||||
# Items - Magic
|
||||
("items", "wand_lightning", "lightning magic wand, yellow crystal tip, electric sparks, glowing"),
|
||||
|
||||
# Items - Potion
|
||||
("items", "potion_mana", "mana potion, blue liquid in glass bottle, magical glow"),
|
||||
|
||||
# Items - Food
|
||||
("items", "food_bread", "bread loaf, fresh baked, brown crust, artisan style"),
|
||||
|
||||
# Environment - Tree
|
||||
("environment", "tree_pine", "pine tree, evergreen, cone shaped, forest tree, full tree"),
|
||||
|
||||
# Environment - Object
|
||||
("environment", "barrel_wood", "wooden storage barrel, medieval style, brown wood"),
|
||||
|
||||
# Mutanti
|
||||
("mutanti", "slime_purple", "purple poison slime monster, bouncing blob, toxic bubbles"),
|
||||
]
|
||||
|
||||
|
||||
def log(msg):
|
||||
ts = datetime.now().strftime("%H:%M:%S")
|
||||
print(f"[{ts}] {msg}")
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def git_commit(file_path, category, name):
|
||||
try:
|
||||
rel_path = file_path.relative_to(REPO_DIR)
|
||||
subprocess.run(["git", "add", str(rel_path)], cwd=REPO_DIR, check=True, capture_output=True)
|
||||
subprocess.run(["git", "commit", "-m", f"🧪 Test sample: {category}/{name}"], cwd=REPO_DIR, check=True, capture_output=True)
|
||||
log(f" 📝 Committed")
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
def create_workflow(prompt_text, output_name, size=512):
|
||||
seed = int(time.time() * 1000) % 2147483647
|
||||
full_prompt = f"{STYLE}, {prompt_text}"
|
||||
|
||||
return {
|
||||
"1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "dreamshaper_8.safetensors"}},
|
||||
"2": {"class_type": "EmptyLatentImage", "inputs": {"width": size, "height": size, "batch_size": 1}},
|
||||
"3": {"class_type": "CLIPTextEncode", "inputs": {"text": full_prompt, "clip": ["1", 1]}},
|
||||
"4": {"class_type": "CLIPTextEncode", "inputs": {"text": NEGATIVE, "clip": ["1", 1]}},
|
||||
"5": {
|
||||
"class_type": "KSampler",
|
||||
"inputs": {
|
||||
"seed": seed, "steps": 30, "cfg": 7.5,
|
||||
"sampler_name": "euler_ancestral", "scheduler": "karras",
|
||||
"denoise": 1.0, "model": ["1", 0],
|
||||
"positive": ["3", 0], "negative": ["4", 0], "latent_image": ["2", 0]
|
||||
}
|
||||
},
|
||||
"6": {"class_type": "VAEDecode", "inputs": {"samples": ["5", 0], "vae": ["1", 2]}},
|
||||
"7": {"class_type": "SaveImage", "inputs": {"filename_prefix": output_name, "images": ["6", 0]}}
|
||||
}
|
||||
|
||||
|
||||
def queue_prompt(workflow):
|
||||
try:
|
||||
r = requests.post(f"{COMFYUI_URL}/prompt", json={"prompt": workflow, "client_id": f"test_{uuid.uuid4().hex[:8]}"}, timeout=10)
|
||||
return r.json().get("prompt_id")
|
||||
except Exception as e:
|
||||
log(f"❌ {e}")
|
||||
return None
|
||||
|
||||
|
||||
def wait_completion(prompt_id, timeout=120):
|
||||
start = time.time()
|
||||
while time.time() - start < timeout:
|
||||
try:
|
||||
r = requests.get(f"{COMFYUI_URL}/history/{prompt_id}", timeout=5)
|
||||
if prompt_id in r.json() and r.json()[prompt_id].get("outputs"):
|
||||
return True
|
||||
except:
|
||||
pass
|
||||
time.sleep(2)
|
||||
return False
|
||||
|
||||
|
||||
def download_and_process(prompt_id, output_path):
|
||||
try:
|
||||
h = requests.get(f"{COMFYUI_URL}/history/{prompt_id}").json()
|
||||
for out in h.get(prompt_id, {}).get("outputs", {}).values():
|
||||
for img in out.get("images", []):
|
||||
r = requests.get(f"{COMFYUI_URL}/view", params={"filename": img["filename"], "subfolder": img.get("subfolder", ""), "type": "output"})
|
||||
if r.status_code == 200:
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
from io import BytesIO
|
||||
transparent_img = remove(Image.open(BytesIO(r.content)))
|
||||
transparent_img.save(str(output_path), "PNG")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
log(f"❌ {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
log("="*70)
|
||||
log("🧪 CATEGORY TEST SAMPLES")
|
||||
log(" Po 1 iz vsake kategorije - kvalitetni check")
|
||||
log(" NPCs IZKLJUČENI iz avtomatike!")
|
||||
log("="*70)
|
||||
|
||||
try:
|
||||
r = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5)
|
||||
log(f"✅ ComfyUI v{r.json()['system']['comfyui_version']}")
|
||||
except:
|
||||
log("❌ ComfyUI not running!")
|
||||
return
|
||||
|
||||
log(f"\n🎯 Generating {len(TEST_SAMPLES)} test samples...\n")
|
||||
|
||||
success = 0
|
||||
|
||||
for i, (cat, name, prompt) in enumerate(TEST_SAMPLES, 1):
|
||||
path = OUTPUT_DIR / cat / f"{name}.png"
|
||||
|
||||
if path.exists():
|
||||
log(f"[{i}/{len(TEST_SAMPLES)}] ⏭️ {name} - exists")
|
||||
continue
|
||||
|
||||
log(f"[{i}/{len(TEST_SAMPLES)}] 🎨 {cat}/{name}")
|
||||
|
||||
size = 768 if cat == "bosses" else 512
|
||||
wf = create_workflow(prompt, name, size)
|
||||
pid = queue_prompt(wf)
|
||||
|
||||
if pid and wait_completion(pid) and download_and_process(pid, path):
|
||||
log(f" ✅ Done!")
|
||||
git_commit(path, cat, name)
|
||||
success += 1
|
||||
|
||||
# Open image immediately for review
|
||||
os.system(f"open {path}")
|
||||
else:
|
||||
log(f" ❌ Failed")
|
||||
|
||||
# Brief pause between generations
|
||||
if i < len(TEST_SAMPLES):
|
||||
time.sleep(2)
|
||||
|
||||
log("\n" + "="*70)
|
||||
log(f"🧪 TEST SAMPLES COMPLETE! ({success}/{len(TEST_SAMPLES)})")
|
||||
log(" Slike so odprte - preverite kakovost!")
|
||||
log("="*70)
|
||||
log("\n💡 Če je kakovost OK → lahko zaženem VSE ostale")
|
||||
log(" (items, environment, animals, bosses, mutants)")
|
||||
log(" NPCs ostanejo ROČNO!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user