From 5577977f9392c9a82d033682cf1fecfdfa62a85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tha=C3=ADs=20Ferreira?= Date: Wed, 29 Jan 2025 14:07:07 +0000 Subject: [PATCH] Update 13 files - /tests/__init__.py - /tests/teste_unitario.py - /static/style.css - /static/styleappy.css - /.dockerignore - /.gitignore - /.gitlab-ci.yml - /app.py - /dockerfile - /main.py - /makefile - /README.md - /requirements.txt --- .dockerignore | 89 ----------------------------------- .gitignore | 96 -------------------------------------- .gitlab-ci.yml | 53 --------------------- README.md | 81 -------------------------------- app.py | 59 ----------------------- dockerfile | 29 ------------ main.py | 59 ----------------------- makefile | 101 ---------------------------------------- requirements.txt | 5 -- static/style.css | 32 ------------- static/styleappy.css | 87 ---------------------------------- tests/__init__.py | 0 tests/teste_unitario.py | 91 ------------------------------------ 13 files changed, 782 deletions(-) delete mode 100644 .dockerignore delete mode 100644 .gitignore delete mode 100644 .gitlab-ci.yml delete mode 100644 README.md delete mode 100644 app.py delete mode 100644 dockerfile delete mode 100644 main.py delete mode 100644 makefile delete mode 100644 requirements.txt delete mode 100644 static/style.css delete mode 100644 static/styleappy.css delete mode 100644 tests/__init__.py delete mode 100644 tests/teste_unitario.py diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 78bb049..0000000 --- a/.dockerignore +++ /dev/null @@ -1,89 +0,0 @@ -# Git -.git -.gitignore -.gitattributes - - -# CI -.codeclimate.yml -.travis.yml -.taskcluster.yml - -# Docker -docker-compose.yml -Dockerfile -.docker -.dockerignore - -# Byte-compiled / optimized / DLL files -**/__pycache__/ -**/*.py[cod] - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg -*.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.cache -nosetests.xml -coverage.xml - -# Translations -*.mo -*.pot - -# Django stuff: -*.log - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Virtual environment -.env -.venv/ -venv/ - -# PyCharm -.idea - -# Python mode for VIM -.ropeproject -**/.ropeproject - -# Vim swap files -**/*.swp - -# VS Code -.vscode/ \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index d7c8c03..0000000 --- a/.gitignore +++ /dev/null @@ -1,96 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Virtual environments -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# IDE specific settings -.vscode/ -.idea/ -*.sublime-project -*.sublime-workspace - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# dotenv -.env -.venv - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# Profiling data -.prof - -# Test coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -lmodel/__pycache__/ -tests/__pycache__/ -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index add6607..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,53 +0,0 @@ -stages: - - build - - check - - publish - - deploy - -variables: - PROJECT_NAME: "api-face-recognition" - -build: - stage: build - tags: - - runner_tars_1 - script: - - make build - only: - - main - - -check: - stage: check - tags: - - runner_tars_1 - script: - - python3 -m venv venv - - source venv/bin/activate - - pip install -r requirements.txt - - make check - only: - - main - - -publish: - stage: publish - tags: - - runner_tars_1 - script: - - make login-aws - - make publish - only: - - main - - -deploy: - stage: deploy - tags: - - runner_tars_1 - script: - - make deploy-ci - only: - - main - - \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index cad9a52..0000000 --- a/README.md +++ /dev/null @@ -1,81 +0,0 @@ -## Sistema de Cadastro de Rostos com Flask - -Este projeto é um sistema simples desenvolvido em Flask para cadastrar e listar rostos. Ele permite que imagens de rostos sejam carregadas, exibidas em uma interface web e enviadas para uma API de cadastro. A aplicação também oferece uma navegação paginada para visualizar as imagens de rostos cadastradas. - -## Funcionalidades - -- [ ] Página inicial: Redireciona automaticamente para a lista de rostos cadastrados. -- [ ] Listagem de rostos: Exibe as imagens dos rostos cadastrados com suporte à paginação. -- [ ] Cadastro de rostos: Permite que o usuário selecione um ou mais rostos e associe-os a um nome. As imagens selecionadas são enviadas para uma API externa para o cadastro. -- [ ] Exibição de imagens: Permite a exibição das imagens cadastradas diretamente na aplicação. - -## Requisitos -Python 3.6 ou superior -Flask -Requests - -Instalando dependências - -Clone o repositório: - -`` -git clone -cd -`` - -## Crie um ambiente virtual: - -`` -python3 -m venv venv -source venv/bin/activate # No Windows use: venv\Scripts\activate -`` - -Instale as dependências: - -`` -pip install -r requirements.txt -`` - -## Estrutura do projeto - -- [ ] app.py: Arquivo principal que contém a aplicação Flask e suas rotas. -- [ ] folder/faces/: Diretório que contém as imagens dos rostos. -- [ ] templates/: Diretório contendo os arquivos HTML para as páginas da aplicação. -- [ ] static/: Diretório para arquivos estáticos (caso necessários). - -## Rotas - -/ -- [ ] Redireciona para a rota /listar_rostos. -/listar_rostos -- [ ] Exibe uma lista paginada das imagens de rostos cadastradas. -/listar_rostos/page/ -- [ ] Exibe a página solicitada da lista de rostos cadastrados. -/cadastrar_pessoas -- [ ] Exibe um formulário para cadastrar rostos. -Requer que o usuário selecione ao menos uma imagem e forneça um nome. -- [ ] As imagens selecionadas são enviadas para a API de cadastro. -/faces/ -Exibe a imagem de rosto solicitada. - -## Como rodar a aplicação -Certifique-se de que todas as dependências estão instaladas. - -Execute o servidor Flask: - -`` -python app.py -`` -Acesse a aplicação em http://localhost:5001 no seu navegador. - -## Configuração -- [ ] FOLDER_PATH: Caminho para o diretório onde as imagens de rostos estão armazenadas. -- [ ] API_URL: URL da API de cadastro de rostos. Certifique-se de que a API esteja rodando na URL fornecida. -- [ ] FILES_PER_PAGE: Define o número de arquivos exibidos por página na listagem. - -## Contribuição -- [ ] Faça um fork deste repositório. -- [ ] Crie uma branch para sua alteração (git checkout -b feature/novo-recurso). -- [ ] Faça suas modificações e commit (git commit -am 'Adicionando novo recurso'). -- [ ] Envie para o repositório remoto (git push origin feature/novo-recurso). -- [ ] Abra um Pull Request. \ No newline at end of file diff --git a/app.py b/app.py deleted file mode 100644 index 6f05559..0000000 --- a/app.py +++ /dev/null @@ -1,59 +0,0 @@ -from flask import Flask, request, send_file, jsonify,render_template -import requests -from io import BytesIO - -app = Flask(__name__) - -@app.route('/', methods=['GET']) -def index(): - return render_template('appy.html') - -@app.route('/list_faces', methods=['POST']) -def list_faces(): - url = request.json.get('url') - try: - response = requests.get(url) - return jsonify(response.json()) - except Exception as e: - return jsonify({'error': str(e)}) - -@app.route('/get_image', methods=['POST']) -def get_image(): - base_url = request.json.get('base_url') - bucket = request.json.get('bucket') - image_path = request.json.get('image_path') - - try: - # Construir a URL completa - full_url = f"{base_url}/{bucket}/{image_path}" - - # Fazer a requisição GET para obter a imagem - response = requests.get(full_url, stream=True) - response.raise_for_status() # Lança exceção se o status for 4xx ou 5xx - - # Retornar a imagem como um arquivo para o front-end - return send_file( - BytesIO(response.content), - mimetype='image/jpeg', # Ajuste o mimetype conforme o formato da imagem (jpeg, png, etc.) - download_name='image.jpg' # Nome sugerido do arquivo, opcional - ) - except requests.exceptions.RequestException as e: - return jsonify({'error': str(e)}), 400 -@app.route('/update_name', methods=['POST']) -def update_name(): - url = request.json.get('url') - userID = request.json.get('userID') - new_name = request.json.get('new_name') - - try: - - full_url = f"{url}/{userID}/{new_name}" - - response = requests.post(full_url) - response.raise_for_status() - - return jsonify(response.json()) - except requests.exceptions.RequestException as e: - return jsonify({'error': str(e)}), 400 -if __name__ == '__main__': - app.run(debug=True) diff --git a/dockerfile b/dockerfile deleted file mode 100644 index bd6a37c..0000000 --- a/dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -# Use a imagem oficial do Python -FROM python:3.9-slim - -# Defina o diretório de trabalho no contêiner -WORKDIR /app - -# Copie os arquivos necessários para o contêiner -COPY . /app - -#RUN apt update && apt install -y cmake make build-essential libgl1-mesa-glx wget libsqlite3-dev -RUN apt-get update && apt-get install -y \ - cmake \ - make \ - build-essential \ - libgl1-mesa-glx \ - wget \ - libsqlite3-dev \ - libgtk2.0-dev \ - pkg-config - - -# Instale as dependências -RUN pip install --no-cache-dir -r requirements.txt -# Exponha a porta em que a aplicação Flask vai rodar -EXPOSE 5001 - -# Comando para rodar a aplicação -CMD ["python3", "app.py"] - diff --git a/main.py b/main.py deleted file mode 100644 index d2b97b2..0000000 --- a/main.py +++ /dev/null @@ -1,59 +0,0 @@ -import cv2 -import os -import torch -from facenet_pytorch import MTCNN -import argparse - -# Função para processar o vídeo -def process_video(source, output_folder): - # Verificar se a pasta de saída existe, se não, criar - if not os.path.exists(output_folder): - os.makedirs(output_folder) - - # Carregar vídeo - cap = cv2.VideoCapture(source) - if not cap.isOpened(): - print(f"Erro ao abrir o vídeo {source}") - return - - # Carregar o modelo MTCNN para detecção de rostos - device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') - mtcnn = MTCNN(keep_all=True, device=device) - - frame_count = 0 - face_count = 0 - - while True: - ret, frame = cap.read() - if not ret: - break - - frame_count += 1 - # Detecção de rostos - boxes, _ = mtcnn.detect(frame) - - if boxes is not None: - for box in boxes: - # Cortar o rosto detectado - x1, y1, x2, y2 = [int(coord) for coord in box] - face = frame[y1:y2, x1:x2] - - # Salvar o rosto na pasta de saída - face_filename = os.path.join(output_folder, f"face_{frame_count}_{face_count}.jpg") - cv2.imwrite(face_filename, face) - face_count += 1 - - # Mostrar o progresso (opcional) - print(f"Frame {frame_count} processado.") - - cap.release() - print(f"Processamento concluído. {face_count} rostos salvos em {output_folder}.") - -# Função principal para parsear argumentos e chamar o processamento -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Detecta e salva rostos de um vídeo.") - parser.add_argument("--source", type=str, required=True, help="Caminho para o arquivo de vídeo.") - parser.add_argument("--output", type=str, required=True, help="Pasta de saída para salvar os rostos detectados.") - args = parser.parse_args() - - process_video(args.source, args.output) diff --git a/makefile b/makefile deleted file mode 100644 index 8e2d945..0000000 --- a/makefile +++ /dev/null @@ -1,101 +0,0 @@ -# Variáveis de ambiente -DOCKER_IMAGE=front-face-recognition -DOCKER_IMAGE_DLIB=dlib-build-image -DOCKER_TAG=latest -LATEST_TAG=latest -AWS_REGION=us-east-2 - -# Verificação de quem é o usuário e carregamento das variáveis -WHOAMI=$(shell whoami) - -ifeq ($(WHOAMI),gitlab-runner) - AWS_ACCESS_KEY_ID ?= $(AWS_ACCESS_KEY_ID) - AWS_SECRET_ACCESS_KEY ?= $(AWS_SECRET_ACCESS_KEY) - DOCKER_REGISTRY ?= $(shell echo 794038208959.dkr.ecr.$(AWS_REGION).amazonaws.com) -else ifeq ($(WHOAMI),verde001) - AWS_ACCESS_KEY_ID=$(shell awk '/aws_access_key_id/ { print $$3 }' ~/.aws/credentials) - AWS_SECRET_ACCESS_KEY=$(shell awk '/aws_secret_access_key/ { print $$3 }' ~/.aws/credentials) - AWS_PROFILE=$(shell awk '/profile/ { print $$2 }' ~/.aws/config) - DOCKER_REGISTRY ?= $(shell echo 794038208959.dkr.ecr.$(AWS_REGION).amazonaws.com) -endif - -.PHONY: all build login-aws pull-latest push publish deploy run stop logs clean format check help - -# Alvo principal que executa todas as etapas -all: build login-aws pull-latest push - -# Nome da imagem do Docker -IMAGE_NAME=front-face-recognition -PUBLIC_IP=18.119.123.240 - -# Login no AWS ECR -login-aws: ## Faz o login no AWS ECR - @echo "Logando no AWS ECR" - aws ecr get-login-password --region $(AWS_REGION) | docker login --username AWS --password-stdin $(DOCKER_REGISTRY) - -# Constrói a imagem Docker -build: ## Constrói a imagem Docker - docker build -t $(DOCKER_IMAGE):$(LATEST_TAG) . - -build-dlib: ## Constrói a imagem Docker do dlib - docker build -t $(DOCKER_IMAGE_DLIB):$(LATEST_TAG) Dockerfile-dlib - -# Puxa a imagem mais recente (latest) do repositório -pull-latest: ## Puxa a imagem mais recente (latest) do repositório - @echo "Puxando a imagem mais recente (latest)" - docker pull $(DOCKER_REGISTRY)/$(DOCKER_IMAGE):$(LATEST_TAG) || true - -# Publica a imagem no Docker Registry (com o SHA do commit e latest) -publish: ## Publica a imagem no Docker Registry - @echo "Tagueando e enviando as imagens" - # Tag também como latest - docker tag $(DOCKER_IMAGE):$(LATEST_TAG) $(DOCKER_REGISTRY)/$(DOCKER_IMAGE):$(LATEST_TAG) - docker push $(DOCKER_REGISTRY)/$(DOCKER_IMAGE):$(LATEST_TAG) - -# Deploy para o EC2 -deploy: ## Realiza o deploy no EC2 - @echo "Deploy para o EC2 em andamento..." - ansible-playbook -i infraestrutura/hosts infraestrutura/deploy.yml - -deploy-ci: ## Realiza o deploy no EC2 em CI - @echo "Deploy para o EC2 em andamento..." - ansible-playbook -i infraestrutura/hosts-ci infraestrutura/deploy.yml - -db: ## Realiza o deploy do Redis e MinIO - @echo "Deploy do Redis e MinIO em andamento..." - ansible-playbook -i infraestrutura/hosts infraestrutura/database.yml - -ssh: ## Acessar via SSH - chmod 400 cred/vm_dev_key.pem - ssh -i cred/vm_dev_key.pem ubuntu@$(PUBLIC_IP) - -# Executa o contêiner Docker em segundo plano -run: ## Executa o contêiner Docker em segundo plano - docker run -d -p 5001:5001 --restart always --name $(IMAGE_NAME)_container $(DOCKER_IMAGE):$(LATEST_TAG) - -# Mostra os logs do contêiner em execução -logs: ## Exibe os logs do contêiner em execução - docker logs -f $(IMAGE_NAME)_container - -# Para e remove o contêiner Docker -stop: ## Para e remove o contêiner Docker - docker stop $(IMAGE_NAME)_container || true - docker rm $(IMAGE_NAME)_container || true - -# Limpa as imagens e contêineres Docker -clean: ## Limpa as imagens e contêineres Docker - make stop - docker rmi $(DOCKER_IMAGE):$(DOCKER_TAG) || true - -# Formata o código na pasta src usando black -format: ## Formata o código na pasta src usando black - black src - -# Roda os testes de sistema com unittest -check: ## Roda os testes de sistema usando unittest - python -m unittest discover -s tests -p "*.py" - -# Exibe a mensagem de ajuda -help: ## Exibe esta mensagem de ajuda - @echo "Escolha um alvo para executar:" - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index ab84b39..0000000 --- a/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -Flask==2.3.3 -requests==2.31.0 -unittest-xml-reporting==3.1.0 -Pillow==9.5.0 -pytest==7.0.0 # ou a versão mais recente do pytest diff --git a/static/style.css b/static/style.css deleted file mode 100644 index c2207d6..0000000 --- a/static/style.css +++ /dev/null @@ -1,32 +0,0 @@ -body { - font-family: Arial, sans-serif; - margin: 20px; -} - -h1 { - text-align: center; - margin-bottom: 20px; -} - -table { - width: 100%; - border-collapse: collapse; -} - -th, td { - padding: 10px; - text-align: left; -} - -th { - background-color: #f4f4f4; -} - -tr:nth-child(even) { - background-color: #f9f9f9; -} - -p { - text-align: center; - font-size: 18px; -} diff --git a/static/styleappy.css b/static/styleappy.css deleted file mode 100644 index 0c8669b..0000000 --- a/static/styleappy.css +++ /dev/null @@ -1,87 +0,0 @@ -body { - font-family: Arial, sans-serif; - background-color: #f0f8ff; - color: #333; - margin: 0; - padding: 0; - line-height: 1.6; -} -.title { -font-size: 2.5em; -font-weight: bold; -color: #1e90ff; -text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1); -margin: 20px 0; -text-align: center; -} -label { - font-weight: bold; - margin-bottom: 5px; - display: block; - color: #1e90ff; -} - -input { - padding: 8px; - border: 1px solid #ccc; - border-radius: 4px; -} - -.container { - display: flex; - gap: 20px; - justify-content: center; - align-items: flex-start; - padding: 20px; -} - -.form-container { - background: linear-gradient(135deg, #e6f7ff, #cce7ff); - border: 1px solid #a3d8ff; - padding: 20px; - border-radius: 8px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); - width: 45%; -} - -pre { - background-color: #e6f7ff; - padding: 15px; - border: 1px solid #a3d8ff; - border-radius: 8px; - overflow-x: auto; - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05); -} - -img { - max-width: 100%; - height: auto; - display: block; - margin-top: 10px; - border: 2px solid #a3d8ff; - border-radius: 8px; - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); -} -h2{ - color: #1e90ff; -} - -button { - background-color: #4da6ff; - color: #fff; - border: none; - padding: 10px 15px; - cursor: pointer; - border-radius: 5px; - transition: background-color 0.3s ease; - box-shadow: 0 3px 6px rgba(0, 0, 0, 0.1); -} - -button:hover { - background-color: #1e90ff; -} - -button:active { - background-color: #0d6efd; - box-shadow: inset 0 3px 6px rgba(0, 0, 0, 0.2); -} \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/teste_unitario.py b/tests/teste_unitario.py deleted file mode 100644 index 95d370d..0000000 --- a/tests/teste_unitario.py +++ /dev/null @@ -1,91 +0,0 @@ -import pytest -import unittest -from io import BytesIO -from app import app - -@pytest.fixture -def client(): - app.config['TESTING'] = True - with app.test_client() as client: - yield client - -class TestExample(unittest.TestCase): - def test_addition(self): - self.assertEqual(1 + 1, 2) - - -def test_index(client): - response = client.get('/') - assert response.status_code == 200 - assert b'