Upload 29 files
Browse files- .gitattributes +7 -0
- GazeTracking/.gitignore +104 -0
- GazeTracking/Blinks_pupil.py +33 -0
- GazeTracking/Dockerfile +13 -0
- GazeTracking/LICENSE +21 -0
- GazeTracking/Location_eye_csv.py +87 -0
- GazeTracking/README.md +172 -0
- GazeTracking/aayfryxljh.mp4 +3 -0
- GazeTracking/adadagaze_tracked_output.avi +3 -0
- GazeTracking/build_and_run.sh +12 -0
- GazeTracking/environment.yml +9 -0
- GazeTracking/example.py +74 -0
- GazeTracking/fake.mp4 +3 -0
- GazeTracking/fake_gaze_data.csv +600 -0
- GazeTracking/fake_gaze_tracked_output.avi +3 -0
- GazeTracking/gaze_data.csv +300 -0
- GazeTracking/gaze_tracked_output.avi +3 -0
- GazeTracking/gaze_tracking/__init__.py +1 -0
- GazeTracking/gaze_tracking/__pycache__/__init__.cpython-312.pyc +0 -0
- GazeTracking/gaze_tracking/__pycache__/calibration.cpython-312.pyc +0 -0
- GazeTracking/gaze_tracking/__pycache__/eye.cpython-312.pyc +0 -0
- GazeTracking/gaze_tracking/__pycache__/gaze_tracking.cpython-312.pyc +0 -0
- GazeTracking/gaze_tracking/__pycache__/pupil.cpython-312.pyc +0 -0
- GazeTracking/gaze_tracking/calibration.py +77 -0
- GazeTracking/gaze_tracking/eye.py +119 -0
- GazeTracking/gaze_tracking/gaze_tracking.py +133 -0
- GazeTracking/gaze_tracking/pupil.py +54 -0
- GazeTracking/gaze_tracking/trained_models/shape_predictor_68_face_landmarks.dat +3 -0
- GazeTracking/real.mp4 +3 -0
- GazeTracking/requirements.txt +3 -0
.gitattributes
CHANGED
@@ -33,3 +33,10 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
GazeTracking/aayfryxljh.mp4 filter=lfs diff=lfs merge=lfs -text
|
37 |
+
GazeTracking/adadagaze_tracked_output.avi filter=lfs diff=lfs merge=lfs -text
|
38 |
+
GazeTracking/fake_gaze_tracked_output.avi filter=lfs diff=lfs merge=lfs -text
|
39 |
+
GazeTracking/fake.mp4 filter=lfs diff=lfs merge=lfs -text
|
40 |
+
GazeTracking/gaze_tracked_output.avi filter=lfs diff=lfs merge=lfs -text
|
41 |
+
GazeTracking/gaze_tracking/trained_models/shape_predictor_68_face_landmarks.dat filter=lfs diff=lfs merge=lfs -text
|
42 |
+
GazeTracking/real.mp4 filter=lfs diff=lfs merge=lfs -text
|
GazeTracking/.gitignore
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Byte-compiled / optimized / DLL files
|
2 |
+
__pycache__/
|
3 |
+
*.py[cod]
|
4 |
+
*$py.class
|
5 |
+
|
6 |
+
# C extensions
|
7 |
+
*.so
|
8 |
+
|
9 |
+
# Distribution / packaging
|
10 |
+
.Python
|
11 |
+
build/
|
12 |
+
develop-eggs/
|
13 |
+
dist/
|
14 |
+
downloads/
|
15 |
+
eggs/
|
16 |
+
.eggs/
|
17 |
+
lib/
|
18 |
+
lib64/
|
19 |
+
parts/
|
20 |
+
sdist/
|
21 |
+
var/
|
22 |
+
wheels/
|
23 |
+
*.egg-info/
|
24 |
+
.installed.cfg
|
25 |
+
*.egg
|
26 |
+
MANIFEST
|
27 |
+
|
28 |
+
# PyInstaller
|
29 |
+
# Usually these files are written by a python script from a template
|
30 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
31 |
+
*.manifest
|
32 |
+
*.spec
|
33 |
+
|
34 |
+
# Installer logs
|
35 |
+
pip-log.txt
|
36 |
+
pip-delete-this-directory.txt
|
37 |
+
|
38 |
+
# Unit test / coverage reports
|
39 |
+
htmlcov/
|
40 |
+
.tox/
|
41 |
+
.coverage
|
42 |
+
.coverage.*
|
43 |
+
.cache
|
44 |
+
nosetests.xml
|
45 |
+
coverage.xml
|
46 |
+
*.cover
|
47 |
+
.hypothesis/
|
48 |
+
.pytest_cache/
|
49 |
+
|
50 |
+
# Translations
|
51 |
+
*.mo
|
52 |
+
*.pot
|
53 |
+
|
54 |
+
# Django stuff:
|
55 |
+
*.log
|
56 |
+
local_settings.py
|
57 |
+
db.sqlite3
|
58 |
+
|
59 |
+
# Flask stuff:
|
60 |
+
instance/
|
61 |
+
.webassets-cache
|
62 |
+
|
63 |
+
# Scrapy stuff:
|
64 |
+
.scrapy
|
65 |
+
|
66 |
+
# Sphinx documentation
|
67 |
+
docs/_build/
|
68 |
+
|
69 |
+
# PyBuilder
|
70 |
+
target/
|
71 |
+
|
72 |
+
# Jupyter Notebook
|
73 |
+
.ipynb_checkpoints
|
74 |
+
|
75 |
+
# pyenv
|
76 |
+
.python-version
|
77 |
+
|
78 |
+
# celery beat schedule file
|
79 |
+
celerybeat-schedule
|
80 |
+
|
81 |
+
# SageMath parsed files
|
82 |
+
*.sage.py
|
83 |
+
|
84 |
+
# Environments
|
85 |
+
.env
|
86 |
+
.venv
|
87 |
+
env/
|
88 |
+
venv/
|
89 |
+
ENV/
|
90 |
+
env.bak/
|
91 |
+
venv.bak/
|
92 |
+
|
93 |
+
# Spyder project settings
|
94 |
+
.spyderproject
|
95 |
+
.spyproject
|
96 |
+
|
97 |
+
# Rope project settings
|
98 |
+
.ropeproject
|
99 |
+
|
100 |
+
# mkdocs documentation
|
101 |
+
/site
|
102 |
+
|
103 |
+
# mypy
|
104 |
+
.mypy_cache/
|
GazeTracking/Blinks_pupil.py
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import csv
|
2 |
+
|
3 |
+
def analyze_gaze_data(csv_file):
|
4 |
+
inconsistent_data = []
|
5 |
+
irregular_blinks = []
|
6 |
+
|
7 |
+
with open(csv_file, 'r') as csvfile:
|
8 |
+
csv_reader = csv.reader(csvfile)
|
9 |
+
next(csv_reader) # Skip header row
|
10 |
+
|
11 |
+
for row in csv_reader:
|
12 |
+
frame_count, gaze_direction, left_pupil, right_pupil = row
|
13 |
+
|
14 |
+
# Check for inconsistencies in eye movement with pupil coordinates
|
15 |
+
if gaze_direction != "Blinking":
|
16 |
+
if left_pupil == "(None, None)" or right_pupil == "(None, None)":
|
17 |
+
inconsistent_data.append(frame_count)
|
18 |
+
|
19 |
+
# Check for irregular blinks
|
20 |
+
if gaze_direction == "Blinking":
|
21 |
+
irregular_blinks.append(frame_count)
|
22 |
+
|
23 |
+
return inconsistent_data, irregular_blinks
|
24 |
+
|
25 |
+
def main():
|
26 |
+
csv_file = 'fake_gaze_data.csv'
|
27 |
+
inconsistent_data, irregular_blinks = analyze_gaze_data(csv_file)
|
28 |
+
|
29 |
+
print("Inconsistent eye movement with pupil coordinates detected in frames:", inconsistent_data)
|
30 |
+
print("Irregular blinks detected in frames:", irregular_blinks)
|
31 |
+
|
32 |
+
if __name__ == "__main__":
|
33 |
+
main()
|
GazeTracking/Dockerfile
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM ubuntu:18.04
|
2 |
+
RUN apt-get update
|
3 |
+
RUN apt install -y python3
|
4 |
+
RUN apt install -y python3-pip
|
5 |
+
RUN apt install -y cmake
|
6 |
+
RUN apt install -y libsm6
|
7 |
+
RUN apt install -y libxext6
|
8 |
+
RUN apt install -y libxrender1
|
9 |
+
RUN apt install -y libfontconfig1
|
10 |
+
RUN pip3 install --upgrade pip
|
11 |
+
COPY . /home/GazeTracking
|
12 |
+
WORKDIR /home/GazeTracking
|
13 |
+
RUN pip3 install -r requirements.txt
|
GazeTracking/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2019 Antoine Lamé
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
GazeTracking/Location_eye_csv.py
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import csv
|
2 |
+
import cv2
|
3 |
+
from gaze_tracking import GazeTracking
|
4 |
+
|
5 |
+
# Replace 'video.mp4' with the path to your video file
|
6 |
+
video_path = 'real.mp4'
|
7 |
+
|
8 |
+
# Create a video capture object
|
9 |
+
cap = cv2.VideoCapture(video_path)
|
10 |
+
|
11 |
+
# Check if video opened successfully
|
12 |
+
if not cap.isOpened():
|
13 |
+
print("Error opening video!")
|
14 |
+
exit()
|
15 |
+
|
16 |
+
# Define output filename (change extension if needed)
|
17 |
+
output_filename = "fake_gaze_tracked_output.avi"
|
18 |
+
|
19 |
+
# Define video writer settings (adjust as needed)
|
20 |
+
fourcc = cv2.VideoWriter_fourcc(*'XVID')
|
21 |
+
out = cv2.VideoWriter(output_filename, fourcc, 20.0, (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))))
|
22 |
+
|
23 |
+
gaze = GazeTracking()
|
24 |
+
|
25 |
+
frame_count = 0
|
26 |
+
|
27 |
+
while True:
|
28 |
+
# Read a frame from the video
|
29 |
+
ret, frame = cap.read()
|
30 |
+
|
31 |
+
# Check if frame is read correctly
|
32 |
+
if not ret:
|
33 |
+
print("No frame captured from video. Exiting...")
|
34 |
+
break
|
35 |
+
|
36 |
+
# Open CSV file for appending gaze data
|
37 |
+
with open('fake_gaze_data.csv', 'a', newline='') as csvfile:
|
38 |
+
csv_writer = csv.writer(csvfile)
|
39 |
+
|
40 |
+
# Send the frame to GazeTracking for analysis
|
41 |
+
gaze.refresh(frame)
|
42 |
+
|
43 |
+
# Get the annotated frame with gaze information
|
44 |
+
annotated_frame = gaze.annotated_frame()
|
45 |
+
|
46 |
+
text = ""
|
47 |
+
|
48 |
+
if gaze.is_blinking():
|
49 |
+
text = "Blinking"
|
50 |
+
elif gaze.is_right():
|
51 |
+
text = "Looking right"
|
52 |
+
elif gaze.is_left():
|
53 |
+
text = "Looking left"
|
54 |
+
elif gaze.is_center():
|
55 |
+
text = "Looking center"
|
56 |
+
|
57 |
+
# Add text overlay on the frame
|
58 |
+
cv2.putText(annotated_frame, text, (90, 60), cv2.FONT_HERSHEY_DUPLEX, 1.6, (147, 58, 31), 2)
|
59 |
+
|
60 |
+
# Get pupil coordinates
|
61 |
+
left_pupil = gaze.pupil_left_coords()
|
62 |
+
right_pupil = gaze.pupil_right_coords()
|
63 |
+
|
64 |
+
# Add pupil coordinates overlay
|
65 |
+
cv2.putText(annotated_frame, "Left pupil: " + str(left_pupil), (90, 130), cv2.FONT_HERSHEY_DUPLEX, 0.9, (147, 58, 31), 1)
|
66 |
+
cv2.putText(annotated_frame, "Right pupil: " + str(right_pupil), (90, 165), cv2.FONT_HERSHEY_DUPLEX, 0.9, (147, 58, 31), 1)
|
67 |
+
|
68 |
+
# Update frame count
|
69 |
+
frame_count += 1
|
70 |
+
|
71 |
+
# Write gaze data to CSV file
|
72 |
+
csv_writer.writerow([frame_count, text, left_pupil, right_pupil])
|
73 |
+
|
74 |
+
# Display the frame
|
75 |
+
cv2.imshow("Demo", annotated_frame)
|
76 |
+
|
77 |
+
# Write the annotated frame to the output video
|
78 |
+
out.write(annotated_frame)
|
79 |
+
|
80 |
+
# Exit on 'Esc' key press
|
81 |
+
if cv2.waitKey(1) == 27:
|
82 |
+
break
|
83 |
+
|
84 |
+
# Release resources
|
85 |
+
cap.release()
|
86 |
+
out.release()
|
87 |
+
cv2.destroyAllWindows()
|
GazeTracking/README.md
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Gaze Tracking
|
2 |
+
|
3 |
+

|
4 |
+

|
5 |
+

