Person / app.py
Yofran23's picture
Update app.py
e39f16a verified
Raw
History Blame Contribute Delete
7.13 kB
import streamlit as st
import pandas as pd
from datetime import datetime
import os
import json
from PIL import Image
import google.generativeai as genai
import gspread
from google.oauth2.service_account import Credentials
# --- CONFIGURACIÓN DE PÁGINA ---
st.set_page_config(page_title="Escáner IA con Gemini", page_icon="✨", layout="centered")
st.title("✨ Escáner Inteligente con Gemini AI")
look = pd.read_csv("Informacion - Estados.csv")
df_ubicaciones = pd.read_excel('Municipios (1).xlsx', engine='openpyxl')
#AGG GOOGLE SHEET
try:
SCOPE = ["https://www.googleapis.com/auth/spreadsheets"]
# LA NUEVA FORMA SEGURA (Cargando desde un Secreto oculto)
credenciales_secretas = os.environ.get("GOOGLE_SHEETS_JSON")
# Convertimos el texto secreto de vuelta a un diccionario de Python
creds_dict = json.loads(credenciales_secretas)
CREDS = Credentials.from_service_account_info(creds_dict, scopes=SCOPE)
client = gspread.authorize(CREDS)
sheet_id = "1dDgUALSVyqgMQJTkCxs2kjI3S5IVoggxxias4dEcqb8" # TU ID ACTUAL
workbook = client.open_by_key(sheet_id)
# ¡IMPORTANTE! Crea una hoja nueva llamada "Encuestas" en tu archivo de Google Sheets
worksheet = workbook.worksheet("Registro")
except:
worksheet = None
# --- CONECTAR CON GOOGLE AI STUDIO ---
GOOGLE_API_KEY = os.environ.get("GEMINI_API_KEY")
genai.configure(api_key=GOOGLE_API_KEY)
# Usamos Gemini 1.5 Flash porque es rapidísimo, excelente viendo imágenes y 100% gratis en AI Studio
modelo = genai.GenerativeModel('gemini-2.5-flash')
def calcular_edad(fecha_str):
try:
fecha_nac = datetime.strptime(fecha_str, "%d-%m-%Y")
hoy = datetime.now()
return hoy.year - fecha_nac.year - ((hoy.month, hoy.day) < (fecha_nac.month, fecha_nac.day))
except:
return "N/A"
# --- INTERFAZ ---
st.markdown("---")
curso = st.radio("Tipo de registro*", ["Jugador", "Entrenador", "Desarrollador de talento"], horizontal=True, index=None)
st.markdown("---")
look = look.rename(columns = {'Estado':'ESTADO'})
estados = look['ESTADO'].unique().tolist()
selected_state = st.selectbox(
"1. Selecciona el estado:",
options=[''] + estados,
index=0
)
st.markdown("---")
selected_municipality = None
if selected_state:
# Filtra los municipios que pertenecen al estado seleccionado
state_municipalities = df_ubicaciones[df_ubicaciones['ESTADO'] == selected_state]['MUNICIPIO'].unique().tolist()
selected_municipality = st.selectbox(
"3. Selecciona el municipio:",
options=[''] + state_municipalities,
index=0
)
st.markdown("---")
opcion = st.radio("Método de entrada:", ("Usar Cámara 📷", "Subir Archivo 📁"), horizontal=True)
imagen_pil = None
if opcion == "Usar Cámara 📷":
foto = st.camera_input("Toma la foto de la cédula (no importa si está un poco torcida)")
if foto: imagen_pil = Image.open(foto)
else:
archivo_subido = st.file_uploader("Sube la imagen de la cédula", type=["jpg", "jpeg", "png"])
if archivo_subido: imagen_pil = Image.open(archivo_subido)
# --- PROCESAMIENTO CON GEMINI ---
if imagen_pil is not None:
st.image(imagen_pil, caption="Imagen Capturada", use_column_width=True)
if st.button("🚀 Analizar Cédula con Gemini"):
with st.spinner("La IA está leyendo la cédula..."):
# El "Prompt" (Las instrucciones exactas para la IA)
prompt = """
Eres un sistema de OCR avanzado de nivel bancario. Analiza esta imagen de una cédula de identidad venezolana.
REGLA DE ORO: El fondo tiene un escudo amarillo y letras pequeñas, IGNORA EL ESCUDO y el fondo. Concéntrate SOLO en el texto negro principal.
Extrae estos datos con precisión absoluta:
1. Cédula: Busca la 'V' o 'E', seguida de números. Quita los puntos. (Ejemplo: V-12345678).
2. Apellidos: Está justo a la derecha de la etiqueta "APELLIDOS".
3. Nombres: Está justo a la derecha de la etiqueta "NOMBRES".
4. Fecha de nacimiento: Formato DD-MM-YYYY. Suele estar en el centro, cerca de la etiqueta "F. NACIMIENTO". ¡No la confundas con la fecha de expedición o vencimiento!
Devuelve ÚNICAMENTE un JSON válido con estas claves exactas: "cedula", "apellidos", "nombres", "fecha_nacimiento".
Si algún dato está demasiado borroso, escribe "No legible". NO INVENTES NÚMEROS.
"""
try:
# Enviamos la imagen y las instrucciones a Gemini
respuesta = modelo.generate_content([prompt, imagen_pil])
texto_respuesta = respuesta.text.strip()
# Limpiamos por si Gemini añade ```json al principio por error
if texto_respuesta.startswith("```json"):
texto_respuesta = texto_respuesta[7:-3]
elif texto_respuesta.startswith("```"):
texto_respuesta = texto_respuesta[3:-3]
# Convertimos la respuesta de texto a un diccionario de Python
datos_extraidos = json.loads(texto_respuesta)
cedula = datos_extraidos.get("cedula", "Error")
apellidos = datos_extraidos.get("apellidos", "Error")
nombres = datos_extraidos.get("nombres", "Error")
fecha_nac = datos_extraidos.get("fecha_nacimiento", "Error")
edad = calcular_edad(fecha_nac)
# Mostrar resultados
st.success("¡Análisis completado al instante!")
col1, col2 = st.columns(2)
col1.text_input("Cédula", value=cedula)
col1.text_input("Apellidos", value=apellidos)
col2.text_input("Fecha de Nacimiento", value=fecha_nac)
col2.text_input("Nombres", value=nombres)
st.metric("Edad Calculada", f"{edad} años" if isinstance(edad, int) else edad)
# Guardar en Excel
fila_a_guardar = [cedula, apellidos, nombres, fecha_nac, edad, datetime.now().strftime("%Y-%m-%d %H:%M:%S"), curso,
selected_state,selected_municipality]
if worksheet:
try:
worksheet.append_row(fila_a_guardar)
st.success("✅ ¡Gracias! Tu encuesta ha sido registrada exitosamente.")
st.balloons()
except Exception as e:
st.error(f"Error al conectar con Google Sheets: {str(e)}")
else:
st.error("⚠️ No hay conexión configurada con la base de datos (Google Sheets).")
except Exception as e:
st.error(f"Hubo un error al procesar con la IA. Asegúrate de que la foto sea clara. Detalles: {e}")
with st.expander("Ver respuesta cruda de la IA (Depuración)"):
st.write(respuesta.text if 'respuesta' in locals() else "Sin respuesta")