# Face Recognition API 🧠

API para comparar duas imagens faciais e verificar se são da mesma pessoa.
### Estrutura de pastas
```plain text
face-api/
├── app.py                 # Flask e registra rotas
├── failed_faces/
├── imgs/                  # imagens de teste
├── routes/
│   └── face_routes.py      # Define rotas (separado)
├── services/
│   └── face_service.py     # Comparação de rostos
├── config/
│   └── settings.py         # Threshold
├── Dockerfile
├── docker-compose.yaml
├── Makefile
├── requirements.txt
└── README.md               
```

# 🧠 API de Reconhecimento Facial com DeepFace Dlib

Esta é uma API minimalista de verificação facial utilizando o modelo `deepface_dlib`, selecionado após benchmark de desempenho e precisão. Ela oferece endpoints simples e eficientes para **registrar imagens** e **comparar faces** com alta acurácia e baixo tempo de resposta.

---

## 📦 Tecnologias utilizadas

- [Python 3.11](https://www.python.org/)
- [Flask](https://flask.palletsprojects.com/)
- [DeepFace](https://github.com/serengil/deepface) com backend Dlib
- [MinIO](https://min.io/) para armazenamento de imagens
- [face_recognition](https://github.com/ageitgey/face_recognition) para validação facial

---

## 🚀 Como rodar com Docker

```bash
make devup
```

---

## 🌐 Endpoints disponíveis

### ✅ `POST /register_face`

Registra uma imagem de uma pessoa e salva os metadados (como as posições das faces detectadas) no MinIO.

**Parâmetros:**
- `person_id`: identificador da pessoa
- `image`: arquivo de imagem (formato `.jpg`, `.png`, etc.)

**Exemplo:**

```bash
curl -X POST http://localhost:5006/register_face \
  -F "person_id=fulano" \
  -F "image=@imgs/aa.jpg"
```

**Resposta:**

```json
{
  "image_path": "fulano/20250501-145258.jpg",
  "person_id": "fulano",
  "status": "Face cropped and saved",
  "timestamp": "20250501-145258"
}
```
Exemplo miniO
![Exemplo miniO](docs/image-1.png)

---

### ✅ `POST /checkin`

Compara duas imagens e retorna se é a mesma pessoa com base no modelo `deepface_dlib`. Uma imagem está no storage ([aa.jpg](imgs/aa.png)) e a outra é passada pro endpoint ([bb.jpg](imgs/bb.png)).

**Parâmetros:**
- `person_id`: fulano
- `image`: bb.jpg

**Exemplo:**

```bash
curl -X POST http://localhost:5006/checkin \
  -F "person_id=fulano" \
  -F "image=@imgs/bb.jpg"
```

**Resposta:**

```json
{
  "confidence": "high",
  "duration_sec": 0.7338,
  "match": true,
  "person_id": "fulano",
  "similarity_score": 0.9643,
  "threshold": 0.6
}
```
**Ou Resposta com medium score:**
```json
{
  "confidence": "medium",
  "duration_sec": 0.4199,
  "match": false,
  "person_id": "fulano",
  "similarity_score": 0.9136,
  "threshold": 0.6
}
```
---
### ✅ Se houver `match = True`, ele:

* ⏱ Salva a data/hora do registro

* 📷 Salva a imagem original

* 😁 Recorta e salva o rosto detectado

* 📝 Gera e salva um .json com:
Pessoa, IP, tempo de resposta, similaridade, confiança e status do match

 * * OBS: É interessante, para a vida útil do modelo, que eventualmente seja salvo uma imagem da face nova após realizar um checkin para compor a pasta de faces registradas do indivíduo para garantir mudanças de aparência e garantir assertividade do ponto eletrônico.

**Se houver match = False:**

* Nada acontece, se quiser pode ser salvo as imagens de tentativa de utilização do ponto para verificar fraudes
---

## 📁 Estrutura esperada no MinIO

Ao registrar imagens com `person_id = fulano`, os arquivos são salvos na pasta registred_faces.

Ao realizar checkin é salvo arquivos na pasta checkins conforme:

```
data/
├── registred_faces/
│   └── ciclano/
│           └── 20240501-180123.jpg
│   └── fulano/
│           └── 20240501-180143.jpg
├── checkins/
│   └── fulano
│       └── data
│           └── hora
│               └── metadata.json
│               └── face.jpg
│               └── original.jpg

```

---


## ⚙️ Variáveis de ambiente `.env`

```env
DEBUG=True
THRESHOLD=0.93
MINIO_ENDPOINT=minio:9000
MINIO_BUCKET=data
MINIO_ACCESS_KEY=admin
MINIO_SECRET_KEY=password

# Faixas de confiança para verificação facial
CONFIDENCE_HIGH=0.95
CONFIDENCE_MEDIUM=0.85
```

---

## 🛠️ Comandos Makefile

```bash
make devup     # Sobe com docker-compose.dev.yaml
make devdown   # Para os containers
make logs      # Logs ao vivo
```

---

## 👨‍🔬 Benchmark e decisão de arquitetura

O modelo `deepface_dlib` foi escolhido após benchmarks comparando:
- Tempo médio por verificação
- Similaridade média
- Taxa de acerto

Veja o gráfico da média dos resultados comparando 7 imagens diferentes, a linha verde é a acurácia 

![benchmark_Figure.png](docs/benchmark_Figure.png)

### Próximos passos
* Atualmente o checkin utiliza a ultima imagem registrada, é possível fazer com que ele utilize todas e faça uma média, ou pegue a de melhor score ( é um detalhe complicado de lidar pois pode gerar falsos positivos)
* Colocar uma etapa de treinamento de modelo após um número de checkins positivo, mapeando o escore de similaridade para que fique sempre acima de 0.95.
* Colocar um sistema para funcionar offline
* Colocar um aviso de tentativa de fraude
* implementar um método que identifica alguém tentando realizar o ponto com uma foto do rosto da pessoa..