|
6 |
+
[](https://github.com/antoinelame/GazeTracking/stargazers)
|
7 |
+
|
8 |
+
This is a Python (2 and 3) library that provides a **webcam-based eye tracking system**. It gives you the exact position of the pupils and the gaze direction, in real time.
|
9 |
+
|
10 |
+
[](https://youtu.be/YEZMk1P0-yw)
|
11 |
+
|
12 |
+
_🚀 Quick note: I'm looking for job opportunities as a software developer, for exciting projects in ambitious companies. Anywhere in the world. Send me an email!_
|
13 |
+
|
14 |
+
## Installation
|
15 |
+
|
16 |
+
Clone this project:
|
17 |
+
|
18 |
+
```shell
|
19 |
+
git clone https://github.com/antoinelame/GazeTracking.git
|
20 |
+
```
|
21 |
+
|
22 |
+
### For Pip install
|
23 |
+
Install these dependencies (NumPy, OpenCV, Dlib):
|
24 |
+
|
25 |
+
```shell
|
26 |
+
pip install -r requirements.txt
|
27 |
+
```
|
28 |
+
|
29 |
+
> The Dlib library has four primary prerequisites: Boost, Boost.Python, CMake and X11/XQuartx. If you doesn't have them, you can [read this article](https://www.pyimagesearch.com/2017/03/27/how-to-install-dlib/) to know how to easily install them.
|
30 |
+
|
31 |
+
|
32 |
+
### For Anaconda install
|
33 |
+
Install these dependencies (NumPy, OpenCV, Dlib):
|
34 |
+
|
35 |
+
```shell
|
36 |
+
conda env create --file environment.yml
|
37 |
+
#After creating environment, activate it
|
38 |
+
conda activate GazeTracking
|
39 |
+
```
|
40 |
+
|
41 |
+
|
42 |
+
### Verify Installation
|
43 |
+
|
44 |
+
Run the demo:
|
45 |
+
|
46 |
+
```shell
|
47 |
+
python example.py
|
48 |
+
```
|
49 |
+
|
50 |
+
## Simple Demo
|
51 |
+
|
52 |
+
```python
|
53 |
+
import cv2
|
54 |
+
from gaze_tracking import GazeTracking
|
55 |
+
|
56 |
+
gaze = GazeTracking()
|
57 |
+
webcam = cv2.VideoCapture(0)
|
58 |
+
|
59 |
+
while True:
|
60 |
+
_, frame = webcam.read()
|
61 |
+
gaze.refresh(frame)
|
62 |
+
|
63 |
+
new_frame = gaze.annotated_frame()
|
64 |
+
text = ""
|
65 |
+
|
66 |
+
if gaze.is_right():
|
67 |
+
text = "Looking right"
|
68 |
+
elif gaze.is_left():
|
69 |
+
text = "Looking left"
|
70 |
+
elif gaze.is_center():
|
71 |
+
text = "Looking center"
|
72 |
+
|
73 |
+
cv2.putText(new_frame, text, (60, 60), cv2.FONT_HERSHEY_DUPLEX, 2, (255, 0, 0), 2)
|
74 |
+
cv2.imshow("Demo", new_frame)
|
75 |
+
|
76 |
+
if cv2.waitKey(1) == 27:
|
77 |
+
break
|
78 |
+
```
|
79 |
+
|
80 |
+
## Documentation
|
81 |
+
|
82 |
+
In the following examples, `gaze` refers to an instance of the `GazeTracking` class.
|
83 |
+
|
84 |
+
### Refresh the frame
|
85 |
+
|
86 |
+
```python
|
87 |
+
gaze.refresh(frame)
|
88 |
+
```
|
89 |
+
|
90 |
+
Pass the frame to analyze (numpy.ndarray). If you want to work with a video stream, you need to put this instruction in a loop, like the example above.
|
91 |
+
|
92 |
+
### Position of the left pupil
|
93 |
+
|
94 |
+
```python
|
95 |
+
gaze.pupil_left_coords()
|
96 |
+
```
|
97 |
+
|
98 |
+
Returns the coordinates (x,y) of the left pupil.
|
99 |
+
|
100 |
+
### Position of the right pupil
|
101 |
+
|
102 |
+
```python
|
103 |
+
gaze.pupil_right_coords()
|
104 |
+
```
|
105 |
+
|
106 |
+
Returns the coordinates (x,y) of the right pupil.
|
107 |
+
|
108 |
+
### Looking to the left
|
109 |
+
|
110 |
+
```python
|
111 |
+
gaze.is_left()
|
112 |
+
```
|
113 |
+
|
114 |
+
Returns `True` if the user is looking to the left.
|
115 |
+
|
116 |
+
### Looking to the right
|
117 |
+
|
118 |
+
```python
|
119 |
+
gaze.is_right()
|
120 |
+
```
|
121 |
+
|
122 |
+
Returns `True` if the user is looking to the right.
|
123 |
+
|
124 |
+
### Looking at the center
|
125 |
+
|
126 |
+
```python
|
127 |
+
gaze.is_center()
|
128 |
+
```
|
129 |
+
|
130 |
+
Returns `True` if the user is looking at the center.
|
131 |
+
|
132 |
+
### Horizontal direction of the gaze
|
133 |
+
|
134 |
+
```python
|
135 |
+
ratio = gaze.horizontal_ratio()
|
136 |
+
```
|
137 |
+
|
138 |
+
Returns a number between 0.0 and 1.0 that indicates the horizontal direction of the gaze. The extreme right is 0.0, the center is 0.5 and the extreme left is 1.0.
|
139 |
+
|
140 |
+
### Vertical direction of the gaze
|
141 |
+
|
142 |
+
```python
|
143 |
+
ratio = gaze.vertical_ratio()
|
144 |
+
```
|
145 |
+
|
146 |
+
Returns a number between 0.0 and 1.0 that indicates the vertical direction of the gaze. The extreme top is 0.0, the center is 0.5 and the extreme bottom is 1.0.
|
147 |
+
|
148 |
+
### Blinking
|
149 |
+
|
150 |
+
```python
|
151 |
+
gaze.is_blinking()
|
152 |
+
```
|
153 |
+
|
154 |
+
Returns `True` if the user's eyes are closed.
|
155 |
+
|
156 |
+
### Webcam frame
|
157 |
+
|
158 |
+
```python
|
159 |
+
frame = gaze.annotated_frame()
|
160 |
+
```
|
161 |
+
|
162 |
+
Returns the main frame with pupils highlighted.
|
163 |
+
|
164 |
+
## You want to help?
|
165 |
+
|
166 |
+
Your suggestions, bugs reports and pull requests are welcome and appreciated. You can also starring ⭐️ the project!
|
167 |
+
|
168 |
+
If the detection of your pupils is not completely optimal, you can send me a video sample of you looking in different directions. I would use it to improve the algorithm.
|
169 |
+
|
170 |
+
## Licensing
|
171 |
+
|
172 |
+
This project is released by Antoine Lamé under the terms of the MIT Open Source License. View LICENSE for more information.
|
GazeTracking/aayfryxljh.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:da7683e58ebd3684b21ea4815bf9bd3484ffebebe47484489da7c1df5e356f82
|
3 |
+
size 10114027
|
GazeTracking/adadagaze_tracked_output.avi
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:395f80cdccab9c1398f05227990d3e995a104b4ee15be30a63a16ecdc5d8710c
|
3 |
+
size 9030194
|
GazeTracking/build_and_run.sh
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
IMAGE_NAME=gaze-tracking
|
2 |
+
|
3 |
+
# allow root access to x server
|
4 |
+
xhost local:root
|
5 |
+
# build and run docker image
|
6 |
+
([ "$(docker images -q ${IMAGE_NAME})" == "" ] && docker build -t ${IMAGE_NAME} . )
|
7 |
+
([ "$(docker images -q ${IMAGE_NAME})" != "" ] && \
|
8 |
+
docker run --rm --device /dev/video0 \
|
9 |
+
-e DISPLAY=${DISPLAY} \
|
10 |
+
-v /tmp/.X11-unix:/tmp/.X11-unix \
|
11 |
+
--env="QT_X11_NO_MITSHM=1" \
|
12 |
+
-it ${IMAGE_NAME} bash)
|
GazeTracking/environment.yml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: GazeTracking
|
2 |
+
channels:
|
3 |
+
- conda-forge
|
4 |
+
- anaconda
|
5 |
+
- defaults
|
6 |
+
dependencies:
|
7 |
+
- numpy == 1.16.1
|
8 |
+
- opencv == 3.4.*
|
9 |
+
- dlib == 19.17.*
|
GazeTracking/example.py
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
from gaze_tracking import GazeTracking
|
3 |
+
|
4 |
+
# Replace 'video.mp4' with the path to your video file
|
5 |
+
video_path = 'apvzjkvnwn.mp4'
|
6 |
+
|
7 |
+
# Create a video capture object
|
8 |
+
cap = cv2.VideoCapture(video_path)
|
9 |
+
|
10 |
+
# Check if video opened successfully
|
11 |
+
if not cap.isOpened():
|
12 |
+
print("Error opening video!")
|
13 |
+
exit()
|
14 |
+
|
15 |
+
# Define output filename (change extension if needed)
|
16 |
+
output_filename = "gaze_tracked_output.avi"
|
17 |
+
|
18 |
+
# Define video writer settings (adjust as needed)
|
19 |
+
fourcc = cv2.VideoWriter_fourcc(*'XVID')
|
20 |
+
out = cv2.VideoWriter(output_filename, fourcc, 20.0, (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))))
|
21 |
+
|
22 |
+
gaze = GazeTracking()
|
23 |
+
|
24 |
+
while True:
|
25 |
+
# Read a frame from the video
|
26 |
+
ret, frame = cap.read()
|
27 |
+
|
28 |
+
# Check if frame is read correctly
|
29 |
+
if not ret:
|
30 |
+
print("No frame captured from video. Exiting...")
|
31 |
+
break
|
32 |
+
|
33 |
+
# Send the frame to GazeTracking for analysis
|
34 |
+
gaze.refresh(frame)
|
35 |
+
|
36 |
+
# Get the annotated frame with gaze information
|
37 |
+
annotated_frame = gaze.annotated_frame()
|
38 |
+
|
39 |
+
text = ""
|
40 |
+
|
41 |
+
if gaze.is_blinking():
|
42 |
+
text = "Blinking"
|
43 |
+
elif gaze.is_right():
|
44 |
+
text = "Looking right"
|
45 |
+
elif gaze.is_left():
|
46 |
+
text = "Looking left"
|
47 |
+
elif gaze.is_center():
|
48 |
+
text = "Looking center"
|
49 |
+
|
50 |
+
# Add text overlay on the frame
|
51 |
+
cv2.putText(annotated_frame, text, (90, 60), cv2.FONT_HERSHEY_DUPLEX, 1.6, (147, 58, 31), 2)
|
52 |
+
|
53 |
+
# Get pupil coordinates
|
54 |
+
left_pupil = gaze.pupil_left_coords()
|
55 |
+
right_pupil = gaze.pupil_right_coords()
|
56 |
+
|
57 |
+
# Add pupil coordinates overlay
|
58 |
+
cv2.putText(annotated_frame, "Left pupil: " + str(left_pupil), (90, 130), cv2.FONT_HERSHEY_DUPLEX, 0.9, (147, 58, 31), 1)
|
59 |
+
cv2.putText(annotated_frame, "Right pupil: " + str(right_pupil), (90, 165), cv2.FONT_HERSHEY_DUPLEX, 0.9, (147, 58, 31), 1)
|
60 |
+
|
61 |
+
# Display the frame
|
62 |
+
cv2.imshow("Demo", annotated_frame)
|
63 |
+
|
64 |
+
# Write the annotated frame to the output video
|
65 |
+
out.write(annotated_frame)
|
66 |
+
|
67 |
+
# Exit on 'Esc' key press
|
68 |
+
if cv2.waitKey(1) == 27:
|
69 |
+
break
|
70 |
+
|
71 |
+
# Release resources
|
72 |
+
cap.release()
|
73 |
+
out.release()
|
74 |
+
cv2.destroyAllWindows()
|
GazeTracking/fake.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:e0c586c4e632586efde54be8fd4219c89ac5d585edceafdcb1e8f2654eee6224
|
3 |
+
size 4110523
|
GazeTracking/fake_gaze_data.csv
ADDED
@@ -0,0 +1,600 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
1,Looking center,"(1037, 354)","(1148, 353)"
|
2 |
+
2,Looking left,"(1050, 361)","(1147, 354)"
|
3 |
+
3,Blinking,"(1054, 370)","(1140, 367)"
|
4 |
+
4,Blinking,"(1057, 369)","(1141, 367)"
|
5 |
+
5,Blinking,"(1058, 363)","(1134, 363)"
|
6 |
+
6,Looking left,"(1054, 357)","(1156, 354)"
|
7 |
+
7,Looking left,"(1054, 353)","(1158, 353)"
|
8 |
+
8,Looking left,"(1054, 352)","(1157, 350)"
|
9 |
+
9,Looking left,"(1053, 349)","(1156, 349)"
|
10 |
+
10,Looking center,"(1061, 354)","(1134, 355)"
|
11 |
+
11,Blinking,"(1059, 360)","(1141, 358)"
|
12 |
+
12,Blinking,"(1059, 360)","(1142, 359)"
|
13 |
+
13,Looking left,"(1060, 361)","(1160, 358)"
|
14 |
+
14,Looking left,"(1059, 363)","(1162, 362)"
|
15 |
+
15,Looking left,"(1058, 368)","(1160, 365)"
|
16 |
+
16,Looking left,"(1054, 370)","(1160, 369)"
|
17 |
+
17,Looking left,"(1055, 370)","(1158, 371)"
|
18 |
+
18,Looking left,"(1053, 370)","(1156, 371)"
|
19 |
+
19,Looking left,"(1053, 371)","(1155, 371)"
|
20 |
+
20,Looking left,"(1051, 371)","(1154, 371)"
|
21 |
+
21,Looking left,"(1046, 371)","(1150, 371)"
|
22 |
+
22,Looking center,"(1037, 371)","(1144, 372)"
|
23 |
+
23,Looking center,"(1034, 372)","(1138, 373)"
|
24 |
+
24,Looking center,"(1033, 371)","(1137, 373)"
|
25 |
+
25,Looking center,"(1033, 371)","(1137, 372)"
|
26 |
+
26,Looking center,"(1032, 371)","(1136, 372)"
|
27 |
+
27,Looking center,"(1032, 372)","(1139, 370)"
|
28 |
+
28,Looking center,"(1031, 371)","(1136, 372)"
|
29 |
+
29,Looking center,"(1031, 372)","(1139, 370)"
|
30 |
+
30,Looking center,"(1032, 372)","(1139, 370)"
|
31 |
+
31,Looking center,"(1032, 372)","(1139, 372)"
|
32 |
+
32,Looking center,"(1033, 371)","(1140, 373)"
|
33 |
+
33,Looking center,"(1033, 371)","(1141, 372)"
|
34 |
+
34,Looking center,"(1035, 372)","(1141, 373)"
|
35 |
+
35,Looking center,"(1035, 371)","(1142, 373)"
|
36 |
+
36,Looking center,"(1035, 371)","(1142, 373)"
|
37 |
+
37,Looking center,"(1035, 371)","(1141, 373)"
|
38 |
+
38,Looking center,"(1035, 370)","(1141, 372)"
|
39 |
+
39,Looking center,"(1035, 370)","(1141, 372)"
|
40 |
+
40,Looking center,"(1034, 370)","(1140, 372)"
|
41 |
+
41,Looking center,"(1033, 370)","(1140, 371)"
|
42 |
+
42,Looking center,"(1034, 370)","(1139, 371)"
|
43 |
+
43,Looking center,"(1032, 369)","(1139, 372)"
|
44 |
+
44,Looking center,"(1032, 369)","(1138, 373)"
|
45 |
+
45,Looking center,"(1031, 369)","(1138, 372)"
|
46 |
+
46,Looking center,"(1030, 368)","(1136, 371)"
|
47 |
+
47,Looking center,"(1029, 367)","(1136, 370)"
|
48 |
+
48,Looking center,"(1028, 367)","(1135, 370)"
|
49 |
+
49,Looking center,"(1028, 367)","(1134, 370)"
|
50 |
+
50,Looking center,"(1028, 368)","(1134, 370)"
|
51 |
+
51,Looking center,"(1028, 367)","(1133, 369)"
|
52 |
+
52,Looking center,"(1027, 367)","(1133, 369)"
|
53 |
+
53,Looking center,"(1026, 367)","(1132, 368)"
|
54 |
+
54,Looking center,"(1026, 367)","(1132, 369)"
|
55 |
+
55,Looking center,"(1025, 367)","(1132, 368)"
|
56 |
+
56,Looking center,"(1026, 366)","(1132, 367)"
|
57 |
+
57,Looking center,"(1027, 367)","(1132, 369)"
|
58 |
+
58,Looking center,"(1027, 367)","(1132, 370)"
|
59 |
+
59,Looking center,"(1026, 369)","(1131, 372)"
|
60 |
+
60,,,
|
61 |
+
61,Blinking,"(1038, 382)","(1120, 381)"
|
62 |
+
62,Blinking,"(1038, 384)","(1121, 383)"
|
63 |
+
63,Blinking,"(1037, 382)","(1120, 382)"
|
64 |
+
64,Blinking,"(1036, 379)","(1119, 380)"
|
65 |
+
65,Looking center,"(1033, 376)","(1123, 378)"
|
66 |
+
66,Looking left,"(1030, 376)","(1130, 379)"
|
67 |
+
67,Looking left,"(1029, 374)","(1131, 380)"
|
68 |
+
68,Looking left,"(1028, 374)","(1131, 381)"
|
69 |
+
69,Looking center,"(1025, 375)","(1128, 381)"
|
70 |
+
70,Looking left,"(1024, 376)","(1127, 381)"
|
71 |
+
71,Looking left,"(1021, 378)","(1125, 383)"
|
72 |
+
72,Looking left,"(1020, 380)","(1123, 384)"
|
73 |
+
73,Looking left,"(1018, 381)","(1122, 385)"
|
74 |
+
74,Looking left,"(1017, 383)","(1121, 385)"
|
75 |
+
75,Looking left,"(1017, 383)","(1121, 385)"
|
76 |
+
76,Looking left,"(1017, 383)","(1121, 386)"
|
77 |
+
77,Looking center,"(1015, 386)","(1117, 389)"
|
78 |
+
78,Looking center,"(1015, 388)","(1116, 392)"
|
79 |
+
79,Looking center,"(1015, 389)","(1116, 393)"
|
80 |
+
80,Looking center,"(1016, 389)","(1118, 392)"
|
81 |
+
81,Looking center,"(1015, 390)","(1117, 393)"
|
82 |
+
82,Looking center,"(1014, 390)","(1116, 393)"
|
83 |
+
83,Looking center,"(1013, 390)","(1115, 393)"
|
84 |
+
84,Looking center,"(1009, 391)","(1110, 393)"
|
85 |
+
85,Looking center,"(1004, 393)","(1106, 390)"
|
86 |
+
86,Looking center,"(1000, 394)","(1101, 390)"
|
87 |
+
87,Looking center,"(994, 396)","(1094, 390)"
|
88 |
+
88,Looking center,"(990, 398)","(1089, 389)"
|
89 |
+
89,Looking center,"(988, 398)","(1087, 388)"
|
90 |
+
90,Looking center,"(988, 399)","(1086, 387)"
|
91 |
+
91,Looking left,"(992, 399)","(1092, 383)"
|
92 |
+
92,Looking left,"(994, 398)","(1093, 382)"
|
93 |
+
93,Looking left,"(996, 397)","(1094, 382)"
|
94 |
+
94,Looking left,"(998, 396)","(1096, 385)"
|
95 |
+
95,Looking left,"(1000, 395)","(1099, 386)"
|
96 |
+
96,Looking left,"(1003, 395)","(1102, 388)"
|
97 |
+
97,Looking left,"(1006, 395)","(1104, 387)"
|
98 |
+
98,Looking left,"(1007, 396)","(1106, 386)"
|
99 |
+
99,Looking left,"(1008, 396)","(1106, 386)"
|
100 |
+
100,Looking left,"(1007, 395)","(1104, 385)"
|
101 |
+
101,Looking left,"(1006, 397)","(1104, 383)"
|
102 |
+
102,Looking left,"(1006, 397)","(1105, 382)"
|
103 |
+
103,Looking left,"(1006, 398)","(1105, 381)"
|
104 |
+
104,Looking left,"(1007, 398)","(1106, 382)"
|
105 |
+
105,Looking left,"(1009, 399)","(1107, 383)"
|
106 |
+
106,Looking left,"(1013, 399)","(1112, 388)"
|
107 |
+
107,Looking left,"(1016, 398)","(1115, 390)"
|
108 |
+
108,Looking left,"(1019, 398)","(1117, 390)"
|
109 |
+
109,Looking left,"(1022, 396)","(1121, 391)"
|
110 |
+
110,Looking left,"(1024, 395)","(1122, 389)"
|
111 |
+
111,Looking left,"(1025, 395)","(1123, 390)"
|
112 |
+
112,Looking left,"(1025, 395)","(1124, 391)"
|
113 |
+
113,Looking left,"(1027, 395)","(1126, 392)"
|
114 |
+
114,Looking left,"(1028, 395)","(1126, 392)"
|
115 |
+
115,Looking left,"(1028, 397)","(1127, 395)"
|
116 |
+
116,Looking left,"(1028, 397)","(1126, 396)"
|
117 |
+
117,Looking left,"(1028, 397)","(1126, 397)"
|
118 |
+
118,Looking left,"(1029, 397)","(1127, 397)"
|
119 |
+
119,Looking left,"(1029, 396)","(1127, 396)"
|
120 |
+
120,Looking left,"(1029, 397)","(1127, 396)"
|
121 |
+
121,Looking left,"(1028, 396)","(1128, 395)"
|
122 |
+
122,Looking center,"(1028, 397)","(1128, 396)"
|
123 |
+
123,Looking left,"(1029, 397)","(1129, 395)"
|
124 |
+
124,Looking left,"(1028, 398)","(1129, 396)"
|
125 |
+
125,Looking left,"(1028, 398)","(1129, 396)"
|
126 |
+
126,Looking left,"(1028, 398)","(1128, 395)"
|
127 |
+
127,Looking left,"(1028, 397)","(1128, 394)"
|
128 |
+
128,Looking left,"(1028, 397)","(1128, 394)"
|
129 |
+
129,Looking left,"(1027, 397)","(1128, 395)"
|
130 |
+
130,Looking left,"(1027, 398)","(1127, 395)"
|
131 |
+
131,Looking center,"(1027, 397)","(1127, 394)"
|
132 |
+
132,Looking left,"(1027, 397)","(1127, 394)"
|
133 |
+
133,Looking left,"(1027, 397)","(1127, 395)"
|
134 |
+
134,Looking center,"(1026, 397)","(1125, 395)"
|
135 |
+
135,Looking center,"(1024, 397)","(1124, 394)"
|
136 |
+
136,Looking center,"(1023, 397)","(1123, 394)"
|
137 |
+
137,Looking center,"(1023, 396)","(1120, 395)"
|
138 |
+
138,Looking center,"(1023, 396)","(1123, 396)"
|
139 |
+
139,Looking center,"(1022, 396)","(1123, 396)"
|
140 |
+
140,Looking center,"(1022, 395)","(1123, 394)"
|
141 |
+
141,Looking center,"(1023, 395)","(1123, 396)"
|
142 |
+
142,Looking center,"(1022, 394)","(1122, 394)"
|
143 |
+
143,Looking center,"(1022, 395)","(1123, 394)"
|
144 |
+
144,Looking center,"(1022, 395)","(1122, 394)"
|
145 |
+
145,Looking center,"(1025, 397)","(1118, 397)"
|
146 |
+
146,Blinking,"(1040, 404)","(1118, 403)"
|
147 |
+
147,Blinking,"(1046, 404)","(1126, 403)"
|
148 |
+
148,Blinking,"(1052, 402)","(1132, 402)"
|
149 |
+
149,Blinking,"(1052, 401)","(1138, 401)"
|
150 |
+
150,Blinking,"(1050, 400)","(1137, 403)"
|
151 |
+
151,Looking center,"(1045, 401)","(1134, 403)"
|
152 |
+
152,Looking center,"(1038, 403)","(1136, 406)"
|
153 |
+
153,Looking center,"(1037, 405)","(1136, 408)"
|
154 |
+
154,Looking left,"(1036, 406)","(1138, 408)"
|
155 |
+
155,Looking center,"(1037, 407)","(1137, 407)"
|
156 |
+
156,Looking center,"(1037, 407)","(1137, 406)"
|
157 |
+
157,Looking center,"(1036, 406)","(1137, 407)"
|
158 |
+
158,Looking center,"(1036, 405)","(1136, 405)"
|
159 |
+
159,Looking center,"(1035, 405)","(1136, 405)"
|
160 |
+
160,Looking left,"(1036, 405)","(1139, 406)"
|
161 |
+
161,Looking left,"(1037, 404)","(1140, 406)"
|
162 |
+
162,Looking left,"(1036, 404)","(1139, 404)"
|
163 |
+
163,Looking left,"(1035, 404)","(1138, 404)"
|
164 |
+
164,Looking left,"(1035, 404)","(1137, 402)"
|
165 |
+
165,Looking left,"(1036, 405)","(1138, 403)"
|
166 |
+
166,Looking left,"(1036, 404)","(1139, 396)"
|
167 |
+
167,Looking left,"(1037, 404)","(1139, 401)"
|
168 |
+
168,Looking left,"(1037, 401)","(1138, 398)"
|
169 |
+
169,Looking left,"(1038, 400)","(1139, 399)"
|
170 |
+
170,Looking left,"(1040, 398)","(1140, 397)"
|
171 |
+
171,Looking left,"(1040, 396)","(1141, 396)"
|
172 |
+
172,Looking left,"(1043, 395)","(1139, 392)"
|
173 |
+
173,Looking left,"(1041, 394)","(1139, 391)"
|
174 |
+
174,Looking left,"(1039, 393)","(1138, 390)"
|
175 |
+
175,Looking left,"(1037, 392)","(1136, 389)"
|
176 |
+
176,Looking left,"(1034, 391)","(1134, 389)"
|
177 |
+
177,Looking left,"(1033, 391)","(1134, 388)"
|
178 |
+
178,Blinking,"(1040, 396)","(1119, 395)"
|
179 |
+
179,Blinking,"(1040, 398)","(1126, 398)"
|
180 |
+
180,Blinking,"(1045, 396)","(1127, 397)"
|
181 |
+
181,Blinking,"(1044, 391)","(1121, 391)"
|
182 |
+
182,Blinking,"(1041, 388)","(1116, 389)"
|
183 |
+
183,Looking left,"(1036, 387)","(1136, 382)"
|
184 |
+
184,Looking left,"(1034, 387)","(1135, 380)"
|
185 |
+
185,Blinking,"(1038, 391)","(1114, 388)"
|
186 |
+
186,Blinking,"(1038, 391)","(1115, 390)"
|
187 |
+
187,Blinking,"(1037, 386)","(1110, 385)"
|
188 |
+
188,Looking center,"(1025, 383)","(1109, 378)"
|
189 |
+
189,Looking center,"(1019, 381)","(1094, 377)"
|
190 |
+
190,Looking center,"(1008, 380)","(1106, 365)"
|
191 |
+
191,Looking center,"(1005, 380)","(1102, 366)"
|
192 |
+
192,Looking center,"(1001, 381)","(1098, 366)"
|
193 |
+
193,Looking center,"(1002, 382)","(1098, 367)"
|
194 |
+
194,Looking center,"(1002, 384)","(1099, 368)"
|
195 |
+
195,Looking center,"(1004, 384)","(1100, 370)"
|
196 |
+
196,Looking center,"(1006, 384)","(1104, 371)"
|
197 |
+
197,Looking center,"(1009, 384)","(1106, 372)"
|
198 |
+
198,Looking center,"(1012, 383)","(1108, 371)"
|
199 |
+
199,Looking left,"(1018, 382)","(1112, 371)"
|
200 |
+
200,Looking left,"(1017, 380)","(1115, 369)"
|
201 |
+
201,Looking center,"(1019, 377)","(1115, 364)"
|
202 |
+
202,Looking left,"(1020, 374)","(1117, 362)"
|
203 |
+
203,Looking left,"(1022, 373)","(1120, 362)"
|
204 |
+
204,Looking left,"(1026, 373)","(1122, 362)"
|
205 |
+
205,Looking left,"(1030, 373)","(1126, 364)"
|
206 |
+
206,Looking left,"(1035, 372)","(1132, 365)"
|
207 |
+
207,Looking left,"(1039, 369)","(1136, 367)"
|
208 |
+
208,Looking center,"(1043, 369)","(1139, 370)"
|
209 |
+
209,Looking left,"(1046, 369)","(1143, 371)"
|
210 |
+
210,Looking center,"(1047, 368)","(1143, 372)"
|
211 |
+
211,Looking left,"(1048, 367)","(1145, 371)"
|
212 |
+
212,Looking left,"(1047, 367)","(1144, 372)"
|
213 |
+
213,Looking center,"(1044, 368)","(1143, 372)"
|
214 |
+
214,Looking center,"(1043, 368)","(1141, 371)"
|
215 |
+
215,Looking center,"(1041, 369)","(1138, 371)"
|
216 |
+
216,Looking left,"(1038, 369)","(1136, 372)"
|
217 |
+
217,Looking center,"(1035, 372)","(1133, 374)"
|
218 |
+
218,Looking center,"(1035, 373)","(1132, 375)"
|
219 |
+
219,Looking center,"(1033, 374)","(1132, 375)"
|
220 |
+
220,Looking center,"(1033, 376)","(1131, 377)"
|
221 |
+
221,Looking center,"(1033, 379)","(1130, 380)"
|
222 |
+
222,Looking center,"(1033, 382)","(1131, 383)"
|
223 |
+
223,Looking center,"(1033, 383)","(1129, 383)"
|
224 |
+
224,Looking center,"(1033, 384)","(1130, 384)"
|
225 |
+
225,Looking center,"(1032, 386)","(1131, 385)"
|
226 |
+
226,Looking center,"(1032, 387)","(1130, 385)"
|
227 |
+
227,Looking center,"(1032, 387)","(1131, 387)"
|
228 |
+
228,Looking center,"(1031, 388)","(1130, 387)"
|
229 |
+
229,Looking center,"(1030, 389)","(1128, 389)"
|
230 |
+
230,Looking center,"(1029, 390)","(1128, 390)"
|
231 |
+
231,Looking center,"(1028, 391)","(1127, 389)"
|
232 |
+
232,Looking center,"(1026, 390)","(1124, 390)"
|
233 |
+
233,Looking center,"(1024, 392)","(1122, 390)"
|
234 |
+
234,Looking center,"(1023, 392)","(1123, 391)"
|
235 |
+
235,Looking center,"(1021, 393)","(1121, 391)"
|
236 |
+
236,Looking center,"(1020, 393)","(1119, 391)"
|
237 |
+
237,Looking center,"(1019, 393)","(1117, 392)"
|
238 |
+
238,Looking center,"(1017, 394)","(1116, 393)"
|
239 |
+
239,Looking center,"(1014, 395)","(1114, 392)"
|
240 |
+
240,Looking center,"(1011, 396)","(1111, 392)"
|
241 |
+
241,Looking center,"(1008, 395)","(1107, 391)"
|
242 |
+
242,Looking center,"(1004, 397)","(1102, 392)"
|
243 |
+
243,Looking left,"(1000, 398)","(1100, 393)"
|
244 |
+
244,Looking left,"(997, 400)","(1096, 396)"
|
245 |
+
245,Looking left,"(994, 401)","(1094, 396)"
|
246 |
+
246,Looking left,"(993, 402)","(1093, 396)"
|
247 |
+
247,Looking left,"(992, 402)","(1090, 396)"
|
248 |
+
248,Looking left,"(991, 404)","(1088, 397)"
|
249 |
+
249,Looking left,"(989, 405)","(1089, 397)"
|
250 |
+
250,Looking left,"(988, 407)","(1086, 399)"
|
251 |
+
251,Looking left,"(987, 408)","(1085, 399)"
|
252 |
+
252,Looking left,"(985, 408)","(1085, 399)"
|
253 |
+
253,Looking left,"(984, 408)","(1083, 399)"
|
254 |
+
254,Looking left,"(984, 409)","(1082, 400)"
|
255 |
+
255,Looking left,"(984, 408)","(1083, 398)"
|
256 |
+
256,Looking center,"(977, 408)","(1077, 399)"
|
257 |
+
257,Looking center,"(972, 408)","(1070, 402)"
|
258 |
+
258,Looking center,"(973, 409)","(1073, 401)"
|
259 |
+
259,Looking center,"(969, 407)","(1074, 401)"
|
260 |
+
260,Looking center,"(975, 406)","(1078, 402)"
|
261 |
+
261,Looking center,"(978, 408)","(1083, 404)"
|
262 |
+
262,Looking center,"(981, 408)","(1086, 404)"
|
263 |
+
263,Looking center,"(982, 407)","(1089, 404)"
|
264 |
+
264,Looking center,"(997, 413)","(1097, 405)"
|
265 |
+
265,Looking left,"(1004, 410)","(1105, 406)"
|
266 |
+
266,Looking center,"(1007, 412)","(1108, 406)"
|
267 |
+
267,Looking center,"(1010, 411)","(1109, 406)"
|
268 |
+
268,Looking center,"(1013, 411)","(1113, 408)"
|
269 |
+
269,Looking center,"(1014, 410)","(1115, 407)"
|
270 |
+
270,Looking center,"(1014, 412)","(1115, 409)"
|
271 |
+
271,Looking center,"(1016, 412)","(1117, 410)"
|
272 |
+
272,Looking center,"(1018, 413)","(1118, 411)"
|
273 |
+
273,Looking center,"(1018, 414)","(1118, 411)"
|
274 |
+
274,Looking center,"(1018, 415)","(1119, 414)"
|
275 |
+
275,Looking center,"(1020, 416)","(1120, 415)"
|
276 |
+
276,Looking left,"(1024, 412)","(1122, 415)"
|
277 |
+
277,Looking left,"(1023, 413)","(1121, 416)"
|
278 |
+
278,Looking left,"(1023, 414)","(1123, 417)"
|
279 |
+
279,Looking left,"(1023, 413)","(1123, 416)"
|
280 |
+
280,Looking left,"(1024, 412)","(1120, 417)"
|
281 |
+
281,Looking left,"(1024, 412)","(1123, 418)"
|
282 |
+
282,Looking left,"(1021, 413)","(1120, 417)"
|
283 |
+
283,Looking left,"(1022, 414)","(1120, 417)"
|
284 |
+
284,Looking left,"(1024, 412)","(1121, 418)"
|
285 |
+
285,Looking left,"(1029, 412)","(1126, 418)"
|
286 |
+
286,Looking left,"(1031, 411)","(1131, 417)"
|
287 |
+
287,Looking left,"(1031, 411)","(1127, 418)"
|
288 |
+
288,Looking left,"(1032, 410)","(1128, 419)"
|
289 |
+
289,,,
|
290 |
+
290,Looking left,"(1033, 410)","(1131, 419)"
|
291 |
+
291,Looking left,"(1035, 410)","(1134, 420)"
|
292 |
+
292,Looking left,"(1037, 406)","(1135, 412)"
|
293 |
+
293,Looking left,"(1040, 407)","(1138, 418)"
|
294 |
+
294,Looking left,"(1042, 405)","(1140, 418)"
|
295 |
+
295,Looking left,"(1045, 404)","(1143, 417)"
|
296 |
+
296,Looking left,"(1048, 405)","(1146, 416)"
|
297 |
+
297,Blinking,"(1053, 407)","(1126, 412)"
|
298 |
+
298,Blinking,"(1054, 408)","(1136, 412)"
|
299 |
+
299,Blinking,"(1058, 406)","(1138, 409)"
|
300 |
+
300,Blinking,"(1063, 401)","(1140, 406)"
|
301 |
+
1,Looking center,"(1071, 389)","(1161, 412)"
|
302 |
+
2,Looking center,"(1069, 389)","(1159, 411)"
|
303 |
+
3,Looking center,"(1066, 390)","(1156, 411)"
|
304 |
+
4,Looking center,"(1062, 389)","(1152, 409)"
|
305 |
+
5,Looking center,"(1057, 389)","(1146, 408)"
|
306 |
+
6,Looking center,"(1048, 390)","(1140, 406)"
|
307 |
+
7,Looking center,"(1042, 390)","(1134, 406)"
|
308 |
+
8,Looking center,"(1037, 389)","(1128, 404)"
|
309 |
+
9,Looking center,"(1031, 389)","(1124, 403)"
|
310 |
+
10,Looking center,"(1026, 388)","(1119, 401)"
|
311 |
+
11,Looking center,"(1021, 388)","(1115, 400)"
|
312 |
+
12,Looking center,"(1017, 388)","(1111, 399)"
|
313 |
+
13,Looking center,"(1014, 389)","(1109, 398)"
|
314 |
+
14,Looking center,"(1011, 389)","(1106, 397)"
|
315 |
+
15,Looking center,"(1009, 389)","(1104, 396)"
|
316 |
+
16,Looking center,"(1007, 389)","(1102, 395)"
|
317 |
+
17,Looking center,"(1006, 390)","(1100, 394)"
|
318 |
+
18,Looking center,"(1005, 390)","(1100, 394)"
|
319 |
+
19,Looking center,"(1004, 391)","(1100, 394)"
|
320 |
+
20,Looking center,"(1004, 391)","(1099, 394)"
|
321 |
+
21,Looking center,"(1004, 392)","(1098, 395)"
|
322 |
+
22,Looking center,"(1004, 393)","(1098, 395)"
|
323 |
+
23,Looking center,"(1003, 393)","(1098, 394)"
|
324 |
+
24,Looking center,"(1003, 393)","(1098, 394)"
|
325 |
+
25,Looking center,"(1002, 394)","(1097, 394)"
|
326 |
+
26,Looking center,"(1002, 394)","(1097, 395)"
|
327 |
+
27,Looking center,"(1002, 394)","(1097, 395)"
|
328 |
+
28,Looking center,"(1002, 394)","(1097, 395)"
|
329 |
+
29,Looking center,"(1002, 395)","(1098, 395)"
|
330 |
+
30,Looking center,"(1003, 395)","(1098, 395)"
|
331 |
+
31,Looking center,"(1006, 396)","(1098, 397)"
|
332 |
+
32,Blinking,"(1016, 402)","(1090, 402)"
|
333 |
+
33,Blinking,"(1017, 403)","(1094, 404)"
|
334 |
+
34,Blinking,"(1016, 403)","(1093, 405)"
|
335 |
+
35,Blinking,"(1011, 402)","(1090, 401)"
|
336 |
+
36,Blinking,"(999, 400)","(1092, 398)"
|
337 |
+
37,Looking center,"(998, 398)","(1092, 396)"
|
338 |
+
38,Looking center,"(996, 397)","(1091, 395)"
|
339 |
+
39,Looking center,"(996, 397)","(1091, 395)"
|
340 |
+
40,Looking center,"(996, 397)","(1091, 394)"
|
341 |
+
41,Looking center,"(996, 397)","(1091, 394)"
|
342 |
+
42,Looking center,"(997, 397)","(1092, 395)"
|
343 |
+
43,Looking center,"(998, 396)","(1093, 395)"
|
344 |
+
44,Looking center,"(998, 395)","(1093, 392)"
|
345 |
+
45,Blinking,"(1017, 399)","(1091, 396)"
|
346 |
+
46,Blinking,"(1015, 401)","(1090, 401)"
|
347 |
+
47,Blinking,"(1012, 400)","(1090, 400)"
|
348 |
+
48,Looking center,"(1010, 397)","(1083, 395)"
|
349 |
+
49,Looking center,"(994, 395)","(1085, 391)"
|
350 |
+
50,Looking center,"(993, 393)","(1086, 388)"
|
351 |
+
51,Looking center,"(992, 390)","(1087, 387)"
|
352 |
+
52,Looking center,"(993, 389)","(1088, 386)"
|
353 |
+
53,Looking center,"(995, 389)","(1089, 386)"
|
354 |
+
54,Blinking,"(1012, 394)","(1086, 393)"
|
355 |
+
55,Blinking,"(1017, 393)","(1089, 395)"
|
356 |
+
56,Blinking,"(1012, 394)","(1091, 393)"
|
357 |
+
57,Blinking,"(998, 393)","(1091, 390)"
|
358 |
+
58,Blinking,"(998, 389)","(1093, 387)"
|
359 |
+
59,Looking center,"(996, 388)","(1092, 386)"
|
360 |
+
60,Looking center,"(996, 387)","(1092, 386)"
|
361 |
+
61,Looking center,"(995, 386)","(1090, 386)"
|
362 |
+
62,Looking center,"(994, 386)","(1089, 385)"
|
363 |
+
63,Looking center,"(993, 385)","(1088, 384)"
|
364 |
+
64,Looking center,"(993, 384)","(1088, 384)"
|
365 |
+
65,Looking center,"(994, 385)","(1089, 384)"
|
366 |
+
66,Looking center,"(995, 384)","(1089, 384)"
|
367 |
+
67,Looking center,"(1010, 388)","(1089, 387)"
|
368 |
+
68,Blinking,"(1012, 391)","(1091, 393)"
|
369 |
+
69,Blinking,"(1015, 390)","(1089, 391)"
|
370 |
+
70,Looking center,"(1016, 385)","(1089, 387)"
|
371 |
+
71,Looking left,"(1018, 380)","(1110, 382)"
|
372 |
+
72,Looking left,"(1022, 376)","(1114, 379)"
|
373 |
+
73,Looking left,"(1026, 372)","(1119, 377)"
|
374 |
+
74,Looking left,"(1032, 369)","(1123, 375)"
|
375 |
+
75,Looking left,"(1036, 368)","(1129, 374)"
|
376 |
+
76,Looking left,"(1038, 370)","(1130, 374)"
|
377 |
+
77,Looking left,"(1038, 370)","(1131, 375)"
|
378 |
+
78,Looking left,"(1038, 369)","(1130, 375)"
|
379 |
+
79,Looking left,"(1036, 367)","(1128, 374)"
|
380 |
+
80,Looking left,"(1033, 368)","(1125, 375)"
|
381 |
+
81,Looking left,"(1030, 369)","(1122, 375)"
|
382 |
+
82,Looking left,"(1028, 369)","(1120, 375)"
|
383 |
+
83,Looking left,"(1026, 369)","(1118, 375)"
|
384 |
+
84,Looking left,"(1025, 369)","(1117, 374)"
|
385 |
+
85,Looking left,"(1025, 369)","(1116, 375)"
|
386 |
+
86,Looking left,"(1024, 371)","(1116, 376)"
|
387 |
+
87,Looking left,"(1025, 372)","(1116, 376)"
|
388 |
+
88,Looking left,"(1025, 372)","(1117, 378)"
|
389 |
+
89,Looking left,"(1026, 374)","(1118, 379)"
|
390 |
+
90,Looking left,"(1028, 373)","(1119, 380)"
|
391 |
+
91,Looking left,"(1029, 375)","(1120, 381)"
|
392 |
+
92,Looking left,"(1030, 374)","(1121, 382)"
|
393 |
+
93,Looking left,"(1032, 375)","(1123, 382)"
|
394 |
+
94,Looking left,"(1032, 375)","(1123, 382)"
|
395 |
+
95,Looking left,"(1033, 375)","(1123, 382)"
|
396 |
+
96,Looking left,"(1033, 376)","(1124, 382)"
|
397 |
+
97,Looking left,"(1033, 375)","(1124, 382)"
|
398 |
+
98,Looking left,"(1032, 375)","(1123, 382)"
|
399 |
+
99,Looking left,"(1032, 374)","(1123, 381)"
|
400 |
+
100,Looking left,"(1031, 376)","(1123, 382)"
|
401 |
+
101,Looking left,"(1030, 375)","(1122, 381)"
|
402 |
+
102,Looking left,"(1030, 375)","(1121, 381)"
|
403 |
+
103,Looking left,"(1029, 374)","(1120, 381)"
|
404 |
+
104,Looking left,"(1029, 375)","(1120, 381)"
|
405 |
+
105,Looking left,"(1028, 375)","(1119, 380)"
|
406 |
+
106,Looking left,"(1028, 374)","(1119, 380)"
|
407 |
+
107,Looking left,"(1027, 375)","(1119, 381)"
|
408 |
+
108,Looking left,"(1028, 374)","(1119, 381)"
|
409 |
+
109,Looking left,"(1028, 374)","(1118, 380)"
|
410 |
+
110,Looking left,"(1027, 375)","(1118, 381)"
|
411 |
+
111,Looking left,"(1028, 375)","(1118, 381)"
|
412 |
+
112,Looking left,"(1027, 375)","(1118, 382)"
|
413 |
+
113,Looking left,"(1028, 375)","(1118, 381)"
|
414 |
+
114,Looking left,"(1028, 377)","(1119, 383)"
|
415 |
+
115,Looking left,"(1028, 378)","(1119, 384)"
|
416 |
+
116,Looking left,"(1029, 378)","(1120, 386)"
|
417 |
+
117,Looking left,"(1028, 382)","(1120, 389)"
|
418 |
+
118,Looking left,"(1029, 382)","(1120, 390)"
|
419 |
+
119,Looking left,"(1028, 383)","(1119, 393)"
|
420 |
+
120,Looking left,"(1028, 384)","(1119, 393)"
|
421 |
+
121,Looking left,"(1028, 383)","(1118, 393)"
|
422 |
+
122,Looking left,"(1027, 386)","(1117, 394)"
|
423 |
+
123,Looking left,"(1026, 385)","(1116, 392)"
|
424 |
+
124,Looking left,"(1025, 385)","(1116, 393)"
|
425 |
+
125,Looking left,"(1025, 386)","(1115, 392)"
|
426 |
+
126,Looking left,"(1026, 386)","(1115, 392)"
|
427 |
+
127,Looking left,"(1026, 387)","(1116, 392)"
|
428 |
+
128,Looking left,"(1026, 387)","(1116, 392)"
|
429 |
+
129,Looking left,"(1027, 388)","(1116, 392)"
|
430 |
+
130,Looking left,"(1027, 386)","(1115, 392)"
|
431 |
+
131,Looking left,"(1027, 387)","(1115, 393)"
|
432 |
+
132,Looking left,"(1026, 386)","(1114, 393)"
|
433 |
+
133,Looking left,"(1024, 388)","(1114, 393)"
|
434 |
+
134,Looking left,"(1022, 387)","(1112, 392)"
|
435 |
+
135,Looking left,"(1021, 388)","(1112, 392)"
|
436 |
+
136,Looking left,"(1021, 388)","(1112, 391)"
|
437 |
+
137,Looking left,"(1022, 387)","(1113, 390)"
|
438 |
+
138,Looking left,"(1024, 385)","(1115, 388)"
|
439 |
+
139,Looking left,"(1026, 385)","(1117, 389)"
|
440 |
+
140,Looking left,"(1029, 386)","(1120, 389)"
|
441 |
+
141,Looking left,"(1031, 387)","(1122, 388)"
|
442 |
+
142,Looking left,"(1034, 386)","(1125, 387)"
|
443 |
+
143,Looking left,"(1036, 384)","(1128, 385)"
|
444 |
+
144,Looking left,"(1039, 383)","(1130, 384)"
|
445 |
+
145,Looking left,"(1041, 382)","(1132, 385)"
|
446 |
+
146,Looking left,"(1042, 382)","(1133, 386)"
|
447 |
+
147,Looking left,"(1042, 383)","(1134, 387)"
|
448 |
+
148,Looking left,"(1042, 382)","(1133, 387)"
|
449 |
+
149,Looking left,"(1042, 382)","(1132, 387)"
|
450 |
+
150,Looking left,"(1041, 382)","(1132, 387)"
|
451 |
+
151,Looking left,"(1040, 382)","(1132, 386)"
|
452 |
+
152,Looking left,"(1039, 382)","(1131, 386)"
|
453 |
+
153,Looking left,"(1038, 382)","(1131, 385)"
|
454 |
+
154,Looking left,"(1038, 381)","(1131, 385)"
|
455 |
+
155,Looking left,"(1038, 382)","(1131, 385)"
|
456 |
+
156,Looking left,"(1038, 381)","(1131, 384)"
|
457 |
+
157,Looking left,"(1038, 381)","(1131, 384)"
|
458 |
+
158,Looking left,"(1038, 381)","(1132, 384)"
|
459 |
+
159,Looking left,"(1039, 382)","(1132, 385)"
|
460 |
+
160,Looking left,"(1041, 382)","(1134, 384)"
|
461 |
+
161,Looking left,"(1043, 382)","(1136, 385)"
|
462 |
+
162,Looking left,"(1047, 383)","(1139, 386)"
|
463 |
+
163,Looking left,"(1049, 383)","(1141, 386)"
|
464 |
+
164,Looking left,"(1050, 383)","(1142, 387)"
|
465 |
+
165,Looking left,"(1051, 384)","(1143, 388)"
|
466 |
+
166,Looking left,"(1051, 383)","(1142, 388)"
|
467 |
+
167,Looking left,"(1049, 384)","(1141, 388)"
|
468 |
+
168,Looking left,"(1047, 383)","(1139, 388)"
|
469 |
+
169,Looking left,"(1044, 384)","(1136, 388)"
|
470 |
+
170,Looking left,"(1041, 383)","(1134, 387)"
|
471 |
+
171,Looking left,"(1039, 384)","(1132, 387)"
|
472 |
+
172,Looking left,"(1037, 385)","(1130, 388)"
|
473 |
+
173,Looking left,"(1036, 385)","(1129, 388)"
|
474 |
+
174,Looking left,"(1036, 387)","(1130, 388)"
|
475 |
+
175,Looking left,"(1037, 386)","(1131, 388)"
|
476 |
+
176,Looking left,"(1039, 385)","(1132, 387)"
|
477 |
+
177,Looking left,"(1041, 386)","(1133, 388)"
|
478 |
+
178,Looking left,"(1042, 386)","(1134, 389)"
|
479 |
+
179,Looking left,"(1043, 386)","(1135, 389)"
|
480 |
+
180,Looking left,"(1043, 387)","(1135, 389)"
|
481 |
+
181,Looking left,"(1042, 385)","(1134, 389)"
|
482 |
+
182,Looking left,"(1041, 384)","(1133, 388)"
|
483 |
+
183,Looking left,"(1039, 384)","(1131, 388)"
|
484 |
+
184,Looking left,"(1037, 384)","(1130, 387)"
|
485 |
+
185,Looking left,"(1035, 385)","(1128, 388)"
|
486 |
+
186,Looking left,"(1033, 387)","(1127, 389)"
|
487 |
+
187,Looking left,"(1033, 386)","(1126, 388)"
|
488 |
+
188,Looking left,"(1033, 386)","(1126, 388)"
|
489 |
+
189,Looking left,"(1033, 385)","(1127, 388)"
|
490 |
+
190,Looking left,"(1035, 385)","(1129, 388)"
|
491 |
+
191,Looking left,"(1037, 386)","(1129, 389)"
|
492 |
+
192,Looking left,"(1039, 385)","(1132, 389)"
|
493 |
+
193,Looking left,"(1040, 385)","(1133, 390)"
|
494 |
+
194,Looking left,"(1041, 385)","(1133, 389)"
|
495 |
+
195,Looking left,"(1041, 385)","(1133, 389)"
|
496 |
+
196,Looking left,"(1040, 383)","(1133, 388)"
|
497 |
+
197,Looking left,"(1038, 384)","(1131, 387)"
|
498 |
+
198,Looking left,"(1036, 384)","(1130, 386)"
|
499 |
+
199,Looking left,"(1034, 383)","(1128, 384)"
|
500 |
+
200,Looking left,"(1032, 381)","(1126, 384)"
|
501 |
+
201,Looking left,"(1030, 383)","(1124, 385)"
|
502 |
+
202,Looking left,"(1027, 382)","(1122, 384)"
|
503 |
+
203,Looking left,"(1026, 380)","(1121, 382)"
|
504 |
+
204,Looking left,"(1026, 377)","(1121, 380)"
|
505 |
+
205,Looking left,"(1028, 373)","(1122, 379)"
|
506 |
+
206,Looking left,"(1030, 370)","(1124, 378)"
|
507 |
+
207,Looking left,"(1033, 370)","(1126, 379)"
|
508 |
+
208,Looking left,"(1036, 372)","(1129, 381)"
|
509 |
+
209,Looking left,"(1038, 373)","(1131, 382)"
|
510 |
+
210,Looking left,"(1038, 373)","(1130, 383)"
|
511 |
+
211,Looking left,"(1038, 373)","(1131, 383)"
|
512 |
+
212,Looking left,"(1036, 374)","(1129, 383)"
|
513 |
+
213,Looking left,"(1034, 375)","(1127, 384)"
|
514 |
+
214,Looking left,"(1031, 376)","(1124, 384)"
|
515 |
+
215,Looking left,"(1028, 376)","(1121, 382)"
|
516 |
+
216,Looking left,"(1025, 375)","(1119, 381)"
|
517 |
+
217,Looking left,"(1023, 374)","(1116, 380)"
|
518 |
+
218,Looking left,"(1021, 375)","(1114, 380)"
|
519 |
+
219,Looking left,"(1019, 375)","(1113, 380)"
|
520 |
+
220,Looking left,"(1018, 376)","(1111, 381)"
|
521 |
+
221,Looking left,"(1017, 376)","(1110, 380)"
|
522 |
+
222,Looking left,"(1016, 376)","(1109, 380)"
|
523 |
+
223,Looking left,"(1016, 376)","(1109, 380)"
|
524 |
+
224,Looking left,"(1016, 376)","(1109, 380)"
|
525 |
+
225,Looking left,"(1017, 376)","(1110, 379)"
|
526 |
+
226,Looking left,"(1019, 374)","(1111, 379)"
|
527 |
+
227,Looking left,"(1020, 375)","(1113, 379)"
|
528 |
+
228,Looking left,"(1022, 375)","(1114, 380)"
|
529 |
+
229,Looking left,"(1024, 376)","(1116, 381)"
|
530 |
+
230,Looking left,"(1024, 377)","(1117, 382)"
|
531 |
+
231,Looking left,"(1026, 376)","(1118, 382)"
|
532 |
+
232,Looking left,"(1026, 377)","(1118, 383)"
|
533 |
+
233,Looking left,"(1026, 377)","(1118, 382)"
|
534 |
+
234,Looking left,"(1026, 378)","(1119, 382)"
|
535 |
+
235,Looking left,"(1027, 377)","(1119, 383)"
|
536 |
+
236,Looking left,"(1028, 377)","(1120, 383)"
|
537 |
+
237,Looking left,"(1029, 379)","(1122, 382)"
|
538 |
+
238,Looking left,"(1031, 382)","(1125, 383)"
|
539 |
+
239,Looking left,"(1036, 382)","(1129, 385)"
|
540 |
+
240,Looking left,"(1039, 383)","(1133, 387)"
|
541 |
+
241,Looking left,"(1043, 384)","(1136, 387)"
|
542 |
+
242,Looking left,"(1046, 385)","(1139, 389)"
|
543 |
+
243,Looking left,"(1047, 383)","(1139, 389)"
|
544 |
+
244,Looking left,"(1048, 382)","(1140, 389)"
|
545 |
+
245,Looking left,"(1048, 381)","(1139, 390)"
|
546 |
+
246,Looking left,"(1047, 383)","(1138, 390)"
|
547 |
+
247,Looking left,"(1046, 383)","(1137, 391)"
|
548 |
+
248,Looking left,"(1045, 383)","(1136, 391)"
|
549 |
+
249,Looking left,"(1045, 386)","(1136, 393)"
|
550 |
+
250,Looking left,"(1045, 388)","(1136, 395)"
|
551 |
+
251,Looking left,"(1044, 390)","(1136, 398)"
|
552 |
+
252,Looking left,"(1044, 393)","(1135, 400)"
|
553 |
+
253,Looking left,"(1044, 395)","(1135, 403)"
|
554 |
+
254,Looking left,"(1043, 397)","(1134, 404)"
|
555 |
+
255,Looking left,"(1042, 396)","(1133, 403)"
|
556 |
+
256,Looking left,"(1040, 397)","(1132, 404)"
|
557 |
+
257,Looking left,"(1039, 399)","(1130, 406)"
|
558 |
+
258,Looking left,"(1036, 399)","(1128, 406)"
|
559 |
+
259,Looking left,"(1034, 402)","(1125, 409)"
|
560 |
+
260,Looking left,"(1030, 406)","(1120, 412)"
|
561 |
+
261,Looking center,"(1027, 409)","(1117, 413)"
|
562 |
+
262,Looking center,"(1026, 409)","(1115, 414)"
|
563 |
+
263,Looking center,"(1025, 411)","(1114, 416)"
|
564 |
+
264,Looking center,"(1025, 409)","(1113, 414)"
|
565 |
+
265,Looking center,"(1024, 408)","(1113, 413)"
|
566 |
+
266,Looking center,"(1024, 406)","(1114, 411)"
|
567 |
+
267,Looking center,"(1024, 405)","(1114, 410)"
|
568 |
+
268,Looking center,"(1023, 401)","(1115, 407)"
|
569 |
+
269,Looking center,"(1026, 398)","(1117, 403)"
|
570 |
+
270,Looking center,"(1028, 394)","(1118, 400)"
|
571 |
+
271,Looking center,"(1029, 390)","(1120, 396)"
|
572 |
+
272,Looking center,"(1030, 390)","(1121, 396)"
|
573 |
+
273,Looking center,"(1031, 391)","(1122, 396)"
|
574 |
+
274,Looking center,"(1030, 391)","(1122, 395)"
|
575 |
+
275,Looking center,"(1030, 391)","(1122, 397)"
|
576 |
+
276,Looking center,"(1029, 392)","(1121, 397)"
|
577 |
+
277,Looking center,"(1029, 393)","(1120, 399)"
|
578 |
+
278,Looking center,"(1026, 396)","(1117, 400)"
|
579 |
+
279,Looking center,"(1024, 397)","(1114, 401)"
|
580 |
+
280,Looking center,"(1022, 395)","(1111, 400)"
|
581 |
+
281,Looking center,"(1019, 395)","(1109, 398)"
|
582 |
+
282,Looking center,"(1016, 394)","(1107, 397)"
|
583 |
+
283,Looking center,"(1015, 393)","(1105, 397)"
|
584 |
+
284,Looking center,"(1014, 390)","(1104, 393)"
|
585 |
+
285,Looking center,"(1013, 387)","(1102, 390)"
|
586 |
+
286,Looking center,"(1011, 385)","(1100, 387)"
|
587 |
+
287,Looking center,"(1011, 383)","(1099, 384)"
|
588 |
+
288,Looking center,"(1011, 379)","(1099, 380)"
|
589 |
+
289,Looking center,"(1009, 375)","(1100, 377)"
|
590 |
+
290,Looking center,"(1011, 374)","(1101, 376)"
|
591 |
+
291,Blinking,"(1014, 372)","(1104, 376)"
|
592 |
+
292,Blinking,"(1018, 370)","(1107, 373)"
|
593 |
+
293,Looking center,"(1022, 370)","(1112, 373)"
|
594 |
+
294,Looking center,"(1026, 370)","(1117, 374)"
|
595 |
+
295,Looking center,"(1030, 370)","(1121, 377)"
|
596 |
+
296,Looking center,"(1035, 372)","(1126, 380)"
|
597 |
+
297,Looking center,"(1039, 375)","(1131, 384)"
|
598 |
+
298,Looking center,"(1042, 379)","(1135, 389)"
|
599 |
+
299,Looking center,"(1044, 386)","(1138, 396)"
|
600 |
+
300,Looking center,"(1045, 393)","(1140, 403)"
|
GazeTracking/fake_gaze_tracked_output.avi
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:395f80cdccab9c1398f05227990d3e995a104b4ee15be30a63a16ecdc5d8710c
|
3 |
+
size 9030194
|
GazeTracking/gaze_data.csv
ADDED
@@ -0,0 +1,300 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
1,Looking center,"(1071, 389)","(1161, 412)"
|
2 |
+
2,Looking center,"(1069, 389)","(1159, 411)"
|
3 |
+
3,Looking center,"(1066, 390)","(1156, 411)"
|
4 |
+
4,Looking center,"(1062, 389)","(1152, 409)"
|
5 |
+
5,Looking center,"(1057, 389)","(1146, 408)"
|
6 |
+
6,Looking center,"(1048, 390)","(1140, 406)"
|
7 |
+
7,Looking center,"(1042, 390)","(1134, 406)"
|
8 |
+
8,Looking center,"(1037, 389)","(1128, 404)"
|
9 |
+
9,Looking center,"(1031, 389)","(1124, 403)"
|
10 |
+
10,Looking center,"(1026, 388)","(1119, 401)"
|
11 |
+
11,Looking center,"(1021, 388)","(1115, 400)"
|
12 |
+
12,Looking center,"(1017, 388)","(1111, 399)"
|
13 |
+
13,Looking center,"(1014, 389)","(1109, 398)"
|
14 |
+
14,Looking center,"(1011, 389)","(1106, 397)"
|
15 |
+
15,Looking center,"(1009, 389)","(1104, 396)"
|
16 |
+
16,Looking center,"(1007, 389)","(1102, 395)"
|
17 |
+
17,Looking center,"(1006, 390)","(1100, 394)"
|
18 |
+
18,Looking center,"(1005, 390)","(1100, 394)"
|
19 |
+
19,Looking center,"(1004, 391)","(1100, 394)"
|
20 |
+
20,Looking center,"(1004, 391)","(1099, 394)"
|
21 |
+
21,Looking center,"(1004, 392)","(1098, 395)"
|
22 |
+
22,Looking center,"(1004, 393)","(1098, 395)"
|
23 |
+
23,Looking center,"(1003, 393)","(1098, 394)"
|
24 |
+
24,Looking center,"(1003, 393)","(1098, 394)"
|
25 |
+
25,Looking center,"(1002, 394)","(1097, 394)"
|
26 |
+
26,Looking center,"(1002, 394)","(1097, 395)"
|
27 |
+
27,Looking center,"(1002, 394)","(1097, 395)"
|
28 |
+
28,Looking center,"(1002, 394)","(1097, 395)"
|
29 |
+
29,Looking center,"(1002, 395)","(1098, 395)"
|
30 |
+
30,Looking center,"(1003, 395)","(1098, 395)"
|
31 |
+
31,Looking center,"(1006, 396)","(1098, 397)"
|
32 |
+
32,Blinking,"(1016, 402)","(1090, 402)"
|
33 |
+
33,Blinking,"(1017, 403)","(1094, 404)"
|
34 |
+
34,Blinking,"(1016, 403)","(1093, 405)"
|
35 |
+
35,Blinking,"(1011, 402)","(1090, 401)"
|
36 |
+
36,Blinking,"(999, 400)","(1092, 398)"
|
37 |
+
37,Looking center,"(998, 398)","(1092, 396)"
|
38 |
+
38,Looking center,"(996, 397)","(1091, 395)"
|
39 |
+
39,Looking center,"(996, 397)","(1091, 395)"
|
40 |
+
40,Looking center,"(996, 397)","(1091, 394)"
|
41 |
+
41,Looking center,"(996, 397)","(1091, 394)"
|
42 |
+
42,Looking center,"(997, 397)","(1092, 395)"
|
43 |
+
43,Looking center,"(998, 396)","(1093, 395)"
|
44 |
+
44,Looking center,"(998, 395)","(1093, 392)"
|
45 |
+
45,Blinking,"(1017, 399)","(1091, 396)"
|
46 |
+
46,Blinking,"(1015, 401)","(1090, 401)"
|
47 |
+
47,Blinking,"(1012, 400)","(1090, 400)"
|
48 |
+
48,Looking center,"(1010, 397)","(1083, 395)"
|
49 |
+
49,Looking center,"(994, 395)","(1085, 391)"
|
50 |
+
50,Looking center,"(993, 393)","(1086, 388)"
|
51 |
+
51,Looking center,"(992, 390)","(1087, 387)"
|
52 |
+
52,Looking center,"(993, 389)","(1088, 386)"
|
53 |
+
53,Looking center,"(995, 389)","(1089, 386)"
|
54 |
+
54,Blinking,"(1012, 394)","(1086, 393)"
|
55 |
+
55,Blinking,"(1017, 393)","(1089, 395)"
|
56 |
+
56,Blinking,"(1012, 394)","(1091, 393)"
|
57 |
+
57,Blinking,"(998, 393)","(1091, 390)"
|
58 |
+
58,Blinking,"(998, 389)","(1093, 387)"
|
59 |
+
59,Looking center,"(996, 388)","(1092, 386)"
|
60 |
+
60,Looking center,"(996, 387)","(1092, 386)"
|
61 |
+
61,Looking center,"(995, 386)","(1090, 386)"
|
62 |
+
62,Looking center,"(994, 386)","(1089, 385)"
|
63 |
+
63,Looking center,"(993, 385)","(1088, 384)"
|
64 |
+
64,Looking center,"(993, 384)","(1088, 384)"
|
65 |
+
65,Looking center,"(994, 385)","(1089, 384)"
|
66 |
+
66,Looking center,"(995, 384)","(1089, 384)"
|
67 |
+
67,Looking center,"(1010, 388)","(1089, 387)"
|
68 |
+
68,Blinking,"(1012, 391)","(1091, 393)"
|
69 |
+
69,Blinking,"(1015, 390)","(1089, 391)"
|
70 |
+
70,Looking center,"(1016, 385)","(1089, 387)"
|
71 |
+
71,Looking left,"(1018, 380)","(1110, 382)"
|
72 |
+
72,Looking left,"(1022, 376)","(1114, 379)"
|
73 |
+
73,Looking left,"(1026, 372)","(1119, 377)"
|
74 |
+
74,Looking left,"(1032, 369)","(1123, 375)"
|
75 |
+
75,Looking left,"(1036, 368)","(1129, 374)"
|
76 |
+
76,Looking left,"(1038, 370)","(1130, 374)"
|
77 |
+
77,Looking left,"(1038, 370)","(1131, 375)"
|
78 |
+
78,Looking left,"(1038, 369)","(1130, 375)"
|
79 |
+
79,Looking left,"(1036, 367)","(1128, 374)"
|
80 |
+
80,Looking left,"(1033, 368)","(1125, 375)"
|
81 |
+
81,Looking left,"(1030, 369)","(1122, 375)"
|
82 |
+
82,Looking left,"(1028, 369)","(1120, 375)"
|
83 |
+
83,Looking left,"(1026, 369)","(1118, 375)"
|
84 |
+
84,Looking left,"(1025, 369)","(1117, 374)"
|
85 |
+
85,Looking left,"(1025, 369)","(1116, 375)"
|
86 |
+
86,Looking left,"(1024, 371)","(1116, 376)"
|
87 |
+
87,Looking left,"(1025, 372)","(1116, 376)"
|
88 |
+
88,Looking left,"(1025, 372)","(1117, 378)"
|
89 |
+
89,Looking left,"(1026, 374)","(1118, 379)"
|
90 |
+
90,Looking left,"(1028, 373)","(1119, 380)"
|
91 |
+
91,Looking left,"(1029, 375)","(1120, 381)"
|
92 |
+
92,Looking left,"(1030, 374)","(1121, 382)"
|
93 |
+
93,Looking left,"(1032, 375)","(1123, 382)"
|
94 |
+
94,Looking left,"(1032, 375)","(1123, 382)"
|
95 |
+
95,Looking left,"(1033, 375)","(1123, 382)"
|
96 |
+
96,Looking left,"(1033, 376)","(1124, 382)"
|
97 |
+
97,Looking left,"(1033, 375)","(1124, 382)"
|
98 |
+
98,Looking left,"(1032, 375)","(1123, 382)"
|
99 |
+
99,Looking left,"(1032, 374)","(1123, 381)"
|
100 |
+
100,Looking left,"(1031, 376)","(1123, 382)"
|
101 |
+
101,Looking left,"(1030, 375)","(1122, 381)"
|
102 |
+
102,Looking left,"(1030, 375)","(1121, 381)"
|
103 |
+
103,Looking left,"(1029, 374)","(1120, 381)"
|
104 |
+
104,Looking left,"(1029, 375)","(1120, 381)"
|
105 |
+
105,Looking left,"(1028, 375)","(1119, 380)"
|
106 |
+
106,Looking left,"(1028, 374)","(1119, 380)"
|
107 |
+
107,Looking left,"(1027, 375)","(1119, 381)"
|
108 |
+
108,Looking left,"(1028, 374)","(1119, 381)"
|
109 |
+
109,Looking left,"(1028, 374)","(1118, 380)"
|
110 |
+
110,Looking left,"(1027, 375)","(1118, 381)"
|
111 |
+
111,Looking left,"(1028, 375)","(1118, 381)"
|
112 |
+
112,Looking left,"(1027, 375)","(1118, 382)"
|
113 |
+
113,Looking left,"(1028, 375)","(1118, 381)"
|
114 |
+
114,Looking left,"(1028, 377)","(1119, 383)"
|
115 |
+
115,Looking left,"(1028, 378)","(1119, 384)"
|
116 |
+
116,Looking left,"(1029, 378)","(1120, 386)"
|
117 |
+
117,Looking left,"(1028, 382)","(1120, 389)"
|
118 |
+
118,Looking left,"(1029, 382)","(1120, 390)"
|
119 |
+
119,Looking left,"(1028, 383)","(1119, 393)"
|
120 |
+
120,Looking left,"(1028, 384)","(1119, 393)"
|
121 |
+
121,Looking left,"(1028, 383)","(1118, 393)"
|
122 |
+
122,Looking left,"(1027, 386)","(1117, 394)"
|
123 |
+
123,Looking left,"(1026, 385)","(1116, 392)"
|
124 |
+
124,Looking left,"(1025, 385)","(1116, 393)"
|
125 |
+
125,Looking left,"(1025, 386)","(1115, 392)"
|
126 |
+
126,Looking left,"(1026, 386)","(1115, 392)"
|
127 |
+
127,Looking left,"(1026, 387)","(1116, 392)"
|
128 |
+
128,Looking left,"(1026, 387)","(1116, 392)"
|
129 |
+
129,Looking left,"(1027, 388)","(1116, 392)"
|
130 |
+
130,Looking left,"(1027, 386)","(1115, 392)"
|
131 |
+
131,Looking left,"(1027, 387)","(1115, 393)"
|
132 |
+
132,Looking left,"(1026, 386)","(1114, 393)"
|
133 |
+
133,Looking left,"(1024, 388)","(1114, 393)"
|
134 |
+
134,Looking left,"(1022, 387)","(1112, 392)"
|
135 |
+
135,Looking left,"(1021, 388)","(1112, 392)"
|
136 |
+
136,Looking left,"(1021, 388)","(1112, 391)"
|
137 |
+
137,Looking left,"(1022, 387)","(1113, 390)"
|
138 |
+
138,Looking left,"(1024, 385)","(1115, 388)"
|
139 |
+
139,Looking left,"(1026, 385)","(1117, 389)"
|
140 |
+
140,Looking left,"(1029, 386)","(1120, 389)"
|
141 |
+
141,Looking left,"(1031, 387)","(1122, 388)"
|
142 |
+
142,Looking left,"(1034, 386)","(1125, 387)"
|
143 |
+
143,Looking left,"(1036, 384)","(1128, 385)"
|
144 |
+
144,Looking left,"(1039, 383)","(1130, 384)"
|
145 |
+
145,Looking left,"(1041, 382)","(1132, 385)"
|
146 |
+
146,Looking left,"(1042, 382)","(1133, 386)"
|
147 |
+
147,Looking left,"(1042, 383)","(1134, 387)"
|
148 |
+
148,Looking left,"(1042, 382)","(1133, 387)"
|
149 |
+
149,Looking left,"(1042, 382)","(1132, 387)"
|
150 |
+
150,Looking left,"(1041, 382)","(1132, 387)"
|
151 |
+
151,Looking left,"(1040, 382)","(1132, 386)"
|
152 |
+
152,Looking left,"(1039, 382)","(1131, 386)"
|
153 |
+
153,Looking left,"(1038, 382)","(1131, 385)"
|
154 |
+
154,Looking left,"(1038, 381)","(1131, 385)"
|
155 |
+
155,Looking left,"(1038, 382)","(1131, 385)"
|
156 |
+
156,Looking left,"(1038, 381)","(1131, 384)"
|
157 |
+
157,Looking left,"(1038, 381)","(1131, 384)"
|
158 |
+
158,Looking left,"(1038, 381)","(1132, 384)"
|
159 |
+
159,Looking left,"(1039, 382)","(1132, 385)"
|
160 |
+
160,Looking left,"(1041, 382)","(1134, 384)"
|
161 |
+
161,Looking left,"(1043, 382)","(1136, 385)"
|
162 |
+
162,Looking left,"(1047, 383)","(1139, 386)"
|
163 |
+
163,Looking left,"(1049, 383)","(1141, 386)"
|
164 |
+
164,Looking left,"(1050, 383)","(1142, 387)"
|
165 |
+
165,Looking left,"(1051, 384)","(1143, 388)"
|
166 |
+
166,Looking left,"(1051, 383)","(1142, 388)"
|
167 |
+
167,Looking left,"(1049, 384)","(1141, 388)"
|
168 |
+
168,Looking left,"(1047, 383)","(1139, 388)"
|
169 |
+
169,Looking left,"(1044, 384)","(1136, 388)"
|
170 |
+
170,Looking left,"(1041, 383)","(1134, 387)"
|
171 |
+
171,Looking left,"(1039, 384)","(1132, 387)"
|
172 |
+
172,Looking left,"(1037, 385)","(1130, 388)"
|
173 |
+
173,Looking left,"(1036, 385)","(1129, 388)"
|
174 |
+
174,Looking left,"(1036, 387)","(1130, 388)"
|
175 |
+
175,Looking left,"(1037, 386)","(1131, 388)"
|
176 |
+
176,Looking left,"(1039, 385)","(1132, 387)"
|
177 |
+
177,Looking left,"(1041, 386)","(1133, 388)"
|
178 |
+
178,Looking left,"(1042, 386)","(1134, 389)"
|
179 |
+
179,Looking left,"(1043, 386)","(1135, 389)"
|
180 |
+
180,Looking left,"(1043, 387)","(1135, 389)"
|
181 |
+
181,Looking left,"(1042, 385)","(1134, 389)"
|
182 |
+
182,Looking left,"(1041, 384)","(1133, 388)"
|
183 |
+
183,Looking left,"(1039, 384)","(1131, 388)"
|
184 |
+
184,Looking left,"(1037, 384)","(1130, 387)"
|
185 |
+
185,Looking left,"(1035, 385)","(1128, 388)"
|
186 |
+
186,Looking left,"(1033, 387)","(1127, 389)"
|
187 |
+
187,Looking left,"(1033, 386)","(1126, 388)"
|
188 |
+
188,Looking left,"(1033, 386)","(1126, 388)"
|
189 |
+
189,Looking left,"(1033, 385)","(1127, 388)"
|
190 |
+
190,Looking left,"(1035, 385)","(1129, 388)"
|
191 |
+
191,Looking left,"(1037, 386)","(1129, 389)"
|
192 |
+
192,Looking left,"(1039, 385)","(1132, 389)"
|
193 |
+
193,Looking left,"(1040, 385)","(1133, 390)"
|
194 |
+
194,Looking left,"(1041, 385)","(1133, 389)"
|
195 |
+
195,Looking left,"(1041, 385)","(1133, 389)"
|
196 |
+
196,Looking left,"(1040, 383)","(1133, 388)"
|
197 |
+
197,Looking left,"(1038, 384)","(1131, 387)"
|
198 |
+
198,Looking left,"(1036, 384)","(1130, 386)"
|
199 |
+
199,Looking left,"(1034, 383)","(1128, 384)"
|
200 |
+
200,Looking left,"(1032, 381)","(1126, 384)"
|
201 |
+
201,Looking left,"(1030, 383)","(1124, 385)"
|
202 |
+
202,Looking left,"(1027, 382)","(1122, 384)"
|
203 |
+
203,Looking left,"(1026, 380)","(1121, 382)"
|
204 |
+
204,Looking left,"(1026, 377)","(1121, 380)"
|
205 |
+
205,Looking left,"(1028, 373)","(1122, 379)"
|
206 |
+
206,Looking left,"(1030, 370)","(1124, 378)"
|
207 |
+
207,Looking left,"(1033, 370)","(1126, 379)"
|
208 |
+
208,Looking left,"(1036, 372)","(1129, 381)"
|
209 |
+
209,Looking left,"(1038, 373)","(1131, 382)"
|
210 |
+
210,Looking left,"(1038, 373)","(1130, 383)"
|
211 |
+
211,Looking left,"(1038, 373)","(1131, 383)"
|
212 |
+
212,Looking left,"(1036, 374)","(1129, 383)"
|
213 |
+
213,Looking left,"(1034, 375)","(1127, 384)"
|
214 |
+
214,Looking left,"(1031, 376)","(1124, 384)"
|
215 |
+
215,Looking left,"(1028, 376)","(1121, 382)"
|
216 |
+
216,Looking left,"(1025, 375)","(1119, 381)"
|
217 |
+
217,Looking left,"(1023, 374)","(1116, 380)"
|
218 |
+
218,Looking left,"(1021, 375)","(1114, 380)"
|
219 |
+
219,Looking left,"(1019, 375)","(1113, 380)"
|
220 |
+
220,Looking left,"(1018, 376)","(1111, 381)"
|
221 |
+
221,Looking left,"(1017, 376)","(1110, 380)"
|
222 |
+
222,Looking left,"(1016, 376)","(1109, 380)"
|
223 |
+
223,Looking left,"(1016, 376)","(1109, 380)"
|
224 |
+
224,Looking left,"(1016, 376)","(1109, 380)"
|
225 |
+
225,Looking left,"(1017, 376)","(1110, 379)"
|
226 |
+
226,Looking left,"(1019, 374)","(1111, 379)"
|
227 |
+
227,Looking left,"(1020, 375)","(1113, 379)"
|
228 |
+
228,Looking left,"(1022, 375)","(1114, 380)"
|
229 |
+
229,Looking left,"(1024, 376)","(1116, 381)"
|
230 |
+
230,Looking left,"(1024, 377)","(1117, 382)"
|
231 |
+
231,Looking left,"(1026, 376)","(1118, 382)"
|
232 |
+
232,Looking left,"(1026, 377)","(1118, 383)"
|
233 |
+
233,Looking left,"(1026, 377)","(1118, 382)"
|
234 |
+
234,Looking left,"(1026, 378)","(1119, 382)"
|
235 |
+
235,Looking left,"(1027, 377)","(1119, 383)"
|
236 |
+
236,Looking left,"(1028, 377)","(1120, 383)"
|
237 |
+
237,Looking left,"(1029, 379)","(1122, 382)"
|
238 |
+
238,Looking left,"(1031, 382)","(1125, 383)"
|
239 |
+
239,Looking left,"(1036, 382)","(1129, 385)"
|
240 |
+
240,Looking left,"(1039, 383)","(1133, 387)"
|
241 |
+
241,Looking left,"(1043, 384)","(1136, 387)"
|
242 |
+
242,Looking left,"(1046, 385)","(1139, 389)"
|
243 |
+
243,Looking left,"(1047, 383)","(1139, 389)"
|
244 |
+
244,Looking left,"(1048, 382)","(1140, 389)"
|
245 |
+
245,Looking left,"(1048, 381)","(1139, 390)"
|
246 |
+
246,Looking left,"(1047, 383)","(1138, 390)"
|
247 |
+
247,Looking left,"(1046, 383)","(1137, 391)"
|
248 |
+
248,Looking left,"(1045, 383)","(1136, 391)"
|
249 |
+
249,Looking left,"(1045, 386)","(1136, 393)"
|
250 |
+
250,Looking left,"(1045, 388)","(1136, 395)"
|
251 |
+
251,Looking left,"(1044, 390)","(1136, 398)"
|
252 |
+
252,Looking left,"(1044, 393)","(1135, 400)"
|
253 |
+
253,Looking left,"(1044, 395)","(1135, 403)"
|
254 |
+
254,Looking left,"(1043, 397)","(1134, 404)"
|
255 |
+
255,Looking left,"(1042, 396)","(1133, 403)"
|
256 |
+
256,Looking left,"(1040, 397)","(1132, 404)"
|
257 |
+
257,Looking left,"(1039, 399)","(1130, 406)"
|
258 |
+
258,Looking left,"(1036, 399)","(1128, 406)"
|
259 |
+
259,Looking left,"(1034, 402)","(1125, 409)"
|
260 |
+
260,Looking left,"(1030, 406)","(1120, 412)"
|
261 |
+
261,Looking center,"(1027, 409)","(1117, 413)"
|
262 |
+
262,Looking center,"(1026, 409)","(1115, 414)"
|
263 |
+
263,Looking center,"(1025, 411)","(1114, 416)"
|
264 |
+
264,Looking center,"(1025, 409)","(1113, 414)"
|
265 |
+
265,Looking center,"(1024, 408)","(1113, 413)"
|
266 |
+
266,Looking center,"(1024, 406)","(1114, 411)"
|
267 |
+
267,Looking center,"(1024, 405)","(1114, 410)"
|
268 |
+
268,Looking center,"(1023, 401)","(1115, 407)"
|
269 |
+
269,Looking center,"(1026, 398)","(1117, 403)"
|
270 |
+
270,Looking center,"(1028, 394)","(1118, 400)"
|
271 |
+
271,Looking center,"(1029, 390)","(1120, 396)"
|
272 |
+
272,Looking center,"(1030, 390)","(1121, 396)"
|
273 |
+
273,Looking center,"(1031, 391)","(1122, 396)"
|
274 |
+
274,Looking center,"(1030, 391)","(1122, 395)"
|
275 |
+
275,Looking center,"(1030, 391)","(1122, 397)"
|
276 |
+
276,Looking center,"(1029, 392)","(1121, 397)"
|
277 |
+
277,Looking center,"(1029, 393)","(1120, 399)"
|
278 |
+
278,Looking center,"(1026, 396)","(1117, 400)"
|
279 |
+
279,Looking center,"(1024, 397)","(1114, 401)"
|
280 |
+
280,Looking center,"(1022, 395)","(1111, 400)"
|
281 |
+
281,Looking center,"(1019, 395)","(1109, 398)"
|
282 |
+
282,Looking center,"(1016, 394)","(1107, 397)"
|
283 |
+
283,Looking center,"(1015, 393)","(1105, 397)"
|
284 |
+
284,Looking center,"(1014, 390)","(1104, 393)"
|
285 |
+
285,Looking center,"(1013, 387)","(1102, 390)"
|
286 |
+
286,Looking center,"(1011, 385)","(1100, 387)"
|
287 |
+
287,Looking center,"(1011, 383)","(1099, 384)"
|
288 |
+
288,Looking center,"(1011, 379)","(1099, 380)"
|
289 |
+
289,Looking center,"(1009, 375)","(1100, 377)"
|
290 |
+
290,Looking center,"(1011, 374)","(1101, 376)"
|
291 |
+
291,Blinking,"(1014, 372)","(1104, 376)"
|
292 |
+
292,Blinking,"(1018, 370)","(1107, 373)"
|
293 |
+
293,Looking center,"(1022, 370)","(1112, 373)"
|
294 |
+
294,Looking center,"(1026, 370)","(1117, 374)"
|
295 |
+
295,Looking center,"(1030, 370)","(1121, 377)"
|
296 |
+
296,Looking center,"(1035, 372)","(1126, 380)"
|
297 |
+
297,Looking center,"(1039, 375)","(1131, 384)"
|
298 |
+
298,Looking center,"(1042, 379)","(1135, 389)"
|
299 |
+
299,Looking center,"(1044, 386)","(1138, 396)"
|
300 |
+
300,Looking center,"(1045, 393)","(1140, 403)"
|
GazeTracking/gaze_tracked_output.avi
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:395f80cdccab9c1398f05227990d3e995a104b4ee15be30a63a16ecdc5d8710c
|
3 |
+
size 9030194
|
GazeTracking/gaze_tracking/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
from .gaze_tracking import GazeTracking
|
GazeTracking/gaze_tracking/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (198 Bytes). View file
|
|
GazeTracking/gaze_tracking/__pycache__/calibration.cpython-312.pyc
ADDED
Binary file (4.15 kB). View file
|
|
GazeTracking/gaze_tracking/__pycache__/eye.cpython-312.pyc
ADDED
Binary file (6.58 kB). View file
|
|
GazeTracking/gaze_tracking/__pycache__/gaze_tracking.cpython-312.pyc
ADDED
Binary file (8.35 kB). View file
|
|
GazeTracking/gaze_tracking/__pycache__/pupil.cpython-312.pyc
ADDED
Binary file (2.92 kB). View file
|
|
GazeTracking/gaze_tracking/calibration.py
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import division
|
2 |
+
import cv2
|
3 |
+
from .pupil import Pupil
|
4 |
+
|
5 |
+
|
6 |
+
class Calibration(object):
|
7 |
+
"""
|
8 |
+
This class calibrates the pupil detection algorithm by finding the
|
9 |
+
best binarization threshold value for the person and the webcam.
|
10 |
+
"""
|
11 |
+
|
12 |
+
def __init__(self):
|
13 |
+
self.nb_frames = 20
|
14 |
+
self.thresholds_left = []
|
15 |
+
self.thresholds_right = []
|
16 |
+
|
17 |
+
def is_complete(self):
|
18 |
+
"""Returns true if the calibration is completed"""
|
19 |
+
return len(self.thresholds_left) >= self.nb_frames and len(self.thresholds_right) >= self.nb_frames
|
20 |
+
|
21 |
+
def threshold(self, side):
|
22 |
+
"""Returns the threshold value for the given eye.
|
23 |
+
|
24 |
+
Argument:
|
25 |
+
side: Indicates whether it's the left eye (0) or the right eye (1)
|
26 |
+
"""
|
27 |
+
if side == 0:
|
28 |
+
return int(sum(self.thresholds_left) / len(self.thresholds_left))
|
29 |
+
elif side == 1:
|
30 |
+
return int(sum(self.thresholds_right) / len(self.thresholds_right))
|
31 |
+
|
32 |
+
@staticmethod
|
33 |
+
def iris_size(frame):
|
34 |
+
"""Returns the percentage of space that the iris takes up on
|
35 |
+
the surface of the eye.
|
36 |
+
|
37 |
+
Argument:
|
38 |
+
frame (numpy.ndarray): Binarized iris frame
|
39 |
+
"""
|
40 |
+
frame = frame[5:-5, 5:-5]
|
41 |
+
height, width = frame.shape[:2]
|
42 |
+
nb_pixels = height * width
|
43 |
+
nb_blacks = nb_pixels - cv2.countNonZero(frame)
|
44 |
+
return nb_blacks / nb_pixels
|
45 |
+
|
46 |
+
@staticmethod
|
47 |
+
def find_best_threshold(eye_frame):
|
48 |
+
"""Calculates the optimal threshold to binarize the
|
49 |
+
frame for the given eye.
|
50 |
+
|
51 |
+
Argument:
|
52 |
+
eye_frame (numpy.ndarray): Frame of the eye to be analyzed
|
53 |
+
"""
|
54 |
+
average_iris_size = 0.48
|
55 |
+
trials = {}
|
56 |
+
|
57 |
+
for threshold in range(5, 100, 5):
|
58 |
+
iris_frame = Pupil.image_processing(eye_frame, threshold)
|
59 |
+
trials[threshold] = Calibration.iris_size(iris_frame)
|
60 |
+
|
61 |
+
best_threshold, iris_size = min(trials.items(), key=(lambda p: abs(p[1] - average_iris_size)))
|
62 |
+
return best_threshold
|
63 |
+
|
64 |
+
def evaluate(self, eye_frame, side):
|
65 |
+
"""Improves calibration by taking into consideration the
|
66 |
+
given image.
|
67 |
+
|
68 |
+
Arguments:
|
69 |
+
eye_frame (numpy.ndarray): Frame of the eye
|
70 |
+
side: Indicates whether it's the left eye (0) or the right eye (1)
|
71 |
+
"""
|
72 |
+
threshold = self.find_best_threshold(eye_frame)
|
73 |
+
|
74 |
+
if side == 0:
|
75 |
+
self.thresholds_left.append(threshold)
|
76 |
+
elif side == 1:
|
77 |
+
self.thresholds_right.append(threshold)
|
GazeTracking/gaze_tracking/eye.py
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
import numpy as np
|
3 |
+
import cv2
|
4 |
+
from .pupil import Pupil
|
5 |
+
|
6 |
+
|
7 |
+
class Eye(object):
|
8 |
+
"""
|
9 |
+
This class creates a new frame to isolate the eye and
|
10 |
+
initiates the pupil detection.
|
11 |
+
"""
|
12 |
+
|
13 |
+
LEFT_EYE_POINTS = [36, 37, 38, 39, 40, 41]
|
14 |
+
RIGHT_EYE_POINTS = [42, 43, 44, 45, 46, 47]
|
15 |
+
|
16 |
+
def __init__(self, original_frame, landmarks, side, calibration):
|
17 |
+
self.frame = None
|
18 |
+
self.origin = None
|
19 |
+
self.center = None
|
20 |
+
self.pupil = None
|
21 |
+
self.landmark_points = None
|
22 |
+
|
23 |
+
self._analyze(original_frame, landmarks, side, calibration)
|
24 |
+
|
25 |
+
@staticmethod
|
26 |
+
def _middle_point(p1, p2):
|
27 |
+
"""Returns the middle point (x,y) between two points
|
28 |
+
|
29 |
+
Arguments:
|
30 |
+
p1 (dlib.point): First point
|
31 |
+
p2 (dlib.point): Second point
|
32 |
+
"""
|
33 |
+
x = int((p1.x + p2.x) / 2)
|
34 |
+
y = int((p1.y + p2.y) / 2)
|
35 |
+
return (x, y)
|
36 |
+
|
37 |
+
def _isolate(self, frame, landmarks, points):
|
38 |
+
"""Isolate an eye, to have a frame without other part of the face.
|
39 |
+
|
40 |
+
Arguments:
|
41 |
+
frame (numpy.ndarray): Frame containing the face
|
42 |
+
landmarks (dlib.full_object_detection): Facial landmarks for the face region
|
43 |
+
points (list): Points of an eye (from the 68 Multi-PIE landmarks)
|
44 |
+
"""
|
45 |
+
region = np.array([(landmarks.part(point).x, landmarks.part(point).y) for point in points])
|
46 |
+
region = region.astype(np.int32)
|
47 |
+
self.landmark_points = region
|
48 |
+
|
49 |
+
# Applying a mask to get only the eye
|
50 |
+
height, width = frame.shape[:2]
|
51 |
+
black_frame = np.zeros((height, width), np.uint8)
|
52 |
+
mask = np.full((height, width), 255, np.uint8)
|
53 |
+
cv2.fillPoly(mask, [region], (0, 0, 0))
|
54 |
+
eye = cv2.bitwise_not(black_frame, frame.copy(), mask=mask)
|
55 |
+
|
56 |
+
# Cropping on the eye
|
57 |
+
margin = 5
|
58 |
+
min_x = np.min(region[:, 0]) - margin
|
59 |
+
max_x = np.max(region[:, 0]) + margin
|
60 |
+
min_y = np.min(region[:, 1]) - margin
|
61 |
+
max_y = np.max(region[:, 1]) + margin
|
62 |
+
|
63 |
+
self.frame = eye[min_y:max_y, min_x:max_x]
|
64 |
+
self.origin = (min_x, min_y)
|
65 |
+
|
66 |
+
height, width = self.frame.shape[:2]
|
67 |
+
self.center = (width / 2, height / 2)
|
68 |
+
|
69 |
+
def _blinking_ratio(self, landmarks, points):
|
70 |
+
"""Calculates a ratio that can indicate whether an eye is closed or not.
|
71 |
+
It's the division of the width of the eye, by its height.
|
72 |
+
|
73 |
+
Arguments:
|
74 |
+
landmarks (dlib.full_object_detection): Facial landmarks for the face region
|
75 |
+
points (list): Points of an eye (from the 68 Multi-PIE landmarks)
|
76 |
+
|
77 |
+
Returns:
|
78 |
+
The computed ratio
|
79 |
+
"""
|
80 |
+
left = (landmarks.part(points[0]).x, landmarks.part(points[0]).y)
|
81 |
+
right = (landmarks.part(points[3]).x, landmarks.part(points[3]).y)
|
82 |
+
top = self._middle_point(landmarks.part(points[1]), landmarks.part(points[2]))
|
83 |
+
bottom = self._middle_point(landmarks.part(points[5]), landmarks.part(points[4]))
|
84 |
+
|
85 |
+
eye_width = math.hypot((left[0] - right[0]), (left[1] - right[1]))
|
86 |
+
eye_height = math.hypot((top[0] - bottom[0]), (top[1] - bottom[1]))
|
87 |
+
|
88 |
+
try:
|
89 |
+
ratio = eye_width / eye_height
|
90 |
+
except ZeroDivisionError:
|
91 |
+
ratio = None
|
92 |
+
|
93 |
+
return ratio
|
94 |
+
|
95 |
+
def _analyze(self, original_frame, landmarks, side, calibration):
|
96 |
+
"""Detects and isolates the eye in a new frame, sends data to the calibration
|
97 |
+
and initializes Pupil object.
|
98 |
+
|
99 |
+
Arguments:
|
100 |
+
original_frame (numpy.ndarray): Frame passed by the user
|
101 |
+
landmarks (dlib.full_object_detection): Facial landmarks for the face region
|
102 |
+
side: Indicates whether it's the left eye (0) or the right eye (1)
|
103 |
+
calibration (calibration.Calibration): Manages the binarization threshold value
|
104 |
+
"""
|
105 |
+
if side == 0:
|
106 |
+
points = self.LEFT_EYE_POINTS
|
107 |
+
elif side == 1:
|
108 |
+
points = self.RIGHT_EYE_POINTS
|
109 |
+
else:
|
110 |
+
return
|
111 |
+
|
112 |
+
self.blinking = self._blinking_ratio(landmarks, points)
|
113 |
+
self._isolate(original_frame, landmarks, points)
|
114 |
+
|
115 |
+
if not calibration.is_complete():
|
116 |
+
calibration.evaluate(self.frame, side)
|
117 |
+
|
118 |
+
threshold = calibration.threshold(side)
|
119 |
+
self.pupil = Pupil(self.frame, threshold)
|
GazeTracking/gaze_tracking/gaze_tracking.py
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import division
|
2 |
+
import os
|
3 |
+
import cv2
|
4 |
+
import dlib
|
5 |
+
from .eye import Eye
|
6 |
+
from .calibration import Calibration
|
7 |
+
|
8 |
+
|
9 |
+
class GazeTracking(object):
|
10 |
+
"""
|
11 |
+
This class tracks the user's gaze.
|
12 |
+
It provides useful information like the position of the eyes
|
13 |
+
and pupils and allows to know if the eyes are open or closed
|
14 |
+
"""
|
15 |
+
|
16 |
+
def __init__(self):
|
17 |
+
self.frame = None
|
18 |
+
self.eye_left = None
|
19 |
+
self.eye_right = None
|
20 |
+
self.calibration = Calibration()
|
21 |
+
|
22 |
+
# _face_detector is used to detect faces
|
23 |
+
self._face_detector = dlib.get_frontal_face_detector()
|
24 |
+
|
25 |
+
# _predictor is used to get facial landmarks of a given face
|
26 |
+
cwd = os.path.abspath(os.path.dirname(__file__))
|
27 |
+
model_path = os.path.abspath(os.path.join(cwd, "trained_models/shape_predictor_68_face_landmarks.dat"))
|
28 |
+
self._predictor = dlib.shape_predictor(model_path)
|
29 |
+
|
30 |
+
@property
|
31 |
+
def pupils_located(self):
|
32 |
+
"""Check that the pupils have been located"""
|
33 |
+
try:
|
34 |
+
int(self.eye_left.pupil.x)
|
35 |
+
int(self.eye_left.pupil.y)
|
36 |
+
int(self.eye_right.pupil.x)
|
37 |
+
int(self.eye_right.pupil.y)
|
38 |
+
return True
|
39 |
+
except Exception:
|
40 |
+
return False
|
41 |
+
|
42 |
+
def _analyze(self):
|
43 |
+
"""Detects the face and initialize Eye objects"""
|
44 |
+
frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
|
45 |
+
faces = self._face_detector(frame)
|
46 |
+
|
47 |
+
try:
|
48 |
+
landmarks = self._predictor(frame, faces[0])
|
49 |
+
self.eye_left = Eye(frame, landmarks, 0, self.calibration)
|
50 |
+
self.eye_right = Eye(frame, landmarks, 1, self.calibration)
|
51 |
+
|
52 |
+
except IndexError:
|
53 |
+
self.eye_left = None
|
54 |
+
self.eye_right = None
|
55 |
+
|
56 |
+
def refresh(self, frame):
|
57 |
+
"""Refreshes the frame and analyzes it.
|
58 |
+
|
59 |
+
Arguments:
|
60 |
+
frame (numpy.ndarray): The frame to analyze
|
61 |
+
"""
|
62 |
+
self.frame = frame
|
63 |
+
self._analyze()
|
64 |
+
|
65 |
+
def pupil_left_coords(self):
|
66 |
+
"""Returns the coordinates of the left pupil"""
|
67 |
+
if self.pupils_located:
|
68 |
+
x = self.eye_left.origin[0] + self.eye_left.pupil.x
|
69 |
+
y = self.eye_left.origin[1] + self.eye_left.pupil.y
|
70 |
+
return (x, y)
|
71 |
+
|
72 |
+
def pupil_right_coords(self):
|
73 |
+
"""Returns the coordinates of the right pupil"""
|
74 |
+
if self.pupils_located:
|
75 |
+
x = self.eye_right.origin[0] + self.eye_right.pupil.x
|
76 |
+
y = self.eye_right.origin[1] + self.eye_right.pupil.y
|
77 |
+
return (x, y)
|
78 |
+
|
79 |
+
def horizontal_ratio(self):
|
80 |
+
"""Returns a number between 0.0 and 1.0 that indicates the
|
81 |
+
horizontal direction of the gaze. The extreme right is 0.0,
|
82 |
+
the center is 0.5 and the extreme left is 1.0
|
83 |
+
"""
|
84 |
+
if self.pupils_located:
|
85 |
+
pupil_left = self.eye_left.pupil.x / (self.eye_left.center[0] * 2 - 10)
|
86 |
+
pupil_right = self.eye_right.pupil.x / (self.eye_right.center[0] * 2 - 10)
|
87 |
+
return (pupil_left + pupil_right) / 2
|
88 |
+
|
89 |
+
def vertical_ratio(self):
|
90 |
+
"""Returns a number between 0.0 and 1.0 that indicates the
|
91 |
+
vertical direction of the gaze. The extreme top is 0.0,
|
92 |
+
the center is 0.5 and the extreme bottom is 1.0
|
93 |
+
"""
|
94 |
+
if self.pupils_located:
|
95 |
+
pupil_left = self.eye_left.pupil.y / (self.eye_left.center[1] * 2 - 10)
|
96 |
+
pupil_right = self.eye_right.pupil.y / (self.eye_right.center[1] * 2 - 10)
|
97 |
+
return (pupil_left + pupil_right) / 2
|
98 |
+
|
99 |
+
def is_right(self):
|
100 |
+
"""Returns true if the user is looking to the right"""
|
101 |
+
if self.pupils_located:
|
102 |
+
return self.horizontal_ratio() <= 0.35
|
103 |
+
|
104 |
+
def is_left(self):
|
105 |
+
"""Returns true if the user is looking to the left"""
|
106 |
+
if self.pupils_located:
|
107 |
+
return self.horizontal_ratio() >= 0.65
|
108 |
+
|
109 |
+
def is_center(self):
|
110 |
+
"""Returns true if the user is looking to the center"""
|
111 |
+
if self.pupils_located:
|
112 |
+
return self.is_right() is not True and self.is_left() is not True
|
113 |
+
|
114 |
+
def is_blinking(self):
|
115 |
+
"""Returns true if the user closes his eyes"""
|
116 |
+
if self.pupils_located:
|
117 |
+
blinking_ratio = (self.eye_left.blinking + self.eye_right.blinking) / 2
|
118 |
+
return blinking_ratio > 3.8
|
119 |
+
|
120 |
+
def annotated_frame(self):
|
121 |
+
"""Returns the main frame with pupils highlighted"""
|
122 |
+
frame = self.frame.copy()
|
123 |
+
|
124 |
+
if self.pupils_located:
|
125 |
+
color = (0, 255, 0)
|
126 |
+
x_left, y_left = self.pupil_left_coords()
|
127 |
+
x_right, y_right = self.pupil_right_coords()
|
128 |
+
cv2.line(frame, (x_left - 5, y_left), (x_left + 5, y_left), color)
|
129 |
+
cv2.line(frame, (x_left, y_left - 5), (x_left, y_left + 5), color)
|
130 |
+
cv2.line(frame, (x_right - 5, y_right), (x_right + 5, y_right), color)
|
131 |
+
cv2.line(frame, (x_right, y_right - 5), (x_right, y_right + 5), color)
|
132 |
+
|
133 |
+
return frame
|
GazeTracking/gaze_tracking/pupil.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import numpy as np
|
2 |
+
import cv2
|
3 |
+
|
4 |
+
|
5 |
+
class Pupil(object):
|
6 |
+
"""
|
7 |
+
This class detects the iris of an eye and estimates
|
8 |
+
the position of the pupil
|
9 |
+
"""
|
10 |
+
|
11 |
+
def __init__(self, eye_frame, threshold):
|
12 |
+
self.iris_frame = None
|
13 |
+
self.threshold = threshold
|
14 |
+
self.x = None
|
15 |
+
self.y = None
|
16 |
+
|
17 |
+
self.detect_iris(eye_frame)
|
18 |
+
|
19 |
+
@staticmethod
|
20 |
+
def image_processing(eye_frame, threshold):
|
21 |
+
"""Performs operations on the eye frame to isolate the iris
|
22 |
+
|
23 |
+
Arguments:
|
24 |
+
eye_frame (numpy.ndarray): Frame containing an eye and nothing else
|
25 |
+
threshold (int): Threshold value used to binarize the eye frame
|
26 |
+
|
27 |
+
Returns:
|
28 |
+
A frame with a single element representing the iris
|
29 |
+
"""
|
30 |
+
kernel = np.ones((3, 3), np.uint8)
|
31 |
+
new_frame = cv2.bilateralFilter(eye_frame, 10, 15, 15)
|
32 |
+
new_frame = cv2.erode(new_frame, kernel, iterations=3)
|
33 |
+
new_frame = cv2.threshold(new_frame, threshold, 255, cv2.THRESH_BINARY)[1]
|
34 |
+
|
35 |
+
return new_frame
|
36 |
+
|
37 |
+
def detect_iris(self, eye_frame):
|
38 |
+
"""Detects the iris and estimates the position of the iris by
|
39 |
+
calculating the centroid.
|
40 |
+
|
41 |
+
Arguments:
|
42 |
+
eye_frame (numpy.ndarray): Frame containing an eye and nothing else
|
43 |
+
"""
|
44 |
+
self.iris_frame = self.image_processing(eye_frame, self.threshold)
|
45 |
+
|
46 |
+
contours, _ = cv2.findContours(self.iris_frame, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:]
|
47 |
+
contours = sorted(contours, key=cv2.contourArea)
|
48 |
+
|
49 |
+
try:
|
50 |
+
moments = cv2.moments(contours[-2])
|
51 |
+
self.x = int(moments['m10'] / moments['m00'])
|
52 |
+
self.y = int(moments['m01'] / moments['m00'])
|
53 |
+
except (IndexError, ZeroDivisionError):
|
54 |
+
pass
|
GazeTracking/gaze_tracking/trained_models/shape_predictor_68_face_landmarks.dat
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:fbdc2cb80eb9aa7a758672cbfdda32ba6300efe9b6e6c7a299ff7e736b11b92f
|
3 |
+
size 99693937
|
GazeTracking/real.mp4
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:c1d5eb63db59e8cf3bbe1b4b8cc9e31c3c4087f29288e9a3ab4a4e9d0c60080d
|
3 |
+
size 4480223
|
GazeTracking/requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
numpy == 1.22.0
|
2 |
+
opencv_python == 4.2.0.32
|
3 |
+
dlib == 19.16.0
|