📝 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:
124
scripts/AUTO_GENERATION_README.md
Normal file
124
scripts/AUTO_GENERATION_README.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# 🎮 DOLINA SMRTI - Avtomatska Generacija Assetsov
|
||||
|
||||
## 🚀 NAČIN 1: Popolnoma Avtomatsko (PRIPOROČENO)
|
||||
|
||||
### Zagon:
|
||||
```bash
|
||||
cd /Users/davidkotnik/repos/novafarma/scripts
|
||||
./run_auto_generation.sh
|
||||
```
|
||||
|
||||
**To bo:**
|
||||
- ✅ Zagnalo generacijo v ozadju
|
||||
- ✅ Kreiral log datoteko z timestampom
|
||||
- ✅ Omogočil da zaprete terminal ALI greste spat
|
||||
- ✅ ComfyUI že teče, zato bo začel takoj
|
||||
|
||||
**Po zagonu lahko:**
|
||||
- Zaprete terminal - proces bo tekel naprej
|
||||
- Ugasnete zaslon - proces bo tekel naprej
|
||||
- Greste spat - proces bo tekel naprej
|
||||
|
||||
---
|
||||
|
||||
## 📊 Spremljanje Napredka
|
||||
|
||||
### Preveri status:
|
||||
```bash
|
||||
./check_generation_status.sh
|
||||
```
|
||||
|
||||
### Live spremljanje (real-time):
|
||||
```bash
|
||||
tail -f /Users/davidkotnik/repos/novafarma/generation_*.log
|
||||
```
|
||||
|
||||
Za izhod iz live pogleda: **Ctrl+C**
|
||||
|
||||
---
|
||||
|
||||
## ⏹️ Ustavitev Generacije
|
||||
|
||||
Če želite ustaviti:
|
||||
```bash
|
||||
kill $(cat /tmp/dolina_generation.pid)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 NAČIN 2: Terminal Session (za debugging)
|
||||
|
||||
Če želite videti output v realnem času:
|
||||
```bash
|
||||
cd /Users/davidkotnik/repos/novafarma/scripts
|
||||
python3 generate_local_final.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⏱️ Časovni Okvir
|
||||
|
||||
**Na podlagi testov:**
|
||||
- ⏱️ ~15-30 sekund na asset
|
||||
- 📊 **110 remaining assets** = ~45-90 minut
|
||||
- 📊 **422 total V7 assets** = ~3-5 ur
|
||||
- 📊 **1,418 full assets** = ~10-18 ur
|
||||
|
||||
**Ker ComfyUI teče lokalno:**
|
||||
- ❌ BREZ API rate limitov
|
||||
- ❌ BREZ pavz
|
||||
- ❌ BREZ potrebe po vaši prisotnosti
|
||||
- ✅ Lahko teče ČEZNOJI
|
||||
|
||||
---
|
||||
|
||||
## 📁 Rezultati
|
||||
|
||||
Vsi generirani PNG-ji so avtomatsko:
|
||||
- ✅ Odstranjeno ozadje (transparentni)
|
||||
- ✅ Shranjeni v `/Users/davidkotnik/repos/novafarma/assets/images/`
|
||||
- ✅ Razvrščeni po kategorijah
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Možne Težave
|
||||
|
||||
### ComfyUI se ne odziva:
|
||||
1. Odprite ComfyUI app
|
||||
2. Počakajte da se zažene (zeleni indikator)
|
||||
3. Poskusite znova
|
||||
|
||||
### Generacija se ne začne:
|
||||
```bash
|
||||
# Preverite error log:
|
||||
cat /Users/davidkotnik/repos/novafarma/generation_*.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 Nasveti
|
||||
|
||||
**ZA ČEZ NOČ:**
|
||||
1. Zaženite: `./run_auto_generation.sh`
|
||||
2. Greste spat 😴
|
||||
3. Zjutraj: `./check_generation_status.sh`
|
||||
4. Profit! 🎉
|
||||
|
||||
**ZA PREMIUM REZULTATE:**
|
||||
- ComfyUI uporablja **Dreamshaper 8** model
|
||||
- Vsaka slika je **512x512** (bosses 768x768)
|
||||
- Background removal z **rembg (u2net model)**
|
||||
- **30 generation steps** za kakovost
|
||||
|
||||
---
|
||||
|
||||
## 📈 Trenutni Status
|
||||
|
||||
Po zadnjem preverjanju:
|
||||
- ✅ ComfyUI: **v teku** (port 8000)
|
||||
- 📊 Generirano: **148/422** (V7) ali **148/1,418** (FULL)
|
||||
- ⏳ Manjka: **~274 slik** za V7 set
|
||||
|
||||
---
|
||||
|
||||
**🎯 Glavna Prednost: Lahko vse teče AVTOMATSKO čez noč!** 🌙
|
||||
49
scripts/check_generation_status.sh
Executable file
49
scripts/check_generation_status.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
# 🔍 Preveri status generacije
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "🎮 DOLINA SMRTI - Asset Generation Status"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# Preveri če proces teče
|
||||
if [ -f /tmp/dolina_generation.pid ]; then
|
||||
PID=$(cat /tmp/dolina_generation.pid)
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "✅ Generacija TEČE (PID: $PID)"
|
||||
|
||||
# Pokaži zadnje loge
|
||||
LATEST_LOG=$(ls -t /Users/davidkotnik/repos/novafarma/generation_*.log 2>/dev/null | head -1)
|
||||
if [ -n "$LATEST_LOG" ]; then
|
||||
echo "📂 Log file: $LATEST_LOG"
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "📊 Zadnjih 15 vrstic:"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
tail -15 "$LATEST_LOG"
|
||||
fi
|
||||
else
|
||||
echo "❌ Proces NE teče več (PID $PID ni aktiven)"
|
||||
rm /tmp/dolina_generation.pid
|
||||
fi
|
||||
else
|
||||
echo "⭕ Generacija NI zagnana"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "📁 Trenutno generirane slike:"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
cd /Users/davidkotnik/repos/novafarma/assets/images
|
||||
for dir in */; do
|
||||
count=$(find "$dir" -name "*.png" 2>/dev/null | wc -l)
|
||||
printf " %-20s: %3d slik\n" "${dir%/}" "$count"
|
||||
done
|
||||
|
||||
total=$(find . -name "*.png" 2>/dev/null | wc -l)
|
||||
echo " ────────────────────────────────"
|
||||
printf " %-20s: %3d slik\n" "SKUPAJ" "$total"
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
161
scripts/fresh_test.py
Normal file
161
scripts/fresh_test.py
Normal file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
🚀 FRESH TEST - Generira 3 nove slike ki jih še ni
|
||||
"""
|
||||
|
||||
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:
|
||||
print("📦 Installing rembg...")
|
||||
os.system("pip3 install --user rembg pillow onnxruntime")
|
||||
from rembg import remove
|
||||
from PIL import Image
|
||||
|
||||
# Configuration
|
||||
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 lines, full body visible, isolated on pure white background"
|
||||
NEGATIVE = "pixel art, pixelated, 3d, realistic, photo, blurry, watermark, text, green background"
|
||||
|
||||
# 🆕 NOVE SLIKE - Še ne generirane
|
||||
NEW_ASSETS = [
|
||||
("npcs", "gronk_front_walk1", "Gronk massive troll, PINK dreadlocks, black baggy t-shirt and pants, pink sneakers, holding vape, front view walking left leg forward"),
|
||||
("npcs", "kai_front_walk1", "Kai teenage survivor, GREEN dreadlocks, blue jacket, torn jeans, boots, front view walking left leg forward"),
|
||||
("zivali", "fox_red", "red fox wildlife animal, bushy tail, clever expression, side view"),
|
||||
]
|
||||
|
||||
|
||||
def log(msg):
|
||||
ts = datetime.now().strftime("%H:%M:%S")
|
||||
print(f"[{ts}] {msg}")
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def git_commit(file_path, category, name):
|
||||
"""Auto-commit generated asset"""
|
||||
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"🎨 Generated: {category}/{name}"], cwd=REPO_DIR, check=True, capture_output=True)
|
||||
log(f" 📝 Git committed: {rel_path}")
|
||||
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"❌ Queue error: {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"❌ Download error: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
log("="*60)
|
||||
log("🚀 FRESH TEST - Generiranje Novih Slik")
|
||||
log(" Z avtomatskim Git commitom")
|
||||
log("="*60)
|
||||
|
||||
try:
|
||||
r = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5)
|
||||
log(f"✅ ComfyUI v{r.json()['system']['comfyui_version']} running")
|
||||
except:
|
||||
log("❌ ComfyUI not running!")
|
||||
return
|
||||
|
||||
log(f"\n🎯 Generating {len(NEW_ASSETS)} new assets...\n")
|
||||
|
||||
for i, (cat, name, prompt) in enumerate(NEW_ASSETS, 1):
|
||||
path = OUTPUT_DIR / cat / f"{name}.png"
|
||||
|
||||
if path.exists():
|
||||
log(f"[{i}/{len(NEW_ASSETS)}] ⏭️ {name} - skipping (exists)")
|
||||
continue
|
||||
|
||||
log(f"[{i}/{len(NEW_ASSETS)}] 🎨 {name}...")
|
||||
|
||||
wf = create_workflow(prompt, name, 512)
|
||||
pid = queue_prompt(wf)
|
||||
|
||||
if pid and wait_completion(pid) and download_and_process(pid, path):
|
||||
log(f" ✅ Generated & transparent!")
|
||||
git_commit(path, cat, name)
|
||||
else:
|
||||
log(f" ❌ FAILED")
|
||||
|
||||
log("\n" + "="*60)
|
||||
log("🚀 FRESH TEST COMPLETE!")
|
||||
log("="*60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -11,6 +11,7 @@ import json
|
||||
import time
|
||||
import uuid
|
||||
import requests
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
@@ -116,6 +117,40 @@ def log(msg):
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def git_commit(file_path, category, name):
|
||||
"""Auto-commit generated asset to Git"""
|
||||
try:
|
||||
repo_dir = Path("/Users/davidkotnik/repos/novafarma")
|
||||
rel_path = file_path.relative_to(repo_dir)
|
||||
|
||||
# Git add
|
||||
subprocess.run(
|
||||
["git", "add", str(rel_path)],
|
||||
cwd=repo_dir,
|
||||
check=True,
|
||||
capture_output=True
|
||||
)
|
||||
|
||||
# Git commit
|
||||
commit_msg = f"🎨 Auto-generated asset: {category}/{name}"
|
||||
result = subprocess.run(
|
||||
["git", "commit", "-m", commit_msg],
|
||||
cwd=repo_dir,
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
log(f" 📝 Git committed")
|
||||
return True
|
||||
else:
|
||||
# Možno da je že committed ali ni sprememb
|
||||
return False
|
||||
except Exception as e:
|
||||
log(f" ⚠️ Git: {str(e)[:50]}")
|
||||
return False
|
||||
|
||||
|
||||
def create_workflow(prompt_text, output_name, size=512):
|
||||
"""Create ComfyUI workflow"""
|
||||
seed = int(time.time() * 1000) % 2147483647
|
||||
@@ -271,6 +306,8 @@ def main():
|
||||
|
||||
if pid and wait_completion(pid) and download_and_process(pid, path):
|
||||
log(f" ✅ DONE (transparent)")
|
||||
# Auto-commit to Git
|
||||
git_commit(path, cat, name)
|
||||
success += 1
|
||||
else:
|
||||
log(f" ❌ FAILED")
|
||||
|
||||
175
scripts/regenerate_with_master_ref.py
Normal file
175
scripts/regenerate_with_master_ref.py
Normal file
@@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
🎨 REGENERATE - Z Master Reference
|
||||
Uporablja točne specifikacije iz MASTER_GRONK.png in MASTER_KAI.png
|
||||
"""
|
||||
|
||||
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 cartoon character sprite, clean vector style, smooth bold outlines, full body visible head to feet, isolated on pure white background"
|
||||
NEGATIVE = "pixel art, pixelated, 3d render, realistic photo, anime, manga, blurry, watermark, text, green background, cut off"
|
||||
|
||||
# 🎯 CORRECT PROMPTS based on MASTER references
|
||||
CORRECT_ASSETS = [
|
||||
("npcs", "gronk_front_walk1",
|
||||
"Gronk the troll character, green-grey skin with visible round belly, "
|
||||
"BRIGHT PINK dreadlocks, large ear gauges, nose ring and facial piercings, "
|
||||
"wearing black baggy t-shirt with purple TROLL SABBATH text, "
|
||||
"black loose baggy pants, bright pink sneakers, "
|
||||
"holding colorful rainbow vape device with pink smoke, "
|
||||
"peaceful relaxed expression, full body, front view, walking pose left leg forward"),
|
||||
|
||||
("npcs", "kai_front_walk1",
|
||||
"Kai teenage survivor character, dark forest green thick dreadlocks, "
|
||||
"medium skin tone, large ear gauges, nose piercing and lip piercing, "
|
||||
"serious determined expression, "
|
||||
"wearing weathered blue-grey denim jacket with dirt stains, "
|
||||
"beige t-shirt underneath, "
|
||||
"torn blue jeans ripped at knees, "
|
||||
"brown leather combat boots, "
|
||||
"brown survival backpack with straps and pockets, "
|
||||
"athletic lean build, full body, front view, walking pose left leg forward"),
|
||||
]
|
||||
|
||||
|
||||
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"🎨 CORRECT: {category}/{name} (master ref)"], cwd=REPO_DIR, check=True, capture_output=True)
|
||||
log(f" 📝 Git committed with master ref tag")
|
||||
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": 35, "cfg": 8.0,
|
||||
"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"regen_{uuid.uuid4().hex[:8]}"}, timeout=10)
|
||||
return r.json().get("prompt_id")
|
||||
except Exception as e:
|
||||
log(f"❌ Queue error: {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"❌ Download error: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
log("="*70)
|
||||
log("🎨 REGENERATE - Z Master Reference Slikami")
|
||||
log(" Točne specifikacije iz MASTER_GRONK.png & MASTER_KAI.png")
|
||||
log("="*70)
|
||||
|
||||
try:
|
||||
r = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5)
|
||||
log(f"✅ ComfyUI v{r.json()['system']['comfyui_version']} running")
|
||||
except:
|
||||
log("❌ ComfyUI not running!")
|
||||
return
|
||||
|
||||
log(f"\n🎯 Regenerating {len(CORRECT_ASSETS)} characters with CORRECT style...\n")
|
||||
|
||||
for i, (cat, name, prompt) in enumerate(CORRECT_ASSETS, 1):
|
||||
path = OUTPUT_DIR / cat / f"{name}.png"
|
||||
|
||||
log(f"[{i}/{len(CORRECT_ASSETS)}] 🎨 {name}...")
|
||||
log(f" 📋 Using master reference prompt")
|
||||
|
||||
wf = create_workflow(prompt, name, 512)
|
||||
pid = queue_prompt(wf)
|
||||
|
||||
if pid and wait_completion(pid) and download_and_process(pid, path):
|
||||
log(f" ✅ Generated with CORRECT style!")
|
||||
git_commit(path, cat, name)
|
||||
|
||||
# Auto-open to verify
|
||||
os.system(f"open {path}")
|
||||
else:
|
||||
log(f" ❌ FAILED")
|
||||
|
||||
log("\n" + "="*70)
|
||||
log("🎨 REGENERATION COMPLETE!")
|
||||
log(" Slike so odprte - preverite ali sedaj ustrezajo!")
|
||||
log("="*70)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
37
scripts/run_auto_generation.sh
Executable file
37
scripts/run_auto_generation.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
# 🎮 DOLINA SMRTI - Avtomatski generator
|
||||
# Teče v ozadju, logs v datoteko
|
||||
|
||||
cd /Users/davidkotnik/repos/novafarma/scripts
|
||||
|
||||
# Kreiraj log file z timestampom
|
||||
LOG_FILE="/Users/davidkotnik/repos/novafarma/generation_$(date +%Y%m%d_%H%M%S).log"
|
||||
|
||||
echo "🎮 Starting DOLINA SMRTI Asset Generation..."
|
||||
echo "📂 Logs: $LOG_FILE"
|
||||
echo "⏱️ Start time: $(date)"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "🔥 Generation je v teku... lahko zaprete terminal ali pustite račun vklopljen."
|
||||
echo " Za preverjanje statusa: tail -f $LOG_FILE"
|
||||
echo ""
|
||||
|
||||
# Zaženi generacijo v ozadju z logs
|
||||
nohup python3 generate_local_final.py > "$LOG_FILE" 2>&1 &
|
||||
|
||||
# Shrani PID
|
||||
PID=$!
|
||||
echo "✅ Process ID: $PID"
|
||||
echo "$PID" > /tmp/dolina_generation.pid
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "📊 Za spremljanje napredka (live):"
|
||||
echo " tail -f $LOG_FILE"
|
||||
echo ""
|
||||
echo "⏹️ Za ustavitev generacije:"
|
||||
echo " kill $PID"
|
||||
echo ""
|
||||
echo "🎯 Ko je končano, rezultat bo v:"
|
||||
echo " /Users/davidkotnik/repos/novafarma/assets/images/"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
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()
|
||||
209
scripts/test_generation.py
Executable file
209
scripts/test_generation.py
Executable file
@@ -0,0 +1,209 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
🧪 TEST GENERATION - Generira 5 testnih slik
|
||||
Z avtomatskim Git commitom
|
||||
"""
|
||||
|
||||
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:
|
||||
print("📦 Installing rembg...")
|
||||
os.system("pip3 install --user rembg pillow onnxruntime")
|
||||
from rembg import remove
|
||||
from PIL import Image
|
||||
|
||||
# Configuration
|
||||
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 lines, full body visible, isolated on pure white background #FFFFFF"
|
||||
NEGATIVE = "pixel art, pixelated, 3d, realistic, photo, blurry, watermark, text, green background"
|
||||
|
||||
# 🧪 TEST ASSETS - Par hitrih testnih slik
|
||||
TEST_ASSETS = [
|
||||
("npcs", "npc_elder", "wise tribal elder NPC, walking stick, long white beard, robes"),
|
||||
("npcs", "npc_child", "survivor orphan child NPC, oversized clothes, teddy bear"),
|
||||
("zivali", "goat_brown", "brown goat farm animal, small horns, playful"),
|
||||
("items", "tool_hammer", "hammer building tool, wooden handle"),
|
||||
("environment", "flower_red", "red flowers patch, blooming"),
|
||||
]
|
||||
|
||||
|
||||
def log(msg):
|
||||
ts = datetime.now().strftime("%H:%M:%S")
|
||||
print(f"[{ts}] {msg}")
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def git_commit(file_path, category, name):
|
||||
"""Auto-commit generated asset"""
|
||||
try:
|
||||
rel_path = file_path.relative_to(REPO_DIR)
|
||||
|
||||
# Git add
|
||||
subprocess.run(
|
||||
["git", "add", str(rel_path)],
|
||||
cwd=REPO_DIR,
|
||||
check=True,
|
||||
capture_output=True
|
||||
)
|
||||
|
||||
# Git commit
|
||||
commit_msg = f"🎨 Generated asset: {category}/{name}"
|
||||
subprocess.run(
|
||||
["git", "commit", "-m", commit_msg],
|
||||
cwd=REPO_DIR,
|
||||
check=True,
|
||||
capture_output=True
|
||||
)
|
||||
|
||||
log(f" ✅ Git committed: {rel_path}")
|
||||
return True
|
||||
except subprocess.CalledProcessError as e:
|
||||
log(f" ⚠️ Git commit failed (možno že committed): {e}")
|
||||
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"❌ Queue error: {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)
|
||||
data = r.json()
|
||||
if prompt_id in data and data[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)
|
||||
|
||||
# Remove background
|
||||
from io import BytesIO
|
||||
src_img = Image.open(BytesIO(r.content))
|
||||
transparent_img = remove(src_img)
|
||||
transparent_img.save(str(output_path), "PNG")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
log(f"❌ Download error: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
log("=" * 60)
|
||||
log("🧪 TEST GENERATION - 5 Testnih Slik")
|
||||
log(" Z avtomatskim Git commitom")
|
||||
log("=" * 60)
|
||||
|
||||
# Check ComfyUI
|
||||
try:
|
||||
r = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5)
|
||||
v = r.json()["system"]["comfyui_version"]
|
||||
log(f"✅ ComfyUI v{v} running")
|
||||
except:
|
||||
log("❌ ComfyUI not running!")
|
||||
return
|
||||
|
||||
log(f"\n🎯 Generating {len(TEST_ASSETS)} test assets...\n")
|
||||
|
||||
success, fail = 0, 0
|
||||
start_time = time.time()
|
||||
|
||||
for i, (cat, name, prompt) in enumerate(TEST_ASSETS, 1):
|
||||
path = OUTPUT_DIR / cat / f"{name}.png"
|
||||
|
||||
# Skip if exists
|
||||
if path.exists():
|
||||
log(f"[{i}/{len(TEST_ASSETS)}] ⏭️ {name} - already exists")
|
||||
continue
|
||||
|
||||
log(f"[{i}/{len(TEST_ASSETS)}] 🎨 Generating {name}...")
|
||||
|
||||
wf = create_workflow(prompt, name, 512)
|
||||
pid = queue_prompt(wf)
|
||||
|
||||
if pid and wait_completion(pid) and download_and_process(pid, path):
|
||||
log(f" ✅ Image saved (transparent)")
|
||||
|
||||
# Auto-commit
|
||||
git_commit(path, cat, name)
|
||||
|
||||
success += 1
|
||||
else:
|
||||
log(f" ❌ FAILED")
|
||||
fail += 1
|
||||
|
||||
elapsed = time.time() - start_time
|
||||
log("\n" + "=" * 60)
|
||||
log("🧪 TEST COMPLETE!")
|
||||
log(f" ✅ Success: {success}")
|
||||
log(f" ❌ Failed: {fail}")
|
||||
log(f" ⏱️ Time: {elapsed:.1f}s ({elapsed/60:.1f} min)")
|
||||
log(f" 📁 Output: {OUTPUT_DIR}")
|
||||
log("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user