96 lines
4.0 KiB
Python
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)
|