Cloud Functions (OCR & Facial Recognition)
Este documento describe 7 Cloud Functions creadas en Node.js.
Se dividen en **Funciones de OCR** y **Funciones de Reconocimiento Facial** para su mejor entendimiento.
---
## Índice
1. **Funciones de OCR**
- [ocrReadAndWriteImage](#1-ocrreadandwriteimage)
- [saveMinimalBotConversations](#2-saveminimalbotconversations)
- [sendOCRdataToCreatePerson](#3-sendocrdatatocreateperson)
2. **Funciones de Reconocimiento Facial**
- [createPerson](#4-createperson)
- [facialRecognition](#5-facialrecognition)
- [searchPersonInDB](#6-searchpersonindb)
- [verifyPersonIdentity](#7-verifypersonidentity)
---
## Funciones de OCR
### 1. **ocrReadAndWriteImage**
**Endpoint** : https://us-west1-servicios-350819.cloudfunctions.net/ocrReadAndWriteImage
**Función Exportada**
```js
functions.http('processImage', async (req, res) => { ... })
```
#### Descripción
Esta función recibe la **URL de una imagen**, la procesa usando **Google Generative AI** para extraer datos de identificación en un formato JSON y los **normaliza** (ajusta campos como `name` → `first_name` y `last_name`, direcciones, fechas, etc.).
Finalmente, envía el JSON normalizado a la ruta configurada en `CONFIG.RECEIVER_URL`.
#### Flujo Principal
1. **Obtener la URL** de la imagen (por `req.query.url` o `req.body.url`).
2. **Descargar** la imagen y convertirla a Base64.
3. **Invocar** el modelo generativo (por ejemplo, `"gemini-1.5-flash"`).
4. **Limpiar** y **parsear** la respuesta para extraer el JSON.
5. **Normalizar** campos (separar `first_name`, `last_name`, unificar direcciones, etc.).
6. **Enviar** el JSON resultante a la función receptora (por POST).
7. **Retornar** el JSON normalizado al cliente.
#### Parámetros de Entrada
- **Body JSON** (o Query Params):
- `url` _(string, requerido)_: URL de la imagen a procesar.
**Ejemplo Body:**
```JSON
{
"url": "https://example.com/my-id-image.jpg"
}
```
- No requiere otros campos. Si se omite `url`, retorna error 400.
#### Respuesta
- **200 OK**
Devuelve un objeto JSON con los campos extraídos y normalizados:
```JSON
{
"first_name": "Jane",
"last_name": "Smith",
"driver_license_number": "ABC12345",
"date_of_birth": "1992-02-02",
"expiration_date": "2032-02-02",
...
}
```
- **400 Bad Request**
Si no se proporciona `url`.
- **422 Unprocessable Entity**
Si la respuesta de la AI no es un JSON válido.
- **500 Internal Server Error**
Cualquier otro error en el procesamiento o en la llamada a la función receptora.
#### Dependencias
- **@google-cloud/functions-framework** (para exponer la función como HTTP).
- **node-fetch** (para descargar la imagen y enviar datos).
- **@google/generative-ai** (cliente de Google Generative AI).
- **dotenv** (para leer variables de entorno como `API_KEY`, `PROMPT`, etc.).
#### Variables de Entorno
- `API_KEY` — Clave para Google Generative AI.
- `PROMPT` — Texto base para el modelo.
- `RECEIVER_URL` — URL destino donde se envía el JSON resultante.
- `MODEL_NAME` — Nombre del modelo a usar (por defecto `"gemini-1.5-flash"`).
_______________________________________________________________________
### 2. **saveMinimalBotConversations**
**Endpoint** : https://us-central1-servicios-350819.cloudfunctions.net/saveMinimalBotConversations
**Función Exportada**
```js
functions.http('sendDataToGoogleSheet', async (req, res) => { ... })
```
#### Descripción
Esta función toma datos relacionados con OCR (o similar) y los **almacena** en Google Sheets mediante el servicio de **SheetDB**:
1. Determina **en qué hoja** (sheet) colocar la información según si los datos están en **español** (`data.nombre`) o **inglés** (`data.first_name`).
2. Construye el objeto `sheetData` (con `sheet` y `data`) y realiza una llamada `POST` a la URL de SheetDB (`API_URL`).
3. Retorna al cliente la respuesta de la API de SheetDB.
#### Parámetros de Entrada
- **Body JSON** (requerido):
- `nombre` _(string, opcional)_: si existe, se guardará en la hoja "OCR Esp".
- `first_name` _(string, opcional)_: si existe, se guardará en la hoja "OCR Eng".
- Otros campos libres (apellidos, dirección, etc.) también se guardan.
**Ejemplo Body en Español:**
```JSON
{
"nombre": "Juan Perez",
"fecha_nacimiento": "1985-01-01",
"direccion": "Av. Principal 123"
}
```
**Ejemplo Body en Inglés:
```JSON
{
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-05-15"
}
```
- **Importante**: Debe existir **al menos** `nombre` **o** `first_name`. De lo contrario, responde `400 JSON format not recognized`.
#### Respuesta
- **200 OK**
Devuelve el resultado de la API de SheetDB:
```JSON
{
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-05-15"
}
```
- **400 Bad Request**
Si no encuentra ni `nombre` ni `first_name`.
- **500 Internal Server Error**
Cualquier otro error interno o fallo en la llamada a SheetDB.
#### Flujo Principal
1. **Validar** que la petición sea `POST`.
2. **Leer** el objeto `data` del `body` de la petición.
3. **Definir** la hoja destino (`"OCR Esp"` si se detecta `nombre`, `"OCR Eng"` si se detecta `first_name`).
4. **Enviar** los datos a la API de SheetDB.
5. **Retornar** la respuesta de la API.
#### Dependencias
- **@google-cloud/functions-framework**
- **axios**
#### Consideraciones
- Si no se detectan `nombre` o `first_name`, se responde con `400 JSON format not recognized`.
- El endpoint de SheetDB se encuentra en la variable `API_URL` (en el código).
_______________________________________________________________________
### 3. **sendOCRdataToCreatePerson**
**Endpoint** : https://us-central1-servicios-350819.cloudfunctions.net/sendOCRdataToCreatePerson
**Función Exportada**
```js
functions.http('processImages', async (req, res) => { ... })
```
#### Descripción
Orquesta el **flujo OCR → creación de persona**:
1. Recibe **dos URLs**: `idImageUrl` (imagen de identificación) y `selfieUrl`.
2. Llama a la función **ocrReadAndWriteImage** con la imagen de identificación.
3. **Normaliza** y **transforma** los datos recibidos del OCR para ajustarlos a la estructura que requiere **createPerson**.
4. Invoca **createPerson** con esos datos y la `selfieUrl`.
5. Retorna la respuesta de `createPerson` y los datos enviados (sin la URL de la selfie).
#### Parámetros de Entrada
- **Body JSON** (o Query Params):
- `idImageUrl` _(string, requerido)_: URL de la imagen de la identificación.
- `selfieUrl` _(string, requerido)_: URL de la imagen tipo selfie.
**Ejemplo Body**
```JSON
{
"idImageUrl": "https://example.com/my-id.jpg",
"selfieUrl": "https://example.com/my-selfie.jpg"
}
```
- Si faltan `idImageUrl` o `selfieUrl`, retorna `400`.
#### Respuesta
- **200 OK**
```JSON
{
"response": {
"message": "Person Created Successfully",
"supabase_id": 123
},
"savedData": {
"name": "Juan Perez",
"date_of_birth": "1985-01-01",
"gender": "M"
...
}
}
```
- **400 Bad Request**
Si faltan URLs en los parámetros.
- **500 Internal Server Error**
Cualquier error al procesar la OCR o la creación de persona.
#### Flujo Principal
1. **Validar** que existan `idImageUrl` y `selfieUrl`.
2. **Invocar** `ocrReadAndWriteImage`, obteniendo los datos OCR.
3. **Formatear** la respuesta OCR (INE vs Licencia, etc.).
4. **Llamar** a `createPerson` con el objeto resultante.
5. **Retornar** la respuesta de creación y los datos utilizados.
#### Dependencias
- **@google-cloud/functions-framework**
- **axios**
#### Funciones Auxiliares
- `formatPersonData(ocrData, selfieUrl)`: Combina campos para ajustarlos al formato requerido por `createPerson`.
- `formatDate(dateString)`: Formatea fechas `DD/MM/YYYY` a `YYYY-MM-DD`.
_______________________________________________________________________
## Funciones de Reconocimiento Facial
### Consideraciones:
- Un "match" corresponde a un puntaje de 0.7 o superior para considerar que las selfies de la o las personas coinciden y se trata de la misma.
- Para mayor referencia revisar la documentación oficial de openCV:
```cardlink
url: https://us.opencv.fr/docs#/
title: "OpenCV Face Recognition - Swagger UI"
host: us.opencv.fr
```
- Los ids que proporciona openCV son el formato uuid y los ids proporcionados por supase son int8.
### 4. **createPerson**
**Endpoint** : https://us-central1-servicios-350819.cloudfunctions.net/createPerson
**Función Exportada**
```js
functions.http('createPerson', async (req, res) => { ... })
```
#### Descripción
Crea un registro de persona en la base de datos de **OpenCV** y luego **almacena** el `opencv_id` en **Supabase**:
1. Convierte la imagen a Base64.
2. Llama a `https://us.opencv.fr/person` para crear la persona y obtener un `id` (llamado `opencv_id`).
3. Guarda ese `opencv_id` en la tabla `people` de **Supabase**.
4. Retorna el `id` de Supabase y un mensaje de éxito.
#### Parámetros de Entrada
- **Body JSON** (o Query Params):
- `date_of_birth` _(string, requerido)_: fecha de nacimiento en formato `YYYY-MM-DD` (o similar).
- `gender` _(string, requerido)_: "M" o "F" (o "H" vs "M" según la convención).
- `imageUrl` _(string, requerido)_: URL de la foto a enrolar.
- `name` _(string, requerido)_: nombre completo o nombre de la persona.
- `nationality` _(string, opcional)_: nacionalidad.
**Ejemplo Body**
```JSON
{
"date_of_birth": "1990-05-15",
"gender": "M",
"imageUrl": "https://example.com/person-face.jpg",
"name": "John Doe",
"nationality": "US"
}
```
- Si falta alguno de los campos requeridos, retorna 400.
#### Respuesta
- **200 OK**
```JSON
{
"message": "Person Created Successfully",
"supabase_id": 17
}
```
- **400 Bad Request**
Si faltan parámetros obligatorios (`date_of_birth`, `gender`, `imageUrl`, `name`).
- **500 Internal Server Error**
Cualquier error al comunicarse con OpenCV o Supabase.
#### Flujo Principal
1. **Leer** parámetros obligatorios (`date_of_birth`, `gender`, `imageUrl`, `name`…).
2. **Validar** que existan. Retornar `400` si faltan.
3. **Descargar** la imagen y convertirla a Base64.
4. **Invocar** la API de OpenCV para crear la persona.
5. **Insertar** en Supabase el registro con el `opencv_id` devuelto.
6. **Retornar** el `supabase_id` y un mensaje de confirmación.
#### Dependencias
- **@google-cloud/functions-framework**
- **axios**
- **dotenv** (para leer `OPENCV_API_KEY`, `SUPABASE_API_KEY`, etc.)
#### Variables de Entorno
- `OPENCV_API_KEY` — Clave de la API de OpenCV.
- `SUPABASE_API_KEY` — Clave de la API de Supabase.
- `SUPABASE_URL` — URL base del proyecto Supabase.
_______________________________________________________________________
### 5. **facialRecognition**
**Endpoint** : https://us-central1-servicios-350819.cloudfunctions.net/facialRecognition
**Función Exportada**
```js
functions.http('compareImages', async (req, res) => { ... })
```
#### Descripción
Compara **dos imágenes** (una llamada “gallery” y otra “probe”) usando la API de OpenCV:
1. Recibe sus URLs (`gallery_url` y `probe_url`).
2. Descarga ambas y las transforma a Base64.
3. Llama a `https://us.opencv.fr/compare` con el modo `"ACCURATE"`.
4. Devuelve al cliente la respuesta de la API (score, match, etc.).
#### Parámetros de Entrada
- **Body JSON** (o Query Params):
- `gallery_url` _(string, requerido)_: URL de la imagen de galería.
- `probe_url` _(string, requerido)_: URL de la imagen a comparar.
**Ejemplo Body**
```JSON
{
"gallery_url": "https://example.com/gallery.jpg",
"probe_url": "https://example.com/probe.jpg"
}
```
#### Respuesta
- **200 OK**
Devuelve el objeto JSON directamente desde la API de OpenCV, por ejemplo:
```JSON
{
"match": {
"score": 0.87,
"bounding_box": ...
...
},
"status": "success"
}
```
- **400 Bad Request**
Si faltan `gallery_url` o `probe_url`.
- **500 Internal Server Error**
Si hay un error en la llamada a OpenCV.
#### Flujo Principal
1. **Verificar** la existencia de `gallery_url` y `probe_url`.
2. **Descargar** ambas imágenes en formato binario.
3. **Convertir** a Base64.
4. **Enviar** a la API `compare` de OpenCV.
5. **Retornar** la respuesta completa de OpenCV al cliente.
#### Dependencias
- **@google-cloud/functions-framework**
- **axios**
- **dotenv**
#### Variables de Entorno
- `OPENCV_API_KEY` — Clave para la API de OpenCV.
_______________________________________________________________________
### 6. **searchPersonInDB**
**Endpoint** : https://us-central1-servicios-350819.cloudfunctions.net/searchPersonInDB
**Función Exportada**
```js
functions.http('searchImage', async (req, res) => { ... })
```
#### Descripción
Busca posibles coincidencias de una persona en la base de **OpenCV** a partir de la **imagen** recibida:
1. Recibe la URL de la imagen (`imageUrl`).
2. Convierte la imagen a Base64.
3. Llama a `https://us.opencv.fr/search` especificando un `max_results` y un `min_score`.
4. Retorna la lista de coincidencias que OpenCV considere válidas.
#### Parámetros de Entrada
- **Body JSON** (o Query Params):
- `url` _(string, requerido)_: URL de la imagen a buscar
(en el código, también se admite `req.body.imageUrl`).
**Ejemplo Body**
```JSON
{
"url": "https://example.com/face_to_search.jpg"
}
```
- Si falta la URL, retorna 400.
#### Respuesta
- **200 OK**
```JSON
[
{
"id": "123",
"score": 0.92
},
{
"id": "456",
"score": 0.85
}
]
```
- **400 Bad Request**
Si no se proporciona la URL de la imagen.
- **500 Internal Server Error**
Si ocurre un error al llamar a OpenCV o procesar la imagen.
#### Flujo Principal
1. **Validar** que `imageUrl` exista (req.body o req.query).
2. **Descargar** y **codificar** la imagen.
3. **Enviar** la petición a `search` en OpenCV.
4. **Retornar** los resultados.
#### Dependencias
- **@google-cloud/functions-framework**
- **axios**
- **dotenv**
#### Variables de Entorno
- `OPENCV_API_KEY` — Clave para la API de OpenCV.
_______________________________________________________________________
### 7. **verifyPersonIdentity**
**Endpoint** : https://us-central1-servicios-350819.cloudfunctions.net/verifyPersonIdentity
**Función Exportada**
```js
functions.http('verifyFace', async (req, res) => { ... })
```
#### Descripción
Verifica la identidad de una persona comparando una **selfie** con el registro previo en OpenCV:
1. Recibe el `id` (de Supabase) y una `imageUrl`.
2. Busca en la tabla `people` de Supabase para obtener el `opencv_id`.
3. Llama a `https://us.opencv.fr/verify` con la imagen y el `opencv_id`.
4. Retorna el `score` de similitud y el `name` registrado.
#### Parámetros de Entrada
- **Body JSON** (o Query Params):
- `id` _(number, requerido)_: ID de la persona en Supabase (campo `id` de la tabla `people`).
- `imageUrl` _(string, requerido)_: URL de la selfie a comparar.
**Ejemplo Body**
```JSON
{
"id": 42,
"imageUrl": "https://example.com/selfie.jpg"
}
```
#### Respuesta
- **200 OK**
```JSON
{
"score": 0.85,
"name": "John Doe"
}
```
- **400 Bad Request**
Si faltan `id` o `imageUrl`, o la imagen no se pudo descargar.
- **404 Not Found**
Si la persona con ese `id` no existe en Supabase.
- **500 Internal Server Error**
Si hay un problema interno (llamadas a OpenCV o a Supabase fallidas).
#### Flujo Principal
1. **Validar** parámetros: `id` y `imageUrl`.
2. **Descargar** la imagen y convertirla a Base64.
3. **Consultar** en Supabase para obtener `opencv_id` y `name`.
4. **Invocar** la API `verify` en OpenCV con el `opencv_id`.
5. **Retornar** `score` y `name`.
#### Dependencias
- **@google-cloud/functions-framework**
- **axios**
- **dotenv**
#### Variables de Entorno
- `OPENCV_API_KEY` — Clave para la API de OpenCV.
- `SUPABASE_API_KEY` — Clave para la API de Supabase.