Image_alter / app.py
Lordecyhper's picture
Update app.py
d6469b6 verified
import gradio as gr
import numpy as np
from PIL import Image
def create_color_ghost(cover, reveal):
if cover is None or reveal is None:
return None
# 1. Ensure images are RGB
img1_raw = cover.convert('RGB')
img2_raw = reveal.convert('RGB')
# 2. Resize reveal to match cover
if img1_raw.size != img2_raw.size:
img2_raw = img2_raw.resize(img1_raw.size, Image.LANCZOS)
# 3. Convert to Float Arrays (0.0 - 1.0)
# This time we keep the 3 color channels (Height, Width, 3)
rgb1 = np.array(img1_raw, dtype=float) / 255.0
rgb2 = np.array(img2_raw, dtype=float) / 255.0
# 4. Create Grayscale copies just to calculate the Alpha Channel
# We use the luminance of the pixels to decide transparency
gray1 = np.mean(rgb1, axis=2)
gray2 = np.mean(rgb2, axis=2)
# 5. Squash the contrast (Math Trick)
# We squash the target values so they don't clip when we combine them
rgb1 = rgb1 * 0.5
rgb2 = 0.5 + (rgb2 * 0.5)
# We also squash the grayscale versions for the Alpha calculation
gray1 = gray1 * 0.5
gray2 = 0.5 + (gray2 * 0.5)
# 6. Calculate the Alpha Channel based on Luminance
# Formula: Alpha = 1 - Light_Image + Dark_Image
alpha = 1.0 - gray2 + gray1
# Clip alpha to avoid errors
alpha = np.clip(alpha, 0.001, 0.999)
# 7. Reconstruct the Color Output
# We define the pixel color based on the "Dark Background" version (rgb1)
# P = Target / Alpha
# We have to reshape alpha to (H, W, 1) so we can divide the RGB array (H, W, 3) by it
alpha_3d = alpha[:, :, np.newaxis]
out_rgb = np.divide(rgb1, alpha_3d, out=np.zeros_like(rgb1), where=alpha_3d > 0.001)
# 8. Convert back to 0-255 Integers
final_rgb_int = (out_rgb * 255).clip(0, 255).astype(np.uint8)
final_alpha_int = (alpha * 255).clip(0, 255).astype(np.uint8)
# 9. Stack them into an RGBA Image
# Concatenate the Color channels with the Alpha channel
rgba_data = np.dstack((final_rgb_int, final_alpha_int))
return Image.fromarray(rgba_data, 'RGBA')
# --- Gradio UI ---
with gr.Blocks(title="Color Ghost Generator") as demo:
gr.Markdown("# 👻 Color Ghost Image Generator")
gr.Markdown("Create a magic image that changes when clicked (Supports Color).")
with gr.Row():
with gr.Column():
img_dark = gr.Image(type="pil", label="Image seen in DARK Mode (Cover)")
img_light = gr.Image(type="pil", label="Image seen in LIGHT Mode (Reveal)")
btn = gr.Button("Generate Ghost", variant="primary")
with gr.Column():
output_img = gr.Image(label="Result (Download to test)", type="pil")
btn.click(fn=create_color_ghost, inputs=[img_dark, img_light], outputs=output_img)
demo.launch()