fzd5 / app.py
fdbw's picture
Update app.py
021f069 verified
Raw
History Blame Contribute Delete
3 kB
import gradio as gr
import easyocr
from deep_translator import GoogleTranslator
from gtts import gTTS
import numpy as np
import os
# --- 全局初始化 ---
# 确保在 CPU 模式下运行,并使用更稳定的 deep-translator 库
OCR_READER = None
def get_ocr_reader():
"""初始化 EasyOCR Reader,使用 CPU 模式和轻量化模型,避免内存溢出 (OOM)"""
global OCR_READER
if OCR_READER is None:
try:
# 使用 CPU 模式 (gpu=False)
# 第一次运行时,会下载模型文件到本地的 model_cache 目录
OCR_READER = easyocr.Reader(['en'],
gpu=False,
model_storage_directory='./model_cache',
download_enabled=True)
print("EasyOCR Reader 初始化成功 (CPU 模式)")
except Exception as e:
print(f"EasyOCR 初始化失败: {e}")
raise
return OCR_READER
def process_image(image):
"""主处理函数:OCR -> 翻译 -> TTS"""
# 检查输入
if image is None:
return "请拍摄或上传图片", None
reader = get_ocr_reader()
# 1. 文本识别 (OCR)
try:
results = reader.readtext(image, detail=0)
source_text = " ".join(results).strip()
except Exception as e:
return f"文字识别失败: {str(e)}", None
if not source_text:
return "未能识别到图片中的文字。", None
# 2. 翻译 (使用 deep-translator,稳定且无需密钥)
try:
# 从自动检测语言翻译到中文 (zh-CN)
translated_text = GoogleTranslator(source='auto', target='zh-CN').translate(source_text)
except Exception as e:
return f"翻译器暂时不可用: {str(e)}", None
# 3. 语音播报 (TTS)
audio_path = "output.mp3"
try:
tts = gTTS(text=translated_text, lang='zh-cn')
tts.save(audio_path)
except Exception as e:
print(f"语音合成失败: {e}")
audio_path = None
result_text = f"【原文】:\n{source_text}\n\n【翻译】:\n{translated_text}"
return result_text, audio_path
# --- Gradio 界面设计 (解决 theme 和 sources 兼容性问题) ---
with gr.Blocks() as demo:
gr.Markdown("# 📸 拍照翻译官 (最终稳定版)")
gr.Markdown("对准英文文字拍照,稍等片刻即可获得中文翻译及发音。")
with gr.Row():
with gr.Column():
# 兼容性修正:将 'camera' 替换为旧版 Gradio 兼容的 'webcam'
input_img = gr.Image(sources=["webcam", "upload"], type="numpy", label="上传/拍照")
btn = gr.Button("开始翻译", variant="primary")
with gr.Column():
out_txt = gr.Textbox(label="文本结果", lines=8)
out_audio = gr.Audio(label="语音播报")
btn.click(process_image, input_img, [out_txt, out_audio])
if __name__ == "__main__":
demo.launch()