mostlycached's picture
Update app.py
2023379 verified
import gradio as gr
import numpy as np
import PIL.Image as Image
from rembg import remove
from PIL import ImageDraw, ImageFont
import textwrap
# Function to remove background and place text behind person
def text_behind_image(input_image, text, text_color, font_size, text_opacity):
if input_image is None or text.strip() == "":
return input_image
# Convert color hex to RGB
try:
r = int(text_color[1:3], 16)
g = int(text_color[3:5], 16)
b = int(text_color[5:7], 16)
text_color_rgb = (r, g, b)
except:
text_color_rgb = (0, 0, 0) # Default to black
try:
# Open the image
img = Image.fromarray(input_image)
# Get dimensions
width, height = img.size
# Step 1: Extract the person from the image
try:
# Try to use the human segmentation model first
person_only = remove(img, model_name="u2net_human_seg")
except:
# Fallback to default model if human_seg not available
person_only = remove(img)
# Step 2: Create a mask from the person cutout
person_mask = Image.new('RGBA', (width, height), (0, 0, 0, 0))
person_mask.paste(person_only, (0, 0), person_only)
# Step 3: Extract the background (original image without the person)
# Create inverted mask (where the person is black, background is white)
inverted_mask = Image.new('L', (width, height), 255)
inverted_mask.paste(0, (0, 0), person_only)
# Extract just the background
background = img.copy()
background.putalpha(inverted_mask)
# Step 4: Create the text layer
text_layer = Image.new('RGBA', (width, height), (0, 0, 0, 0))
draw = ImageDraw.Draw(text_layer)
# Prepare the text
text = text.strip().upper()
if not text:
text = "SAMPLE TEXT"
# Set up the font size - make it larger since we're just placing it once
font_size = max(20, int(min(width, height) * (font_size / 100)))
# Try several fonts
font = None
try:
font_paths = [
"arial.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
"/usr/share/fonts/truetype/freefont/FreeSansBold.ttf"
]
for font_path in font_paths:
try:
font = ImageFont.truetype(font_path, font_size)
break
except:
continue
except:
pass
if font is None:
font = ImageFont.load_default()
# Get text dimensions
# Try to use getbbox first for newer PIL versions
try:
text_width = font.getbbox(text)[2] - font.getbbox(text)[0]
text_height = font.getbbox(text)[3] - font.getbbox(text)[1]
except:
# Fallback for older PIL versions
try:
text_width = font.getsize(text)[0]
text_height = font.getsize(text)[1]
except:
# Second fallback - estimate size
text_width = len(text) * (font_size * 0.6)
text_height = font_size * 1.2
# Position in the upper middle section
# Divide the image into a 3x3 grid and put the text in the top-center cell
grid_width = width // 3
grid_height = height // 3
# Center horizontally in the middle third
x_center = width // 2 - text_width // 2
# Position vertically in the top third
y_top = grid_height // 2 - text_height // 2
# Draw the text with specified opacity and color
draw.text((x_center, y_top), text, font=font, fill=text_color_rgb + (int(text_opacity * 255),))
# Step 5: Composite all layers together
# First, composite the text on top of the background
background_with_text = Image.alpha_composite(background, text_layer)
# Then, composite the person on top
final_image = Image.alpha_composite(background_with_text, person_mask)
# Convert to RGB for display
return np.array(final_image.convert('RGB'))
except Exception as e:
print(f"Error processing image: {e}")
return input_image # Return original image on error
# Create Gradio interface
with gr.Blocks(title="Text Behind Image") as demo:
gr.Markdown("# Text Behind Image")
gr.Markdown("Upload an image with a person and add text behind them")
with gr.Row():
with gr.Column():
input_image = gr.Image(label="Upload Image", type="numpy")
text_input = gr.Textbox(label="Text to place behind", placeholder="Enter text here...")
with gr.Row():
text_color = gr.ColorPicker(label="Text Color", value="#000000")
font_size = gr.Slider(label="Font Size (%)", minimum=1, maximum=30, value=10, step=1)
text_opacity = gr.Slider(label="Text Opacity", minimum=0.1, maximum=1.0, value=0.8, step=0.1)
submit_btn = gr.Button("Generate", variant="primary")
with gr.Column():
output_image = gr.Image(label="Result", type="numpy")
submit_btn.click(
fn=text_behind_image,
inputs=[input_image, text_input, text_color, font_size, text_opacity],
outputs=output_image
)
gr.Markdown("## How it works")
gr.Markdown("1. Upload an image with a person")
gr.Markdown("2. Enter the text you want to place behind the person")
gr.Markdown("3. Customize text color, size, and opacity")
gr.Markdown("4. Click 'Generate' to create your image")
# Launch the app
demo.launch()