Tonic's picture
fixes 500 error for some users
144ab4f verified
raw
history blame
7.6 kB
import gradio as gr
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import os
from PIL import Image
from gradio_client import Client, handle_file
import uuid
client = Client("ysharma/BiRefNet_for_text_writing")
def add_text_with_stroke(draw, text, x, y, font, text_color, stroke_width):
"""Helper function to draw text with stroke"""
# Draw the stroke/outline
for adj_x in range(-stroke_width, stroke_width + 1):
for adj_y in range(-stroke_width, stroke_width + 1):
draw.text((x + adj_x, y + adj_y), text, font=font, fill=text_color)
def remove_background(image):
# Save the image to a specific location
filename = f"image_{uuid.uuid4()}.png" # Generates a universally unique identifier (UUID) for the filename
image.save(filename)
# Call gradio client for background removal
result = client.predict(images=handle_file(filename), api_name="/image")
return Image.open(result[0])
def superimpose(image_with_text, overlay_image):
# Open image as RGBA to handle transparency
overlay_image = overlay_image.convert("RGBA")
# Paste overlay on the background
image_with_text.paste(overlay_image, (0, 0), overlay_image)
# Save the final image
# image_with_text.save("output_image.png")
return image_with_text
def add_text_to_image(
input_image,
text,
font_size,
color,
opacity,
x_position,
y_position,
thickness
):
"""
Add text to an image with customizable properties
"""
# Convert gradio image (numpy array) to PIL Image
if input_image is None:
return None
image = Image.fromarray(input_image)
# remove background
overlay_image = remove_background(image)
# Create a transparent overlay for the text
txt_overlay = Image.new('RGBA', image.size, (255, 255, 255, 0))
draw = ImageDraw.Draw(txt_overlay)
# Create a font with specified size
try:
font = ImageFont.truetype("DejaVuSans.ttf", int(font_size))
except:
# If DejaVu font is not found, try to use Arial or default
try:
font = ImageFont.truetype("arial.ttf", int(font_size))
except:
print("Using default font as system fonts not found")
font = ImageFont.load_default()
# Convert color name to RGB
color_map = {
'White': (255, 255, 255),
'Black': (0, 0, 0),
'Red': (255, 0, 0),
'Green': (0, 255, 0),
'Blue': (0, 0, 255),
'Yellow': (255, 255, 0),
'Purple': (128, 0, 128)
}
rgb_color = color_map.get(color, (255, 255, 255))
# Get text size for positioning
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
# Calculate actual x and y positions based on percentages
actual_x = int((image.width - text_width) * (x_position / 100))
actual_y = int((image.height - text_height) * (y_position / 100))
# Create final color with opacity
text_color = (*rgb_color, int(opacity))
# Draw the text with stroke for thickness
add_text_with_stroke(
draw,
text,
actual_x,
actual_y,
font,
text_color,
int(thickness)
)
# Combine the original image with the text overlay
if image.mode != 'RGBA':
image = image.convert('RGBA')
output_image = Image.alpha_composite(image, txt_overlay)
# Convert back to RGB for display
output_image = output_image.convert('RGB')
# superimpose images
output_image = superimpose(output_image, overlay_image)
# Convert PIL image back to numpy array for Gradio
return np.array(output_image)
# Create the Gradio interface
def create_interface():
with gr.Blocks() as app:
gr.Markdown("# Add Text Behind Image")
gr.Markdown("Upload an image and customize text properties to add text overlay.")
with gr.Row():
with gr.Column():
# Input components
input_image = gr.Image(label="Upload Image", type="numpy")
text_input = gr.Textbox(label="Enter Text", placeholder="Type your text here...")
font_size = gr.Slider(minimum=10, maximum=800, value=400, step=10,
label="Font Size")
thickness = gr.Slider(minimum=0, maximum=20, value=0, step=1,
label="Text Thickness")
color_dropdown = gr.Dropdown(
choices=["White", "Black", "Red", "Green", "Blue", "Yellow", "Purple"],
value="White",
label="Text Color"
)
opacity_slider = gr.Slider(minimum=0, maximum=255, value=255, step=1,
label="Opacity")
x_position = gr.Slider(minimum=0, maximum=100, value=50, step=1,
label="X Position (%)")
y_position = gr.Slider(minimum=0, maximum=100, value=50, step=1,
label="Y Position (%)")
with gr.Column():
# Output image
output_image = gr.Image(label="Output Image")
# Process button
process_btn = gr.Button("Add Text to Image")
# Connect the input components to the processing function
process_btn.click(
fn=add_text_to_image,
inputs=[
input_image,
text_input,
font_size,
color_dropdown,
opacity_slider,
x_position,
y_position,
thickness
],
outputs=output_image
)
# Add example inputs
gr.Examples(
examples=[
[
"pink_convertible.webp",
"EPIC",
420,
"Purple",
150,
50,
21,
9
],
[
"pear.jpg",
"PEAR",
350,
"Black",
100,
50,
2,
5
],
[
"sample_text_image.jpeg",
"LIFE",
400,
"Black",
150,
50,
2,
8
],
],
inputs=[
input_image,
text_input,
font_size,
color_dropdown,
opacity_slider,
x_position,
y_position,
thickness
],
outputs=output_image,
fn=add_text_to_image,
cache_examples=True,
)
return app
# Launch the app
if __name__ == "__main__":
# Try to install required font
try:
import subprocess
subprocess.run(['apt-get', 'update'])
subprocess.run(['apt-get', 'install', '-y', 'fonts-dejavu'])
print("Font installed successfully")
except:
print("Could not install font automatically. Please install DejaVu font manually.")
# Create and launch the interface
app = create_interface()
app.launch(ssr_mode = False)