easyocr / app.py
roque99cheroA's picture
Upload 4 files
008c86f verified
Raw
History Blame Contribute Delete
5.92 kB
"""
=============================================================
EasyOCR API - Reconocimiento de Texto Rápido
=============================================================
API REST para reconocer texto usando EasyOCR
Optimizado para velocidad - Ideal para páginas completas
=============================================================
"""
import io
import easyocr
import numpy as np
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from pydantic import BaseModel
from PIL import Image
from typing import Optional, List
import os
# =============================================================
# CONFIGURACION
# =============================================================
app = FastAPI(
title="EasyOCR API",
description="Reconocimiento de texto rápido con EasyOCR",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc"
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# =============================================================
# MODELOS DE RESPUESTA
# =============================================================
class LineDetail(BaseModel):
texto: str
confianza: float
class OCRResponse(BaseModel):
exito: bool
texto: str
confianza: float
lineas: List[LineDetail]
mensaje: Optional[str] = None
# =============================================================
# GESTOR DE EASYOCR
# =============================================================
class EasyOCRManager:
def __init__(self):
self._reader = None
@property
def reader(self):
if self._reader is None:
print("=" * 50)
print("Cargando EasyOCR (español + inglés)...")
print("=" * 50)
self._reader = easyocr.Reader(
['es', 'en'],
gpu=False,
verbose=False
)
print("EasyOCR listo!")
return self._reader
def recognize(self, image: Image.Image) -> tuple:
"""Reconoce texto en una imagen"""
# Convertir a RGB
if image.mode != 'RGB':
image = image.convert('RGB')
# Redimensionar si es muy grande
max_size = 2048
if max(image.size) > max_size:
ratio = max_size / max(image.size)
new_size = (int(image.size[0] * ratio), int(image.size[1] * ratio))
image = image.resize(new_size, Image.Resampling.LANCZOS)
# Convertir a numpy array
image_np = np.array(image)
# Reconocer
resultados = self.reader.readtext(image_np)
if not resultados:
return "", 0.0, []
textos = []
confianzas = []
lineas = []
for bbox, texto, conf in resultados:
texto = texto.strip()
if texto and conf >= 0.3: # Filtrar baja confianza
textos.append(texto)
confianzas.append(conf)
lineas.append({
"texto": texto,
"confianza": round(conf, 3)
})
texto_completo = ' '.join(textos)
confianza_promedio = sum(confianzas) / len(confianzas) if confianzas else 0.0
return texto_completo, confianza_promedio, lineas
# Instancia global
ocr = EasyOCRManager()
# =============================================================
# ENDPOINTS
# =============================================================
@app.get("/")
async def inicio():
return {
"nombre": "EasyOCR API",
"version": "1.0.0",
"descripcion": "Reconocimiento de texto rápido",
"modelo": "EasyOCR (español + inglés)",
"velocidad": "~2-5 segundos por imagen",
"endpoints": {
"GET /": "Esta información",
"GET /health": "Estado del servicio",
"GET /docs": "Documentación Swagger",
"POST /recognize": "Reconocer texto en imagen"
}
}
@app.get("/health")
async def health():
return {"status": "ok", "modelo": "EasyOCR"}
# Servir index.html si existe
@app.get("/app")
async def serve_app():
if os.path.exists("index.html"):
return FileResponse("index.html")
return {"error": "index.html no encontrado"}
@app.post("/recognize", response_model=OCRResponse)
async def recognize(file: UploadFile = File(...)):
"""
Reconoce texto en una imagen usando EasyOCR.
Rápido: ~2-5 segundos por imagen
Soporta: Español e Inglés
"""
if not file.content_type or not file.content_type.startswith('image/'):
raise HTTPException(status_code=400, detail="Debe ser una imagen")
try:
contents = await file.read()
image = Image.open(io.BytesIO(contents))
texto, confianza, lineas = ocr.recognize(image)
if texto:
return OCRResponse(
exito=True,
texto=texto,
confianza=round(confianza, 3),
lineas=[LineDetail(**l) for l in lineas],
mensaje=f"Se reconocieron {len(lineas)} elementos"
)
else:
return OCRResponse(
exito=False,
texto="",
confianza=0.0,
lineas=[],
mensaje="No se detectó texto"
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# =============================================================
# MAIN
# =============================================================
if __name__ == "__main__":
import uvicorn
print("\n" + "=" * 50)
print(" EasyOCR API")
print(" http://localhost:7860")
print(" Docs: http://localhost:7860/docs")
print("=" * 50 + "\n")
uvicorn.run(app, host="0.0.0.0", port=7860)