Case-app / app.py
Taf2023's picture
Upload app.py with huggingface_hub
56f49e6 verified
import gradio as gr
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import io
import os
from typing import Optional, Tuple, List
import re
# Mock OCR function (in real implementation, you'd use pytesseract or similar)
def detect_text_in_image(image: np.ndarray) -> List[str]:
"""Mock function to detect existing text in image"""
# In a real implementation, this would use OCR like pytesseract
# For demo purposes, we'll return some sample detected text
return ["Sample text detected", "Another text element"]
def add_text_to_image(
image: np.ndarray,
new_text: str,
text_position: str,
font_size: int,
text_color: str,
background_color: str,
detect_existing: bool,
accessibility_description: str
) -> Tuple[np.ndarray, str, str]:
"""
Add text overlay to image with accessibility features
"""
if image is None:
return None, "Please upload an image first", ""
# Convert numpy array to PIL Image
pil_image = Image.fromarray(image.astype('uint8'), 'RGB')
# Detect existing text if requested
existing_text_info = ""
if detect_existing:
try:
detected_texts = detect_text_in_image(image)
if detected_texts:
existing_text_info = "Detected existing text:\n" + "\n".join(f"• {text}" for text in detected_texts)
else:
existing_text_info = "No existing text detected in the image."
except Exception as e:
existing_text_info = f"Text detection failed: {str(e)}"
# Add new text overlay
draw = ImageDraw.Draw(pil_image)
# Create font (you might want to use a proper font file in production)
try:
font = ImageFont.truetype("arial.ttf", font_size)
except:
font = ImageFont.load_default()
# Get image dimensions
img_width, img_height = pil_image.size
# Calculate text position
text_bbox = draw.textbbox((0, 0), new_text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
position_map = {
"top-left": (10, 10),
"top-center": ((img_width - text_width) // 2, 10),
"top-right": (img_width - text_width - 10, 10),
"center-left": (10, (img_height - text_height) // 2),
"center": ((img_width - text_width) // 2, (img_height - text_height) // 2),
"center-right": (img_width - text_width - 10, (img_height - text_height) // 2),
"bottom-left": (10, img_height - text_height - 10),
"bottom-center": ((img_width - text_width) // 2, img_height - text_height - 10),
"bottom-right": (img_width - text_width - 10, img_height - text_height - 10)
}
x, y = position_map.get(text_position, position_map["bottom-center"])
# Add background rectangle for better readability (optional)
if background_color != "transparent":
# Convert hex color to RGB
if background_color.startswith('#'):
bg_rgb = tuple(int(background_color[i:i+2], 16) for i in (1, 3, 5))
else:
bg_rgb = (0, 0, 0) # default black
# Draw background rectangle
padding = 5
draw.rectangle([
x - padding, y - padding,
x + text_width + padding, y + text_height + padding
], fill=bg_rgb)
# Convert text color to RGB
if text_color.startswith('#'):
text_rgb = tuple(int(text_color[i:i+2], 16) for i in (1, 3, 5))
else:
text_rgb = (255, 255, 255) # default white
# Draw text
draw.text((x, y), new_text, fill=text_rgb, font=font)
# Convert back to numpy array
result_image = np.array(pil_image)
# Generate accessibility description
if not accessibility_description:
accessibility_description = f"Image with text overlay: '{new_text}' positioned at {text_position}"
# Combine all information for accessibility
full_accessibility_info = f"Accessibility Description: {accessibility_description}\n\n"
if existing_text_info:
full_accessibility_info += f"{existing_text_info}\n\n"
full_accessibility_info += f"Added text: '{new_text}' at {text_position} with font size {font_size}"
return result_image, full_accessibility_info, existing_text_info
# Create the Gradio interface
with gr.Blocks(title="Premium Image Text Overlay - Accessibility Edition") as demo:
gr.HTML("""
<div style="text-align: center; margin-bottom: 20px;">
<h1 style="color: #4A90E2; font-size: 2.5em;">🖼️ Premium Image Text Overlay</h1>
<p style="font-size: 1.2em; color: #666;">Enhanced accessibility for visually impaired users with text detection</p>
<p><a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">Built with anycoder</a></p>
</div>
""")
with gr.Tabs():
with gr.Tab("🖼️ Image Editor"):
with gr.Row():
with gr.Column():
input_image = gr.Image(
label="Upload Image",
type="numpy",
height=400,
interactive=True
)
with gr.Accordion("🔍 Text Detection Settings", open=True):
detect_existing = gr.Checkbox(
label="Detect existing text in image",
value=True,
info="Automatically detect and display any text already present in the uploaded image"
)
existing_text_display = gr.Textbox(
label="Existing Text Detection Results",
interactive=False,
max_lines=5,
placeholder="Existing text will appear here after detection..."
)
with gr.Column():
output_image = gr.Image(
label="Result Image",
type="numpy",
height=400,
interactive=False
)
accessibility_output = gr.Textbox(
label="♿ Accessibility Information",
interactive=False,
max_lines=8,
placeholder="Comprehensive accessibility description will appear here..."
)
with gr.Accordion("✏️ Add New Text", open=True):
with gr.Row():
new_text = gr.Textbox(
label="Text to Add",
placeholder="Enter your text here...",
max_lines=3
)
text_position = gr.Dropdown(
choices=[
"top-left", "top-center", "top-right",
"center-left", "center", "center-right",
"bottom-left", "bottom-center", "bottom-right"
],
value="bottom-center",
label="Text Position"
)
with gr.Row():
font_size = gr.Slider(
minimum=10,
maximum=100,
value=24,
step=2,
label="Font Size"
)
text_color = gr.ColorPicker(
value="#FFFFFF",
label="Text Color"
)
background_color = gr.ColorPicker(
value="#000000",
label="Background Color",
info="Set to transparent for no background"
)
accessibility_description = gr.Textbox(
label="Custom Accessibility Description",
placeholder="Add a custom description for screen readers (optional)...",
max_lines=3
)
with gr.Row():
process_btn = gr.Button(
"✨ Add Text & Generate Accessibility Info",
variant="primary",
size="lg"
)
clear_btn = gr.Button("🗑️ Clear All", variant="secondary")
with gr.Tab("ℹ️ How to Use"):
gr.Markdown("""
### 🎯 Premium Features for Accessibility
**For Visually Impaired Users:**
- **Automatic Text Detection**: Our system automatically detects existing text in your uploaded images
- **Comprehensive Descriptions**: Get detailed accessibility information including detected text and added overlays
- **Screen Reader Friendly**: All outputs are optimized for screen reader compatibility
**How It Works:**
1. **Upload** your image using the file picker or drag-and-drop
2. **Enable** "Detect existing text in image" to automatically find text already present
3. **Add** your new text with customizable position, size, and colors
4. **Review** the accessibility information that combines detected text and your additions
5. **Download** the final image with complete accessibility metadata
**Accessibility Best Practices:**
- Always provide meaningful custom descriptions when possible
- Use high contrast colors for better visibility
- Consider the context of existing text when adding new overlays
- The accessibility information is designed to be read by screen readers
""")
# Event handlers
process_btn.click(
fn=add_text_to_image,
inputs=[
input_image,
new_text,
text_position,
font_size,
text_color,
background_color,
detect_existing,
accessibility_description
],
outputs=[
output_image,
accessibility_output,
existing_text_display
]
)
clear_btn.click(
fn=lambda: (None, "", "", ""),
inputs=[],
outputs=[
input_image,
output_image,
accessibility_output,
existing_text_display
]
)
# Auto-detect existing text when image is uploaded (if detection is enabled)
input_image.change(
fn=lambda img, detect: (detect_text_in_image(img) if detect and img is not None else []) if detect else [],
inputs=[input_image, detect_existing],
outputs=existing_text_display
)
# Launch the app
if __name__ == "__main__":
demo.launch()