Alex Hortua
Adding new documentation for thisprocess
6eb4ed6
import gradio as gr
import numpy as np
from PIL import Image
from utils import load_model, segment_person, resize_image, split_stereo_image,resize_image_to_width, resize_mask, resize_images
from testing import get_image_names
# Load model and processor once
processor, model = load_model()
# Default background (solid color)
default_bg = Image.new("RGB", (512, 512), color=(95, 147, 89))
def generate_3d_outputs(person_img, background_img=None, shift_pixels=10, person_size=100):
# Resize images to match
background_img = background_img if background_img is not None else default_bg
# Split background image into left and right halves
leftBackground, rightBackground = split_stereo_image(Image.fromarray(background_img))
## Match person image to background image width
image = resize_image_to_width(person_img, leftBackground)
# Step 1: Segment person
mask = segment_person(image, processor, model)
# Resize mask based on person_size percentage
mask = resize_mask(person_size, mask)
# Resize image based on person_size percentage
image_np = resize_images(image, person_size)
# Apply mask to image
person_only = image_np * mask
person_segmentation = np.clip(person_only, 0, 255).astype(np.uint8)
# Resize mask and person_only to match background dimensions while preserving content
target_height, target_width = leftBackground.shape[:2]
current_height, current_width = mask.shape[:2]
# Calculate padding
pad_top = max(0, (target_height - current_height) // 2)
pad_bottom = max(0, target_height - current_height - pad_top)
pad_left = max(0, (target_width - current_width) // 2)
pad_right = max(0, target_width - current_width - pad_left)
# Pad mask and person_only arrays
mask = np.pad(mask, ((pad_top, pad_bottom), (pad_left, pad_right), (0,0)), mode='constant')
person_only = np.pad(person_segmentation, ((pad_top, pad_bottom), (pad_left, pad_right), (0,0)), mode='constant')
# CROP MASK TO MATCH BACKGROUND DIMENSIONS FROM CENTER OF BACKGROUND
if(mask.shape[0] > target_height or mask.shape[1] > target_width):
mask = mask[mask.shape[0]//2-target_height//2:mask.shape[0]//2+target_height//2, mask.shape[1]//2-target_width//2:mask.shape[1]//2+target_width//2, :]
person_only = person_only[person_only.shape[0]//2-target_height//2:person_only.shape[0]//2+target_height//2, person_only.shape[1]//2-target_width//2:person_only.shape[1]//2+target_width//2, :]
# Convert background images to numpy arrays
leftBackground_np = np.array(leftBackground)
rightBackground_np = np.array(rightBackground)
# Apply mask to background images
leftBackground_only = leftBackground_np * (1 - mask)
rightBackground_only = rightBackground_np * (1 - mask)
# Step 2: Create stereo pair
person_left = np.roll(person_only, shift=-shift_pixels, axis=1)
person_right = np.roll(person_only, shift=shift_pixels, axis=1)
left_eye = np.clip(person_right + leftBackground_only, 0, 255).astype(np.uint8)
right_eye = np.clip(person_left + rightBackground_only, 0, 255).astype(np.uint8)
# --- Combine left and right images side by side ---
stereo_pair = np.concatenate([left_eye, right_eye], axis=1)
stereo_image = Image.fromarray(stereo_pair)
# Step 3: Create anaglyph
anaglyph = np.stack([
left_eye[:, :, 0], # Red from left
right_eye[:, :, 1], # Green from right
right_eye[:, :, 2] # Blue from right
], axis=2)
anaglyph_img = Image.fromarray(anaglyph.astype(np.uint8))
left_img = Image.fromarray(left_eye)
right_img = Image.fromarray(right_eye)
return person_segmentation, stereo_image, anaglyph_img
# Gradio Interface
demo = gr.Interface(
fn=generate_3d_outputs,
inputs=[
gr.Image(label="Person Image"),
gr.Image(label="Optional Background Image"),
gr.Slider(minimum=0, maximum=20, step=1, value=10, label="interaxial distance"),
gr.Slider(minimum=10, maximum=200, step=10, value=100, label="Person Size %"),
],
outputs=[
gr.Image(label="segmentation mask"),
gr.Image(label="Stereo_pair"),
gr.Image(label="3D Anaglyph Image")
],
examples= get_image_names(),
title="3D Person Segmentation Viewer",
description="Upload a person photo and optionally a background image. Outputs anaglyph and stereo views."
)
if __name__ == "__main__":
demo.launch()