Files
novafarma/scripts/utils/final_decheckerboard.py
2026-01-25 12:20:50 +01:00

96 lines
4.0 KiB
Python

import os
import numpy as np
from PIL import Image
def remove_checkerboard(image_path, sensitivity=20):
try:
if not os.path.exists(image_path):
print(f"File not found: {image_path}")
return
print(f"Processing: {image_path}")
img = Image.open(image_path).convert("RGBA")
data = np.array(img)
# Get dimensions
height, width = data.shape[:2]
# 1. SAMPLE BACKGROUND COLORS FROM CORNERS
# We assume corners are background. We'll take a 10x10 patch from top-left.
corner_patch = data[0:10, 0:10]
# Find unique colors in the corner (likely the two checkerboard colors)
unique_colors = np.unique(corner_patch.reshape(-1, 4), axis=0)
# We also manually add standard checkerboard colors just in case corners are weird
# Light grey, Dark grey, White
standard_bg_colors = [
[255, 255, 255], # White
[204, 204, 204], # Light Grey
[238, 238, 238], # Lighter Grey
[192, 192, 192], # Classic Grey
[128, 128, 128], # Darker Grey
[0, 0, 0] # Black (if user mentioned black earlier)
]
# Create a boolean mask for transparency (Starts as False = Keep)
to_remove = np.zeros((height, width), dtype=bool)
r, g, b = data[:,:,0], data[:,:,1], data[:,:,2]
# Helper to match color with tolerance
def match_color(target_rgb, tol):
return (np.abs(r - target_rgb[0]) < tol) & \
(np.abs(g - target_rgb[1]) < tol) & \
(np.abs(b - target_rgb[2]) < tol)
# Mark pixels matching sampled corner colors
for color in unique_colors:
# Ignore if alpha is already 0
if color[3] == 0: continue
to_remove |= match_color(color[:3], sensitivity)
# Mark pixels matching standard checkerboard colors
for bg_c in standard_bg_colors:
to_remove |= match_color(bg_c, sensitivity)
# APPLY MASK
# Set alpha to 0 where mask is True
data[to_remove, 3] = 0
# SPECIAL CASE: AMNESIA MASK
# If it's the mask/vignette, we might need to inverted logic or specific handling?
# User said "through the holes in the rusty frame".
# If the frame has a solid checkerboard INSIDE the frame, we need to nuke that too.
# The logic above replaces ALL instances of those colors.
# This is risky if the object itself uses grey/white.
# BUT for "Rusty" (brown/orange) and "Health Gauge" (brown/red), grey/white is safe to remove.
# "Start Button" has white text... "match_color" might kill the text!
# REFINEMENT: MASKING
# We only remove if it touches the "outside" or is part of the large background blocks.
# But implementing full floodfill in numpy is hard.
# Let's hope the "Rusty" colors distinct enough from "Pure Grey/White".
# Save
result = Image.fromarray(data)
result.save(image_path)
print(f"Saved cleaned: {image_path}")
except Exception as e:
print(f"Error processing {image_path}: {e}")
# PATHS TO FIX
files_to_fix = [
"/Users/davidkotnik/repos/novafarma/assets/slike/NOVE_SLIKE/UI/okvir_zarjavel.png",
"/Users/davidkotnik/repos/novafarma/assets/slike/NOVE_SLIKE/UI/merilec_zdravja.png",
"/Users/davidkotnik/repos/novafarma/assets/slike/NOVE_SLIKE/UI/amnezija_maska.png",
"/Users/davidkotnik/repos/novafarma/assets/slike/NOVE_SLIKE/UI/gumb_start.png",
# Also cleaning the ghosts as requested
"/Users/davidkotnik/repos/novafarma/assets/slike/NOVE_SLIKE/Characters/starsa/Ghost/ghost_otac_cyan.png",
"/Users/davidkotnik/repos/novafarma/assets/slike/NOVE_SLIKE/Characters/starsa/Ghost/MOJE_SLIKE_KONCNA_ostalo_parents_transparent_ghosts_clean.png"
]
for f in files_to_fix:
remove_checkerboard(f, sensitivity=25)