Nuevos campos DNI: fecha nacimiento y sexo
Browse files- __pycache__/app.cpython-311.pyc +0 -0
- __pycache__/funciones.cpython-311.pyc +0 -0
- app.py +5 -2
- documentos.py +5 -3
- funciones.py +4 -2
- herramientas.py +89 -6
- obtenCampo.py +27 -2
__pycache__/app.cpython-311.pyc
CHANGED
Binary files a/__pycache__/app.cpython-311.pyc and b/__pycache__/app.cpython-311.pyc differ
|
|
__pycache__/funciones.cpython-311.pyc
CHANGED
Binary files a/__pycache__/funciones.cpython-311.pyc and b/__pycache__/funciones.cpython-311.pyc differ
|
|
app.py
CHANGED
@@ -19,6 +19,7 @@ async def health_check():
|
|
19 |
return JSONResponse(content={"status": "ok"}, status_code=200)
|
20 |
|
21 |
@app.post("/echo-image/",
|
|
|
22 |
description="Test endpoint que recibe y regresa la misma imagen, para probar envío, recepción y problemas con api o red.",
|
23 |
summary="Summary"
|
24 |
)
|
@@ -29,7 +30,8 @@ async def echo_image(image: UploadFile = File(...)):
|
|
29 |
return StreamingResponse(BytesIO(contents), media_type=image.content_type)
|
30 |
|
31 |
@app.post(
|
32 |
-
"/procesa_dni/",
|
|
|
33 |
summary="Procesamiento de DNI")
|
34 |
async def procesa_dni(image: UploadFile = File(...)):
|
35 |
if not image.content_type.startswith("image/"):
|
@@ -37,7 +39,8 @@ async def procesa_dni(image: UploadFile = File(...)):
|
|
37 |
return await funciones.procesa_dni(image)
|
38 |
|
39 |
@app.post(
|
40 |
-
"/procesa_pasaporte/",
|
|
|
41 |
summary="Procesamiento de DNI")
|
42 |
async def procesa_pasaporte(image: UploadFile = File(...)):
|
43 |
if not image.content_type.startswith("image/"):
|
|
|
19 |
return JSONResponse(content={"status": "ok"}, status_code=200)
|
20 |
|
21 |
@app.post("/echo-image/",
|
22 |
+
tags=["Health Check"],
|
23 |
description="Test endpoint que recibe y regresa la misma imagen, para probar envío, recepción y problemas con api o red.",
|
24 |
summary="Summary"
|
25 |
)
|
|
|
30 |
return StreamingResponse(BytesIO(contents), media_type=image.content_type)
|
31 |
|
32 |
@app.post(
|
33 |
+
"/procesa_dni/",
|
34 |
+
tags=["Rapicash"],
|
35 |
summary="Procesamiento de DNI")
|
36 |
async def procesa_dni(image: UploadFile = File(...)):
|
37 |
if not image.content_type.startswith("image/"):
|
|
|
39 |
return await funciones.procesa_dni(image)
|
40 |
|
41 |
@app.post(
|
42 |
+
"/procesa_pasaporte/",
|
43 |
+
tags=["Rapicash"],
|
44 |
summary="Procesamiento de DNI")
|
45 |
async def procesa_pasaporte(image: UploadFile = File(...)):
|
46 |
if not image.content_type.startswith("image/"):
|
documentos.py
CHANGED
@@ -2,18 +2,20 @@ import obtenCampo
|
|
2 |
|
3 |
async def dni(textos_extraidos):
|
4 |
textos_extraidos_simplificados = [texto.lower().replace(" ", "") for texto in textos_extraidos]
|
|
|
|
|
5 |
|
6 |
#Campos Buscados
|
7 |
nombre, apellido = obtenCampo.Nombre(textos_extraidos, textos_extraidos_simplificados)
|
8 |
identificacion = obtenCampo.Identificacion(textos_extraidos, textos_extraidos_simplificados)
|
|
|
|
|
9 |
|
10 |
-
return nombre, apellido, identificacion
|
11 |
|
12 |
async def pasaporte(textos_extraidos):
|
13 |
textos_extraidos_simplificados = [texto.lower().replace(" ", "") for texto in textos_extraidos]
|
14 |
-
|
15 |
#Campos Buscados
|
16 |
nombre, apellido = obtenCampo.Nombre(textos_extraidos, textos_extraidos_simplificados)
|
17 |
identificacion = obtenCampo.Identificacion(textos_extraidos, textos_extraidos_simplificados)
|
18 |
-
|
19 |
return nombre, apellido, identificacion
|
|
|
2 |
|
3 |
async def dni(textos_extraidos):
|
4 |
textos_extraidos_simplificados = [texto.lower().replace(" ", "") for texto in textos_extraidos]
|
5 |
+
print("Textos extraídos simplificados:")
|
6 |
+
print(textos_extraidos_simplificados)
|
7 |
|
8 |
#Campos Buscados
|
9 |
nombre, apellido = obtenCampo.Nombre(textos_extraidos, textos_extraidos_simplificados)
|
10 |
identificacion = obtenCampo.Identificacion(textos_extraidos, textos_extraidos_simplificados)
|
11 |
+
fecha_nacimiento = obtenCampo.Fecha_Nacimiento(textos_extraidos, textos_extraidos_simplificados)
|
12 |
+
sexo = obtenCampo.Sexo(textos_extraidos, textos_extraidos_simplificados)
|
13 |
|
14 |
+
return nombre, apellido, identificacion, fecha_nacimiento, sexo
|
15 |
|
16 |
async def pasaporte(textos_extraidos):
|
17 |
textos_extraidos_simplificados = [texto.lower().replace(" ", "") for texto in textos_extraidos]
|
|
|
18 |
#Campos Buscados
|
19 |
nombre, apellido = obtenCampo.Nombre(textos_extraidos, textos_extraidos_simplificados)
|
20 |
identificacion = obtenCampo.Identificacion(textos_extraidos, textos_extraidos_simplificados)
|
|
|
21 |
return nombre, apellido, identificacion
|
funciones.py
CHANGED
@@ -8,12 +8,14 @@ async def procesa_dni(image):
|
|
8 |
textos_extraidos = await herramientas.procesaImagen(image)
|
9 |
|
10 |
#Campos DNI Panamá.
|
11 |
-
nombre, apellido, identificacion = await documentos.dni(textos_extraidos)
|
12 |
|
13 |
return {
|
14 |
"nombre": nombre,
|
15 |
"apellido": apellido,
|
16 |
-
"identificacion": identificacion
|
|
|
|
|
17 |
}
|
18 |
|
19 |
async def procesa_pasaporte(image):
|
|
|
8 |
textos_extraidos = await herramientas.procesaImagen(image)
|
9 |
|
10 |
#Campos DNI Panamá.
|
11 |
+
nombre, apellido, identificacion, fecha_nacimiento, sexo = await documentos.dni(textos_extraidos)
|
12 |
|
13 |
return {
|
14 |
"nombre": nombre,
|
15 |
"apellido": apellido,
|
16 |
+
"identificacion": identificacion,
|
17 |
+
"fecha_nacimiento": fecha_nacimiento,
|
18 |
+
"sexo": sexo
|
19 |
}
|
20 |
|
21 |
async def procesa_pasaporte(image):
|
herramientas.py
CHANGED
@@ -1,10 +1,9 @@
|
|
1 |
import tempfile
|
2 |
import time
|
3 |
-
import herramientas
|
4 |
from gradio_client import Client, handle_file
|
|
|
5 |
|
6 |
async def imageToTemp(image):
|
7 |
-
print("Estoy en imageToTemp...")
|
8 |
|
9 |
try:
|
10 |
with tempfile.NamedTemporaryFile(delete=False, suffix=f"_{image.filename}") as tmp_file:
|
@@ -37,10 +36,49 @@ def listaTextosExtraidos(dict_recibido):
|
|
37 |
|
38 |
def buscaIndexPalabra(arreglo, palabra):
|
39 |
palabra_limpia = palabra.lower().replace(" ", "")
|
40 |
-
for i, texto_limpio in enumerate(arreglo):
|
41 |
if palabra_limpia in texto_limpio:
|
42 |
return i
|
43 |
-
return 'error'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
def buscarPatronCedula(lista_textos):
|
46 |
for i, texto in enumerate(lista_textos):
|
@@ -52,7 +90,7 @@ async def procesaImagen(image):
|
|
52 |
|
53 |
temp_image = await imageToTemp(image)
|
54 |
|
55 |
-
client = Client("
|
56 |
dict_recibido = client.predict(
|
57 |
img=handle_file(temp_image),
|
58 |
lang="en",
|
@@ -60,4 +98,49 @@ async def procesaImagen(image):
|
|
60 |
)
|
61 |
#Aquí es donde personalizo el proceso:
|
62 |
textos_extraidos = listaTextosExtraidos(dict_recibido)
|
63 |
-
return textos_extraidos
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import tempfile
|
2 |
import time
|
|
|
3 |
from gradio_client import Client, handle_file
|
4 |
+
import re
|
5 |
|
6 |
async def imageToTemp(image):
|
|
|
7 |
|
8 |
try:
|
9 |
with tempfile.NamedTemporaryFile(delete=False, suffix=f"_{image.filename}") as tmp_file:
|
|
|
36 |
|
37 |
def buscaIndexPalabra(arreglo, palabra):
|
38 |
palabra_limpia = palabra.lower().replace(" ", "")
|
39 |
+
for i, texto_limpio in enumerate(arreglo):
|
40 |
if palabra_limpia in texto_limpio:
|
41 |
return i
|
42 |
+
return None # Cambiado de 'error' a None
|
43 |
+
|
44 |
+
def buscaIndexMultiplesPalabras(arreglo, palabras_requeridas):
|
45 |
+
"""
|
46 |
+
Busca el índice de la primera línea en un arreglo de textos
|
47 |
+
que contenga TODAS las palabras especificadas en palabras_requeridas.
|
48 |
+
|
49 |
+
Args:
|
50 |
+
arreglo (list): Una lista de strings (los textos limpios).
|
51 |
+
palabras_requeridas (list): Una lista de strings, donde cada string
|
52 |
+
es una palabra que debe estar presente en la línea.
|
53 |
+
La búsqueda es insensible a mayúsculas/minúsculas
|
54 |
+
y limpia espacios en las palabras requeridas.
|
55 |
+
|
56 |
+
Returns:
|
57 |
+
int: El índice de la primera línea que contiene todas las palabras,
|
58 |
+
o None si ninguna línea las contiene.
|
59 |
+
"""
|
60 |
+
|
61 |
+
print("Estoy en busca palabras múltiples.")
|
62 |
+
|
63 |
+
|
64 |
+
# Limpiar y normalizar todas las palabras requeridas de una vez
|
65 |
+
palabras_requeridas_limpias = [p.lower().replace(" ", "") for p in palabras_requeridas]
|
66 |
+
|
67 |
+
print("Las palabras requeridas límpias son: ", palabras_requeridas_limpias)
|
68 |
+
|
69 |
+
for i, texto_linea in enumerate(arreglo):
|
70 |
+
# Convertir la línea actual a minúsculas para una comparación insensible a mayúsculas/minúsculas
|
71 |
+
texto_linea_lower = texto_linea.lower()
|
72 |
+
|
73 |
+
print("La línea que estoy analizando es: ", texto_linea_lower)
|
74 |
+
|
75 |
+
# Verificar si TODAS las palabras requeridas están en la línea actual
|
76 |
+
# Usamos 'all()' para asegurarnos de que CADA palabra_limpia esté en texto_linea_lower
|
77 |
+
if all(palabra_limpia in texto_linea_lower for palabra_limpia in palabras_requeridas_limpias):
|
78 |
+
print(f"Todas las palabras están en la línea {i}")
|
79 |
+
return i # Retorna el índice de la primera línea que cumple la condición
|
80 |
+
|
81 |
+
return None # Si ninguna línea contiene todas las palabras
|
82 |
|
83 |
def buscarPatronCedula(lista_textos):
|
84 |
for i, texto in enumerate(lista_textos):
|
|
|
90 |
|
91 |
temp_image = await imageToTemp(image)
|
92 |
|
93 |
+
client = Client("BuzzwordMx/ai_ocr")
|
94 |
dict_recibido = client.predict(
|
95 |
img=handle_file(temp_image),
|
96 |
lang="en",
|
|
|
98 |
)
|
99 |
#Aquí es donde personalizo el proceso:
|
100 |
textos_extraidos = listaTextosExtraidos(dict_recibido)
|
101 |
+
return textos_extraidos
|
102 |
+
|
103 |
+
def obtener_fecha(texto):
|
104 |
+
# El patrón busca:
|
105 |
+
# - "FECHADENACIMIENTO" (insensible a mayúsculas/minúsculas)
|
106 |
+
# - Seguido opcionalmente de CERO o MÁS caracteres que NO SEAN UN DÍGITO (lo que inicia la fecha).
|
107 |
+
# Esto cubrirá ':', '.', espacios, o cualquier otro carácter de separación.
|
108 |
+
# - Captura el patrón de fecha: \d{1,2}-[A-Za-z0-9]{3}-\d{4}
|
109 |
+
patron = r"FECHADENACIMIENTO[^\d]*(\d{1,2}-[A-Za-z0-9]{3}-\d{4})"
|
110 |
+
|
111 |
+
match = re.search(patron, texto, re.IGNORECASE)
|
112 |
+
|
113 |
+
fecha_encontrada = None
|
114 |
+
if match:
|
115 |
+
fecha_encontrada = match.group(1)
|
116 |
+
|
117 |
+
if fecha_encontrada:
|
118 |
+
partes_fecha = fecha_encontrada.split('-')
|
119 |
+
if len(partes_fecha) == 3:
|
120 |
+
dia = partes_fecha[0]
|
121 |
+
mes = partes_fecha[1].lower() # Convierte el mes a minúsculas
|
122 |
+
año = partes_fecha[2]
|
123 |
+
return f"{dia}-{mes}-{año}"
|
124 |
+
else:
|
125 |
+
# Esto se ejecutaría si el formato de la fecha extraída no es el esperado (ej. 2 partes)
|
126 |
+
return fecha_encontrada
|
127 |
+
|
128 |
+
return None # Si no se encontró el patrón de fecha
|
129 |
+
|
130 |
+
def obtener_sexo(texto):
|
131 |
+
# El patrón ahora busca "Sexo" O "Seno" (insensible a mayúsculas/minúsculas)
|
132 |
+
# Seguido opcionalmente de un ":"
|
133 |
+
# Seguido opcionalmente de espacios en blanco
|
134 |
+
# Captura la siguiente letra
|
135 |
+
patron = r"(Sexo|Seno):?\s*([A-Za-z])"
|
136 |
+
|
137 |
+
# re.search busca la primera ocurrencia del patrón en el texto
|
138 |
+
# re.IGNORECASE hace que la búsqueda sea insensible a mayúsculas/minúsculas para "Sexo" y "Seno"
|
139 |
+
match = re.search(patron, texto, re.IGNORECASE)
|
140 |
+
|
141 |
+
if match:
|
142 |
+
# match.group(2) devuelve lo que se capturó en el SEGUNDO grupo de paréntesis,
|
143 |
+
# que es la letra del sexo/seno. match.group(1) sería "Sexo" o "Seno".
|
144 |
+
return match.group(2)
|
145 |
+
else:
|
146 |
+
return None
|
obtenCampo.py
CHANGED
@@ -4,7 +4,6 @@ import herramientas
|
|
4 |
#Campos para DNI.
|
5 |
def Nombre(textos_extraidos, textos_extraidos_limpios):
|
6 |
indice = herramientas.buscaIndexPalabra(textos_extraidos_limpios, 'usual')
|
7 |
-
print(f"Indice es: {indice} y es del tipo {type(indice)}...")
|
8 |
nombre = textos_extraidos[indice-2]
|
9 |
apellido = textos_extraidos[indice-1]
|
10 |
return nombre, apellido
|
@@ -12,4 +11,30 @@ def Nombre(textos_extraidos, textos_extraidos_limpios):
|
|
12 |
def Identificacion(textos_extraidos, textos_extraidos_limpios):
|
13 |
indice = herramientas.buscarPatronCedula(textos_extraidos_limpios)
|
14 |
identificacion = textos_extraidos[indice]
|
15 |
-
return identificacion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
#Campos para DNI.
|
5 |
def Nombre(textos_extraidos, textos_extraidos_limpios):
|
6 |
indice = herramientas.buscaIndexPalabra(textos_extraidos_limpios, 'usual')
|
|
|
7 |
nombre = textos_extraidos[indice-2]
|
8 |
apellido = textos_extraidos[indice-1]
|
9 |
return nombre, apellido
|
|
|
11 |
def Identificacion(textos_extraidos, textos_extraidos_limpios):
|
12 |
indice = herramientas.buscarPatronCedula(textos_extraidos_limpios)
|
13 |
identificacion = textos_extraidos[indice]
|
14 |
+
return identificacion
|
15 |
+
|
16 |
+
def Fecha_Nacimiento(textos_extraidos, textos_extraidos_limpios):
|
17 |
+
indice = herramientas.buscaIndexMultiplesPalabras(textos_extraidos_limpios, ['fecha', 'nacimiento'])
|
18 |
+
print("El índice de la fecha de nacimiento es: ", indice)
|
19 |
+
texto_fecha_nacimiento = textos_extraidos_limpios[indice] #En ésta ocasión estoy usando el texto limpio para que el patrón lo identifique más fácilmente.
|
20 |
+
print("Y su correspondiente texto es: " , texto_fecha_nacimiento)
|
21 |
+
fecha_nacimiento = herramientas.obtener_fecha(texto_fecha_nacimiento)
|
22 |
+
return fecha_nacimiento
|
23 |
+
|
24 |
+
def Sexo(textos_extraidos, textos_extraidos_limpios):
|
25 |
+
|
26 |
+
indice = herramientas.buscaIndexPalabra(textos_extraidos_limpios, 'sexo')
|
27 |
+
|
28 |
+
if indice is None: # Comprobamos si el resultado es None (no encontrado)
|
29 |
+
indice = herramientas.buscaIndexPalabra(textos_extraidos_limpios, 'seno')
|
30 |
+
if indice is not None:
|
31 |
+
print(f"Se encontró una variación de sexo en el índice: {indice}")
|
32 |
+
else:
|
33 |
+
print("No se encontró ninguna forma de la palabra sexo.")
|
34 |
+
return None
|
35 |
+
else:
|
36 |
+
print(f"Se encontró palabra directamente.")
|
37 |
+
|
38 |
+
texto_campo_sexo = textos_extraidos[indice]
|
39 |
+
sexo = herramientas.obtener_sexo(texto_campo_sexo)
|
40 |
+
return sexo
|