Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

teste #4

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d2b76d9
Merge pull request #2 from LSIIM-Eye-Tracker/refactor
CodeWracker Aug 27, 2023
988b648
coloquei os argumentos em cli e escrevi isso na doc
CodeWracker Aug 27, 2023
1b131da
readme
CodeWracker Aug 27, 2023
e20d3a2
.
CodeWracker Aug 27, 2023
1bd78c3
teste depois da renbomeação da org
CodeWracker Oct 18, 2023
ae60b6c
corrigido para funcionar com processamento em lote
CodeWracker Oct 19, 2023
876c809
corrigi o multicore e corrigi o uso de memoria (eu passo o frame no d…
CodeWracker Oct 19, 2023
1bfc53a
correção de logs
CodeWracker Oct 19, 2023
4f82bf7
AJUSTES
CodeWracker Oct 19, 2023
b83575c
agora ele salva uma tela preta nos frames que não conseguiu ler
CodeWracker Oct 19, 2023
3df0051
troquei os nomes para ser da orientação do rosto
CodeWracker Apr 11, 2024
010ca92
tentei adicionar o gaze do olho
CodeWracker Apr 11, 2024
daef56c
pego o gaze de cada olho, ainda falta salvar
CodeWracker Apr 11, 2024
fdbcae9
salvando os dados de gaze (depois para reconstruir o vetor em 3d vai …
CodeWracker Apr 11, 2024
55859a6
coloquei pra salvar a posição do nariz pra poder descontar o moviment…
CodeWracker Apr 12, 2024
a689352
comecei um alg pra gerar visualizações dos dados
CodeWracker Apr 12, 2024
f73d3e1
agora to salvando a visualização da amplitude de movimento
CodeWracker Apr 12, 2024
cd05261
extrai a função de filtro de outliers e smoothing
CodeWracker Apr 13, 2024
036c8d1
pega o angulo (e deixa negativo dependendo do lado)
CodeWracker Apr 13, 2024
00806ab
extrai a função de desenhar o gráfico para uma função separada, que r…
CodeWracker Apr 13, 2024
21d2518
extrai tudo pra fora e chamei para os dois olhos o gaze
CodeWracker Apr 13, 2024
66a0e69
extrai todo o conteudo da função de fixation e deixei ela processar o…
CodeWracker Apr 13, 2024
b4dc56e
tinha esquecido dos filtros nos movimentos verticais e horizontal
CodeWracker Apr 13, 2024
e080110
como agora o angulo pode ser negativo, eu removo outliers de baixo tb
CodeWracker Apr 13, 2024
40116cf
update readme
CodeWracker Apr 13, 2024
6db60c2
Criei um workflow que verifica pull requests
CodeWracker Apr 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Verifica Pull Request

on:
pull_request:
types: [opened, reopened, labeled, review_requested, assigned]

jobs:
check-pr:
runs-on: ubuntu-latest
steps:
- name: Checar labels
uses: actions/github-script@v3
with:
script: |
const pullRequest = github.context.payload.pull_request;
if (pullRequest.labels.length === 0) {
core.setFailed("Pull Request deve ter pelo menos um label.");
}

- name: Checar reviewers
uses: actions/github-script@v3
with:
script: |
const pullRequest = github.context.payload.pull_request;
const reviewsRequested = pullRequest.requested_reviewers.length + pullRequest.requested_teams.length;
if (reviewsRequested === 0) {
core.setFailed("Pull Request deve ter pelo menos um reviewer.");
}

- name: Checar assignees
uses: actions/github-script@v3
with:
script: |
const pullRequest = github.context.payload.pull_request;
if (pullRequest.assignees.length === 0) {
core.setFailed("Pull Request deve ter pelo menos um assignee.");
}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ vds/*
build/*
dst/mediapippe/*
mediapipe/*
dst/vds/*
dst/vds/*
Pipefile.lock
31 changes: 19 additions & 12 deletions Face.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@

from face_mesh_module import FaceMeshDetector
from eye_feature_detector_module import EyeModule
from gaze_module import GazeEstimator
from gaze_module import HeadOrientationEstimator, EyeGazeEstimator
from definitions import *


class Face():
def __init__(self, image, logging = False):
self.image = image.copy()
def __init__(self, logging = False):
self.image = None
self._face_mesh_detector = FaceMeshDetector()
self._gaze_estimator = None
self._head_orientation_estimator = None
self._eye_gaze_estimator = None
self._eye_module = None
self.logging = logging
self.lms_3d = None
Expand All @@ -24,13 +23,20 @@ def __init__(self, image, logging = False):
self.right_pupil = None
self.face_border = None
self.nose_2d = None
self.gaze_vector = None
self.head_orientation_vector = None
self.left_eye_gaze = None
self.right_eye_gaze = None

def detect_gaze(self):
self._gaze_estimator = GazeEstimator( self.lms_3d, self.image.shape[0], self.image.shape[1])
gaze_vector, nose_2d = self._gaze_estimator.get_gaze_vector()
def detect_head_orientation(self):
self._head_orientation_estimator = HeadOrientationEstimator( self.lms_3d, self.image.shape[0], self.image.shape[1])
head_orientation_vector, nose_2d = self._head_orientation_estimator.get_head_orientation_vector()
self.nose_2d = nose_2d
self.gaze_vector = gaze_vector
self.head_orientation_vector = head_orientation_vector

def detect_eyes_gaze(self):
self._eye_gaze_estimator = EyeGazeEstimator(self.image.shape)
self.left_eye_gaze, self.right_eye_gaze = self._eye_gaze_estimator.get_eye_gaze_vector(self.lms_3d)


def get_position_data_as_dict(self):
return {
Expand All @@ -42,7 +48,8 @@ def get_position_data_as_dict(self):
}
def init_eye_module(self):
self._eye_module = EyeModule(self.image, self.lms_2d)
def detect_face(self):
def detect_face(self, image):
self.image = image
self.lms_3d = self._face_mesh_detector.findFaceMesh(self.image)
if self.lms_3d is None:
if self.logging:
Expand Down
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ mediapipe = "*"
tqdm = "*"
scipy = "*"
pandas = "*"
plotly = "*"
kaleido = "==0.1.0post1"

[dev-packages]
pyinstaller = "*"
Expand Down
1,046 changes: 715 additions & 331 deletions Pipfile.lock

Large diffs are not rendered by default.

108 changes: 106 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ A combinação que teve o melhor resultado foi analisar o rosto com o mediapipe

Com a imagem correspondente a cada olho foi-se feite uma analise de histograma das cores da imagem, apos alguns filtros serem aplicados, para tentar analisar onde estavam a iris e a pupila. O resultado foi que a pupia é razoavelmente fácil e consistente de se obter, contudo, a iris não. Por conta disso será adicionada mais uma etapa no processo de analise, com um outro algorítimo da mediapipe, o qual extrai a posição da iris de um rosto.

## Pré-requisitos

- Python 3.9
- pipenv

## Como rodar

Eu utilizo o gerenciador de pacotes pipenv, caso não o tenha instalado execute `pip install pipenv`
Expand All @@ -14,14 +19,113 @@ Para rodar o programa:

- `pipenv shell`
- `pipenv install`
- `python eye_tracker.py`
- `python main.py [argumentos]`

## Criar o executavel

```
$ pipenv run pyinstaller --onefile --paths C:\Users\Rodrigo\.virtualenvs\eye-tracking-opencv-2R_2QBtr ./eye_tracker.py --add-data 'C:\Users\Rodrigo\.virtualenvs\eye-tracking-opencv-2R_2QBtr\Lib\site-packages\mediapipe\modules:mediapipe/modules' --add-data 'C:\Users\Rodrigo\.virtualenvs\eye-tracking-opencv-2R_2QBtr\Lib\site-packages\mediapipe\python\solutions:mediapipe/solutions'
pipenv run pyinstaller --onefile --paths [seu_caminho] ./main.py --add-data '[seu_caminho]\Lib\site-packages\mediapipe\modules:mediapipe/modules' --add-data '[seu_caminho]\Lib\site-packages\mediapipe\python\solutions:mediapipe/solutions'

```

Substitua [seu_caminho] pelo caminho apropriado do seu ambiente.

## Regras

PROIBIDO colocar pastas que contenham o caractere '.' no nome dentro do diretório /raw para o processamento em lote

## Documentação de Argumentos CLI

### Descrição

O script aceita vários argumentos de linha de comando para configurar suas opções globais. Abaixo estão as opções disponíveis e suas descrições.

### Argumentos

#### -showprocess

Define se o processo será mostrado.

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: n

#### -drawbb

Define se a bounding box será desenhada.

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: n

#### -drawir

Define se a íris será desenhada.

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: n

#### -drawpu

Define se a pupila será desenhada.

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: n

#### -drawpp

Define se as posições passadas serão desenhadas.

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: s

#### -drawmp

Define se os pontos da máscara serão desenhados.

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: n

#### -drawheadpose

Define se o vetor de direção da cabeça vai ser mostrado

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: n

#### -draweyegaze

Define se os vetores de direção do olhar de ambos os olhos vão ser mostrados

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: n

#### -showwarn

Define se os avisos serão mostrados.

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: s

#### -multicore

Define se o processamento multicore será usado.

- Valores aceitos: s (sim) ou n (não)
- Valor padrão: n

#### -overwrite

Define se os arquivos existentes serão sobrescritos. Se -multicore for s, o valor padrão é s. Caso contrário, o valor padrão é n.

- Valores aceitos: s (sim) ou n (não)

#### -path

Define o caminho para os arquivos.

- Valor padrão: ""./vds"

##### Exemplo de Uso

`python main.py -showprocess s -drawbb n -path "./meus_arquivos"`

> Nota: Se um argumento inválido for fornecido para uma opção, o script imprimirá uma mensagem de erro e encerrará sua execução.
29 changes: 27 additions & 2 deletions drawing_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,33 @@

from definitions import *

def draw_gaze(image, gaze_vector, nose_2d):
x,y,z = gaze_vector
def draw_eye_gaze(image, left_pupil, left_gaze, right_pupil, right_gaze):
if(left_pupil == 0 or right_pupil == 0 or left_pupil == None or right_pupil == None):
return image
left_pupil_pos, left_pupil_radius = left_pupil
right_pupil_pos, right_pupil_radius = right_pupil

if left_gaze is not None:
left_gaze_x, left_gaze_y = left_gaze

p1_left = (int(left_pupil_pos[0]), int(left_pupil_pos[1]))
p2_left = (int(left_gaze[0]), int(left_gaze[1]))

image = cv2.line(image, p1_left, p2_left, (0, 0, 255), 2)


if right_gaze is not None:
right_gaze_x, right_gaze_y = right_gaze
p1_right = (int(right_pupil_pos[0]), int(right_pupil_pos[1]))
p2_right = (int(right_gaze[0]), int(right_gaze[1]))

image = cv2.line(image, p1_right, p2_right, (0, 0, 255), 2)

return image


def draw_head_orientation(image, head_orientation_vector, nose_2d):
x,y,z = head_orientation_vector
p1 = (int(nose_2d[0]), int(nose_2d[1]))
p2 = (int(nose_2d[0] + y*10), int(nose_2d[1] - x*10))

Expand Down
2 changes: 1 addition & 1 deletion face_mesh_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ def findFaceMesh(self, image):
# mesh_points=np.array([np.multiply([p.x, p.y], [img_w, img_h]).astype(int) for p in results.multi_face_landmarks[0].landmark])
mesh_points_3d = np.array([np.multiply([p.x, p.y, p.z], [img_w, img_h, 1]).astype(float) for p in results.multi_face_landmarks[0].landmark])

return mesh_points_3d
return mesh_points_3d # teh points are normalized to [-1, 1] and returned as (x, y, z) format
else:
return None
Loading
Loading