Complete Faza 1&2 Status + Batch Visual Cleanup

- Created comprehensive FAZA1_GENERATION_STATUS.md with 10 categories tracking 176 tasks
- Auto-sync system for real-time progress updates
- Batch cleanup: 1411 images scanned across references/, assets/, style_test_samples/
- 33 backgrounds removed total (24 previous + 9 new)
- Updated ROADMAP.md: Visual Cleanup  Complete
- Script: batch_cleanup_all_assets.py for automated processing
- Critical path identified: 17 tasks (60-80h) to Kickstarter Demo ready
This commit is contained in:
2026-01-05 12:08:24 +01:00
parent 1221e78492
commit 3ca2cd7f86
12 changed files with 534 additions and 104 deletions

View File

@@ -0,0 +1,182 @@
#!/usr/bin/env python3
"""
BATCH VISUAL ASSET CLEANUP
Removes backgrounds from ALL image assets in the project.
Processes: /references/, /assets/, /style_test_samples/
Features:
- Multi-folder scanning
- Chroma keying (green #00FF00 removal)
- Smart detection of already transparent images
- Progress tracking
- Automatic _nobg.png generation
"""
import os
from PIL import Image
import numpy as np
from pathlib import Path
# Configuration
SEARCH_FOLDERS = [
'references',
'assets/images',
'assets/bugs',
'assets/tools',
'assets/crops',
'assets/buildings',
'assets/characters',
'assets/enemies',
'assets/npcs',
'style_test_samples'
]
GREEN_KEY = (0, 255, 0) # #00FF00
TOLERANCE = 30 # Color variance tolerance
def has_transparency(image):
"""Check if image already has transparent pixels"""
if image.mode != 'RGBA':
return False
alpha = np.array(image)[:, :, 3]
return np.any(alpha < 255)
def remove_green_background(image_path, output_path):
"""Remove green chroma key background and save as transparent PNG"""
try:
img = Image.open(image_path).convert('RGBA')
data = np.array(img)
# Check if already transparent
if has_transparency(img):
print(f" ⏭️ Already transparent: {os.path.basename(image_path)}")
return False
# Extract RGB channels
red, green, blue, alpha = data[:, :, 0], data[:, :, 1], data[:, :, 2], data[:, :, 3]
# Create mask for green pixels (with tolerance)
mask = (
(np.abs(red.astype(int) - GREEN_KEY[0]) <= TOLERANCE) &
(np.abs(green.astype(int) - GREEN_KEY[1]) <= TOLERANCE) &
(np.abs(blue.astype(int) - GREEN_KEY[2]) <= TOLERANCE)
)
# Check if green background exists
green_pixel_count = np.sum(mask)
if green_pixel_count == 0:
print(f" No green background: {os.path.basename(image_path)}")
return False
# Set alpha to 0 for green pixels
data[:, :, 3] = np.where(mask, 0, 255)
# Save as transparent PNG
result = Image.fromarray(data, 'RGBA')
result.save(output_path, 'PNG')
percentage = (green_pixel_count / (data.shape[0] * data.shape[1])) * 100
print(f" ✅ Processed: {os.path.basename(image_path)} ({percentage:.1f}% background removed)")
return True
except Exception as e:
print(f" ❌ ERROR: {os.path.basename(image_path)} - {e}")
return False
def scan_and_process(base_dir):
"""Scan all configured folders and process images"""
stats = {
'total_found': 0,
'processed': 0,
'skipped_transparent': 0,
'skipped_no_green': 0,
'errors': 0
}
print("🔍 SCANNING FOR IMAGES...\n")
for folder in SEARCH_FOLDERS:
folder_path = os.path.join(base_dir, folder)
if not os.path.exists(folder_path):
print(f"⏭️ Skipping (not found): {folder}")
continue
print(f"\n📁 Processing: {folder}/")
print("=" * 60)
# Find all image files
image_files = []
for ext in ['*.png', '*.jpg', '*.jpeg']:
image_files.extend(Path(folder_path).rglob(ext))
folder_stats = {
'found': len(image_files),
'processed': 0
}
for img_path in sorted(image_files):
# Skip already processed files
if '_nobg' in img_path.stem:
continue
stats['total_found'] += 1
# Generate output filename
output_path = img_path.parent / f"{img_path.stem}_nobg.png"
# Skip if already exists
if output_path.exists():
print(f" ⏭️ Already exists: {output_path.name}")
stats['skipped_transparent'] += 1
continue
# Process the image
result = remove_green_background(str(img_path), str(output_path))
if result:
stats['processed'] += 1
folder_stats['processed'] += 1
elif result is False:
# Check reason from function output
stats['skipped_no_green'] += 1
print(f"\n📊 Folder Summary: {folder_stats['processed']}/{folder_stats['found']} processed")
return stats
def main():
"""Main execution"""
print("=" * 60)
print("🎨 BATCH VISUAL ASSET CLEANUP")
print("=" * 60)
print(f"Target folders: {len(SEARCH_FOLDERS)}")
print(f"Chroma key: RGB{GREEN_KEY} ±{TOLERANCE}")
print("=" * 60)
# Get project root
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(script_dir)
# Process all folders
stats = scan_and_process(project_root)
# Final report
print("\n" + "=" * 60)
print("📊 FINAL REPORT")
print("=" * 60)
print(f"Total images found: {stats['total_found']}")
print(f"✅ Successfully processed: {stats['processed']}")
print(f"⏭️ Already transparent: {stats['skipped_transparent']}")
print(f" No green background: {stats['skipped_no_green']}")
print(f"❌ Errors: {stats['errors']}")
print("=" * 60)
if stats['processed'] > 0:
print(f"\n✅ CLEANUP COMPLETE! {stats['processed']} backgrounds removed.")
else:
print("\n✅ All images already clean!")
if __name__ == "__main__":
main()