Spaces:
Runtime error
Runtime error
| 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("ovi054/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() |