File size: 6,928 Bytes
ea50c95 5d094c5 ea50c95 5d094c5 ea50c95 5d094c5 ea50c95 5d094c5 ea50c95 5d094c5 ea50c95 5d094c5 ea50c95 5d094c5 ea50c95 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
import streamlit as st
import os
from PIL import Image
import torch
from manga_translator.translator import MangaTextDetector, process_manga_pages
import tempfile
import cv2
import io
# Initialize session state
if 'processed_results' not in st.session_state:
st.session_state.processed_results = {}
if 'temp_dir' not in st.session_state:
st.session_state.temp_dir = tempfile.mkdtemp()
# Set page config for wider layout and title
st.set_page_config(
page_title="Manga Translator",
page_icon="π―",
layout="wide",
initial_sidebar_state="auto"
)
# Custom CSS for centering and background
st.markdown("""
<style>
/* Background Gradient */
body {
background: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%) !important;
}
/* Main content container */
.main .block-container {
max-width: 900px;
margin: 0 auto;
padding-top: 2rem;
padding-bottom: 2rem;
}
/* Custom box style */
.centered-box {
background: white;
border-radius: 16px;
box-shadow: 0 4px 32px rgba(0,0,0,0.08);
padding: 2rem;
margin-bottom: 2rem;
}
/* Button stretch */
.stButton>button {
width: 100%;
}
/* Alert style */
.stAlert {
background-color: rgb(255, 251, 235);
border: none;
padding: 1rem;
margin: 1rem 0;
}
</style>
""", unsafe_allow_html=True)
st.title("π¦ MangaFlow: AI Manga Translator")
st.write("Upload a manga page to translate Japanese text to English. Powered by YOLO, Manga OCR, and DeepL.")
st.warning("**Note:** Translation accuracy may vary due to the complexity of Japanese text and manga-specific expressions. We're continuously working to improve the system!")
with st.expander("π Guidelines for Best Results", expanded=False):
st.markdown("1. **Image Requirements:**")
st.markdown("""
- Clear, high-resolution manga page
- Japanese text should be clearly visible
- Text bubbles should not be cropped
- Supported formats: PNG, JPG, JPEG
""")
st.markdown("2. **For Best Results:**")
st.markdown("""
- Avoid pages with handwritten text
- Ensure text bubbles are not overlapping
- Image should be properly oriented
- Avoid heavily compressed images
""")
st.markdown("3. **Privacy & Copyright:**")
st.markdown("""
- Only upload content you have rights to use
- We don't store any uploaded images
- All processing is done in real-time
""")
with st.expander("π How It Works", expanded=False):
st.markdown("""
1. **Text Detection:** Custom YOLO model detects text bubbles
2. **OCR Processing:** Extracts Japanese text
3. **Translation:** Converts to English using DeepL API
4. **Text Insertion:** Places translated text back into the image
""")
def process_image(uploaded_file):
"""Process image and store results in session state."""
if uploaded_file.name not in st.session_state.processed_results:
try:
detector = MangaTextDetector('best.pt')
# Save temporary file
temp_path = os.path.join(st.session_state.temp_dir, uploaded_file.name)
with open(temp_path, "wb") as f:
f.write(uploaded_file.getbuffer())
# Process image
image, detections, result_image, processed_regions, translated_image = detector.process_image(temp_path)
# Store all results in session state
st.session_state.processed_results[uploaded_file.name] = {
'image': image,
'detections': detections,
'result_image': result_image,
'processed_regions': processed_regions,
'translated_image': translated_image
}
return True
except Exception as e:
st.error(f"β Error: {str(e)}")
return False
return True
uploaded_files = st.file_uploader(
"Choose manga pages",
type=['png', 'jpg', 'jpeg'],
accept_multiple_files=True,
help="Drag and drop your manga images here. Supported formats: PNG, JPG, JPEG"
)
if uploaded_files:
with tempfile.TemporaryDirectory() as temp_dir:
for uploaded_file in uploaded_files:
file_path = os.path.join(temp_dir, uploaded_file.name)
with open(file_path, "wb") as f:
f.write(uploaded_file.getbuffer())
detector = MangaTextDetector('best.pt')
for uploaded_file in uploaded_files:
st.subheader(f"Processing: {uploaded_file.name}")
col1, col2 = st.columns(2)
image_path = os.path.join(temp_dir, uploaded_file.name)
original_image = Image.open(image_path)
with col1:
st.markdown("**Original Image**")
st.image(original_image, use_column_width=True)
try:
image, detections, result_image, processed_regions, translated_image = detector.process_image(image_path)
with col2:
if translated_image is not None:
st.markdown("**Translated Image**")
st.image(translated_image, use_column_width=True)
else:
st.error("No text was detected in this image.")
if processed_regions and processed_regions['text_regions']:
with st.expander("View Detected Text and Translations"):
for i, region in enumerate(processed_regions['text_regions'], 1):
st.markdown(f"**Region {i}**")
cols = st.columns(2)
with cols[0]:
st.markdown("Original Text:")
st.code(region['text'])
with cols[1]:
st.markdown("Translation:")
st.code(region['translation'])
st.markdown("---")
except Exception as e:
st.error(f"Error processing {uploaded_file.name}: {str(e)}")
continue
st.markdown("---")
else:
st.info("π Upload a manga page to get started!")
st.markdown("""
<div style='text-align: center; color: #666666; padding: 1rem;'>
Made with β€οΈ for manga fans
</div>
""", unsafe_allow_html=True)
st.markdown("---")
st.markdown("""
*Created by Ebhon*
This app translates manga text from Japanese to English using:
- YOLO for text detection
- Manga OCR for Japanese text recognition
- DeepL for translation
""")
st.markdown('</div>', unsafe_allow_html=True)
st.markdown('</div>', unsafe_allow_html=True) |