Spaces:
Runtime error
Runtime error
import streamlit as st | |
from PIL import Image | |
import io | |
import numpy as np | |
import base64 | |
# Import our custom modules | |
from utils.image_preprocessing import preprocess_image | |
from models.document_ai import extract_text_and_layout | |
from models.text_processor import process_menu_text | |
from models.braille_translator import text_to_braille, get_braille_metadata | |
from utils.braille_display import create_braille_html, create_braille_comparison | |
from utils.pdf_generator import create_braille_pdf, create_braille_pdf_with_comparison | |
# Function to create a download link for a PDF | |
def get_pdf_download_link(pdf_bytes, filename="braille_menu.pdf", text="Download PDF"): | |
"""Generate a link to download the PDF file.""" | |
b64 = base64.b64encode(pdf_bytes.read()).decode() | |
href = f'<a href="data:application/pdf;base64,{b64}" download="{filename}">{text}</a>' | |
return href | |
# App title and description | |
st.title("Menu to Braille Converter") | |
st.write("Upload a menu image to convert it to Braille text") | |
# Sidebar for model settings | |
st.sidebar.header("Settings") | |
use_llm = st.sidebar.checkbox("Use LLM for text processing", value=True) | |
use_context = st.sidebar.checkbox("Use AI for context enhancement", value=True) | |
show_comparison = st.sidebar.checkbox("Show text/Braille comparison", value=True) | |
# Add information about the application | |
st.sidebar.markdown("---") | |
st.sidebar.subheader("About") | |
st.sidebar.info( | |
"This application converts menu images to Braille text using AI. " | |
"It extracts text from images using document AI, processes the text with LLMs, " | |
"and converts to Braille." | |
) | |
# File uploader | |
uploaded_file = st.file_uploader("Choose a menu image...", type=["jpg", "jpeg", "png"]) | |
# Display uploaded image and process it | |
if uploaded_file is not None: | |
# Load and display image | |
image = Image.open(uploaded_file) | |
st.image(image, caption="Uploaded Menu", use_column_width=True) | |
# Add a button to process the image | |
if st.button("Process Menu"): | |
with st.spinner("Processing image..."): | |
# Preprocess the image | |
preprocessed_img = preprocess_image(image) | |
# Extract text using LayoutLMv2 | |
try: | |
result = extract_text_and_layout(preprocessed_img) | |
# Display extracted words | |
if result['words']: | |
raw_text = ' '.join(result['words']) | |
# Show raw text in an expandable section | |
with st.expander("Raw Extracted Text"): | |
st.text_area("Raw OCR Output", raw_text, height=150) | |
# Process text with LLM if enabled | |
if use_llm: | |
st.subheader("Processed Menu Text") | |
with st.spinner("Enhancing text with AI..."): | |
processed_result = process_menu_text(raw_text) | |
if processed_result['success']: | |
processed_text = processed_result['structured_text'] | |
st.text_area("Structured Menu Text", processed_text, height=200) | |
# Store the processed result for later use | |
st.session_state.processed_text = processed_text | |
st.session_state.menu_data = processed_result.get('menu_data', {}) | |
else: | |
st.warning(f"AI processing failed: {processed_result.get('error', 'Unknown error')}") | |
processed_text = raw_text | |
st.text_area("Text Output", processed_text, height=200) | |
st.session_state.processed_text = processed_text | |
else: | |
# Just use the raw text | |
st.subheader("Extracted Text") | |
processed_text = raw_text | |
st.text_area("Text Output", processed_text, height=200) | |
st.session_state.processed_text = processed_text | |
# Translate to Braille | |
st.subheader("Braille Translation") | |
with st.spinner("Translating to Braille..."): | |
braille_result = text_to_braille(processed_text, use_context=use_context) | |
if braille_result['success']: | |
# Store for download | |
st.session_state.braille_text = braille_result['formatted_braille'] | |
# Display options | |
display_option = st.radio( | |
"Display format:", | |
["Text Only", "Visual Braille", "Side-by-Side Comparison"] | |
) | |
if display_option == "Text Only": | |
# Display Braille text as plain text | |
st.text_area("Braille Output", braille_result['formatted_braille'], height=300) | |
elif display_option == "Visual Braille": | |
# Display Braille with visual representation | |
braille_html = create_braille_html(braille_result['formatted_braille']) | |
st.markdown(braille_html, unsafe_allow_html=True) | |
else: # Side-by-Side Comparison | |
# Display side-by-side comparison | |
comparison_html = create_braille_comparison( | |
processed_text, braille_result['formatted_braille'] | |
) | |
st.markdown(comparison_html, unsafe_allow_html=True) | |
# Display metadata | |
metadata = get_braille_metadata(processed_text) | |
st.info(f"Translation contains {metadata['word_count']} words, " | |
f"{metadata['character_count']} characters, " | |
f"{metadata['line_count']} lines.") | |
# Show context summary if available | |
if braille_result.get('context_summary'): | |
with st.expander("AI Context Understanding"): | |
st.write(braille_result['context_summary']) | |
# PDF Download section | |
st.subheader("Download Options") | |
pdf_option = st.selectbox( | |
"Select PDF format:", | |
["Sequential (Text then Braille)", "Side-by-Side Comparison"] | |
) | |
pdf_title = st.text_input("PDF Title:", "Menu in Braille") | |
if st.button("Generate PDF"): | |
with st.spinner("Generating PDF..."): | |
if pdf_option == "Sequential (Text then Braille)": | |
pdf_buffer = create_braille_pdf( | |
processed_text, | |
braille_result['formatted_braille'], | |
title=pdf_title | |
) | |
else: # Side-by-Side Comparison | |
pdf_buffer = create_braille_pdf_with_comparison( | |
processed_text, | |
braille_result['formatted_braille'], | |
title=pdf_title | |
) | |
# Create download link | |
st.markdown( | |
get_pdf_download_link(pdf_buffer, f"{pdf_title.lower().replace(' ', '_')}.pdf"), | |
unsafe_allow_html=True | |
) | |
else: | |
st.error(f"Braille translation failed: {braille_result.get('error', 'Unknown error')}") | |
else: | |
st.warning("No text was extracted from the image.") | |
except Exception as e: | |
st.error(f"Error processing image: {str(e)}") | |