Spaces:
Running
Running
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) |