mostlycached's picture
Update app.py
2023379 verified
raw
history blame
6.02 kB
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()