Spaces:
Build error
Build error
File size: 4,288 Bytes
70fb032 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
import gradio as gr
import numpy as np
import io
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:
return None
# 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 = (255, 255, 255) # Default to white
try:
# Open the image
img = Image.fromarray(input_image)
# Get dimensions
width, height = img.size
# Create a new image with white background (this will be the canvas)
background = Image.new('RGBA', (width, height), (255, 255, 255, 255))
# Create a drawing context for the text
draw = ImageDraw.Draw(background)
# Determine font size (relative to image size)
font_size = int(min(width, height) * (font_size / 100)) # Convert percentage to actual size
# Try to load a nice font, fall back to default if not available
try:
font = ImageFont.truetype("arial.ttf", font_size)
except:
font = ImageFont.load_default()
# Word wrap the text to fit within the image width
margin = 20
wrapper = textwrap.TextWrapper(width=int(width/font_size*2) - 2*margin)
word_list = wrapper.wrap(text)
# Calculate text block height
text_height = len(word_list) * (font_size + 10)
# Position text in the center
y_text = (height - text_height) // 2
# Draw text with specified opacity
for line in word_list:
# Get line width
line_width = font.getbbox(line)[2] - font.getbbox(line)[0]
# Center the line
x_text = (width - line_width) // 2
# Draw text with specified opacity
text_color_with_opacity = text_color_rgb + (int(text_opacity * 255),)
draw.text((x_text, y_text), line, font=font, fill=text_color_with_opacity)
y_text += font_size + 10
# Remove background from the original image to get the person silhouette
person_img = remove(img)
# Composite the images: text in background, then person on top
final_image = Image.alpha_composite(background.convert('RGBA'), person_img.convert('RGBA'))
# Convert back 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="#FFFFFF")
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()
|