Implement Nova Farma S1 Max: Layered terrain, water mechanics, Y-sorting, and asset cleanup
This commit is contained in:
83
scripts/clean_and_resize_white.py
Normal file
83
scripts/clean_and_resize_white.py
Normal file
@@ -0,0 +1,83 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
import os
|
||||
import sys
|
||||
|
||||
def remove_white_bg_and_resize(path, target_width=None):
|
||||
if not os.path.exists(path):
|
||||
print(f"File not found: {path}")
|
||||
return
|
||||
|
||||
img = cv2.imread(path)
|
||||
if img is None:
|
||||
print(f"Error loading {path}")
|
||||
return
|
||||
|
||||
# Convert to RGBA
|
||||
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
|
||||
|
||||
# Threshold for white (allowing slight off-white/compression artifacts)
|
||||
# White is (255,255,255). Let's say anything > 240 in all channels.
|
||||
lower_white = np.array([240, 240, 240, 255])
|
||||
upper_white = np.array([255, 255, 255, 255])
|
||||
|
||||
# Create mask: looking for white pixels
|
||||
# Note: cv2.inRange checks ranges. For BGRA, A is 255.
|
||||
# However, input usually doesn't have A yet if loaded as BGR.
|
||||
# But we converted.
|
||||
|
||||
# Alternative: Grayscale thresholding is often safer for "almost white" backgrounds in illustrations
|
||||
gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
|
||||
# Create binary mask where white is 255, else 0
|
||||
_, mask = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY)
|
||||
|
||||
# Invert mask: We want to KEEP non-white.
|
||||
# Non-white = 0 in mask? No, thresholded white became 255.
|
||||
# So we invert.
|
||||
mask_inv = cv2.bitwise_not(mask)
|
||||
|
||||
# Morphological cleanup (remove small white specks inside object if necessary, or smooth edges)
|
||||
# For vector art, simple threshold usually works well.
|
||||
|
||||
# Assign new alpha channel
|
||||
b, g, r, a = cv2.split(img)
|
||||
# Use mask_inv as alpha
|
||||
final_img = cv2.merge((b, g, r, mask_inv))
|
||||
|
||||
# Crop to content (Trim transparent borders)
|
||||
coords = cv2.findNonZero(mask_inv)
|
||||
if coords is not None:
|
||||
x, y, w, h = cv2.boundingRect(coords)
|
||||
# Padding
|
||||
pad = 2
|
||||
x = max(0, x - pad)
|
||||
y = max(0, y - pad)
|
||||
w = min(final_img.shape[1] - x, w + 2*pad)
|
||||
h = min(final_img.shape[0] - y, h + 2*pad)
|
||||
final_img = final_img[y:y+h, x:x+w]
|
||||
|
||||
# Resize if target_width provided
|
||||
if target_width:
|
||||
h_curr, w_curr = final_img.shape[:2]
|
||||
if w_curr > target_width: # Only scale down
|
||||
ratio = target_width / w_curr
|
||||
new_h = int(h_curr * ratio)
|
||||
final_img = cv2.resize(final_img, (target_width, new_h), interpolation=cv2.INTER_AREA)
|
||||
print(f"Resized to {target_width}x{new_h}")
|
||||
|
||||
cv2.imwrite(path, final_img)
|
||||
print(f"Processed (Cleaned White BG + Trim): {path}")
|
||||
|
||||
TARGETS = {
|
||||
'assets/DEMO_FAZA1/UI/badge_purchase.png': 512,
|
||||
'assets/DEMO_FAZA1/UI/health_critical.png': 512,
|
||||
'assets/DEMO_FAZA1/VFX/toxic_fog.png': 512,
|
||||
'assets/DEMO_FAZA1/Environment/obstacle_thorns.png': 256,
|
||||
'assets/DEMO_FAZA1/Structures/foundation_concrete.png': 512,
|
||||
'assets/DEMO_FAZA1/Items/hay_drop_0.png': 128
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
base = os.getcwd()
|
||||
for rel, w in TARGETS.items():
|
||||
remove_white_bg_and_resize(os.path.join(base, rel), w)
|
||||
Reference in New Issue
Block a user