Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
bob
bob.db.fargo
Commits
b0e78cef
Commit
b0e78cef
authored
May 01, 2017
by
Guillaume HEUSCH
Browse files
[extract eyes] made scripts to extract eyes center from detected landmarks
parent
3fce204b
Changes
2
Hide whitespace changes
Inline
Side-by-side
bob/db/fargo/scripts/eyes_center_from_landmarks.py
0 → 100644
View file @
b0e78cef
#!/usr/bin/env python
# encoding: utf-8
# Guillaume HEUSCH <guillaume.heusch@idiap.ch>
# Mon 21 Nov 08:25:54 CET 2016
"""Eyes center extractor for the FARGO images (%(version)s)
Usage:
%(prog)s [--ldmdir=<path>] [--eyesdir=<path>] [--imagesdir=<path>]
[--verbose ...] [--plot] [--log=<string>]
Options:
-h, --help Show this screen.
-V, --version Show version.
-l, --ldmdir=<path> The path to the landmarks on your disk.
-e, --eyesdir=<path> Where to store saved images.
-i, --imagesdir=<path> Where the images are stored.
--log=<string> Log filename [default: logs.txt]
-v, --verbose Increase the verbosity (may appear multiple times).
-P, --plot Show some stuff
Example:
To get the eyes center, do
$ %(prog)s --ldmdir path/to/database
See '%(prog)s --help' for more information.
"""
import
os
import
sys
import
pkg_resources
import
logging
__logging_format__
=
'[%(levelname)s] %(message)s'
logging
.
basicConfig
(
format
=
__logging_format__
)
logger
=
logging
.
getLogger
(
"extract_log"
)
from
docopt
import
docopt
version
=
pkg_resources
.
require
(
'bob.db.fargo'
)[
0
].
version
import
numpy
import
bob.io.base
import
bob.io.image
import
bob.ip.draw
def
get_frame
(
image_dir
,
index
):
""" get_frame(image_dir, index) -> frame
This function gets the frame that corresponds to the landmarks.
**Parameters**
``image_dir`` (path):
The dir continaing the image
``index`` (int):
The index of the image
**Returns**
``frame`` (numpy array):
The frame where the annotation have been made
"""
image_file
=
os
.
path
.
join
(
image_dir
,
'{:0>2d}.png'
.
format
(
index
))
if
os
.
path
.
isfile
(
image_file
):
frame
=
bob
.
io
.
base
.
load
(
image_file
)
return
frame
def
is_annotation_complete
(
landmarks
):
""" is_annotation_complete(landmarks) -> True or False
This function checks if the landmarks read from the provided
file contain what we need to infer eyes center (i.e. eyes corner)
**Parameters**
``landmarks`` (dict):
The landmarks, read from a txt file and stored as a dict
**Returns**
``bool`` (boolean):
True if all eyes corners are present, False otherwise.
"""
if
'1'
not
in
landmarks
.
keys
()
or
'2'
not
in
landmarks
.
keys
()
or
'3'
not
in
landmarks
.
keys
()
or
'4'
not
in
landmarks
.
keys
():
return
False
return
True
def
get_eyes_center
(
landmarks
):
""" get_eyes_center(landmarks) -> eyes_center
This function computes the position of the eyes center,
based on eyes corners.
Note that left and right are defined wrt the imaged subject.
**Parameters**
``landmarks`` (dict):
The landmarks, read from a txt file and stored as a dict
**Returns**
``eyes_center`` (tuple):
Tuple containing the (x, y) position of the right and left eye.
"""
reye_x
=
int
(
0.5
*
(
landmarks
[
'1'
][
1
]
+
landmarks
[
'2'
][
1
]))
reye_y
=
int
(
0.5
*
(
landmarks
[
'1'
][
0
]
+
landmarks
[
'2'
][
0
]))
leye_x
=
int
(
0.5
*
(
landmarks
[
'3'
][
1
]
+
landmarks
[
'4'
][
1
]))
leye_y
=
int
(
0.5
*
(
landmarks
[
'3'
][
0
]
+
landmarks
[
'4'
][
0
]))
return
(
reye_x
,
reye_y
,
leye_x
,
leye_y
)
def
draw_eyes_center
(
frame
,
positions
):
""" draw_eyes_center(frame, positions) -> frame
This function draws the computed eyes center on the provided image.
**Parameters**
``frame`` (numpy array):
The frame on which to draw eyes center.
``positions`` (tuple):
The position of the center of both eyes.
"""
reye_x
=
positions
[
0
]
reye_y
=
positions
[
1
]
leye_x
=
positions
[
2
]
leye_y
=
positions
[
3
]
if
frame
.
shape
[
0
]
==
3
:
bob
.
ip
.
draw
.
cross
(
frame
,
(
reye_y
,
reye_x
),
4
,
(
255
,
0
,
0
))
bob
.
ip
.
draw
.
cross
(
frame
,
(
leye_y
,
leye_x
),
4
,
(
255
,
0
,
0
))
else
:
bob
.
ip
.
draw
.
cross
(
frame
,
(
reye_y
,
reye_x
),
4
,
(
255
))
bob
.
ip
.
draw
.
cross
(
frame
,
(
leye_y
,
leye_x
),
4
,
(
255
))
return
frame
def
draw_landmarks
(
frame
,
landmarks
):
""" draw_landmarks(frame, landmarks) -> frame
This function draws both the original landmarks (provided in the file)
and the projected ones.
**Parameters**
``frame`` (numpy array):
The frame on which to draw eyes center.
``landmarks`` (dict):
The landmarks
"""
for
i
in
landmarks
.
keys
():
if
frame
.
shape
[
0
]
==
3
:
bob
.
ip
.
draw
.
plus
(
frame
,
(
landmarks
[
i
][
0
],
landmarks
[
i
][
1
]),
4
,
(
0
,
255
,
0
))
else
:
bob
.
ip
.
draw
.
plus
(
frame
,
(
landmarks
[
i
][
0
],
landmarks
[
i
][
1
]),
4
,
(
255
))
return
frame
def
get_landmarks
(
annotation_file
):
""" get_landmarks(annotation_file) -> landmarks
This function reads landmarks from a file and load
them into a dictionary.
Note: left and right are defined in terms of subject
Landmarks:
1 right corner of right eye
2 left corner of right eye
3 right corner of left eye
4 left corner of left eye
5
6
7
8
9
10
11
12
13
14
15
16
**Parameters**
``annotated_file`` (path):
The path to the file containing the landmarks.
**Returns**
``landmarks`` (dict):
The landmarks.
"""
with
open
(
annotation_file
,
"r"
)
as
c
:
landmarks
=
{}
for
line
in
c
:
line
=
line
.
rstrip
()
ints
=
line
.
split
()
landmarks
[
ints
[
0
]]
=
((
int
(
ints
[
2
]),
int
(
ints
[
1
])))
return
landmarks
def
write_eyes_pos
(
eyes
,
eyes_dir
):
""" write_eyes_pos(eyes, eyes_dir)
This function write the eyes center in text file(s).
**Parameters**
``eyes`` (tuple):
tuple containing the (x,y) coordinates of the eyes center.
``eyes_dir`` (path):
The path to the dir where the file(s) are written.
"""
if
not
os
.
path
.
isdir
(
eyes_dir
):
os
.
makedirs
(
eyes_dir
)
for
i
in
range
(
0
,
10
):
eyes_filename
=
os
.
path
.
join
(
eyes_dir
,
'{:0>2d}.pos'
.
format
(
i
))
eyes_file
=
open
(
eyes_filename
,
'w'
)
eyes_file
.
write
(
'{0} {1} {2} {3}'
.
format
(
eyes
[
0
],
eyes
[
1
],
eyes
[
2
],
eyes
[
3
]))
eyes_file
.
close
()
def
annotations_exist
(
annotation_dir
):
"""annotations_exist(annotation_dir) -> [True, False]
This function checks if the annotation (i.e. eyes center) already exists
**Parameters**
``annotation_dir`` (path):
The directory where the annotations should be saved.
**Returns**
``bool`` (boolean):
True if all annotations exist, False otherwise.
"""
for
i
in
range
(
0
,
10
):
annotation_file
=
os
.
path
.
join
(
annotation_dir
,
'{:0>2d}.pos'
.
format
(
i
))
if
not
os
.
path
.
isfile
(
annotation_file
):
return
False
return
True
def
main
(
user_input
=
None
):
"""
Main function to extract eyes center from existing annotations.
"""
# Parse the command-line arguments
if
user_input
is
not
None
:
arguments
=
user_input
else
:
arguments
=
sys
.
argv
[
1
:]
prog
=
os
.
path
.
basename
(
sys
.
argv
[
0
])
completions
=
dict
(
prog
=
prog
,
version
=
version
,)
args
=
docopt
(
__doc__
%
completions
,
argv
=
arguments
,
version
=
'Eyes position extractor (%s)'
%
version
,)
# if the user wants more verbosity, lowers the logging level
if
args
[
'--verbose'
]
==
1
:
logging
.
getLogger
(
"extract_log"
).
setLevel
(
logging
.
INFO
)
elif
args
[
'--verbose'
]
>=
2
:
logging
.
getLogger
(
"extract_log"
).
setLevel
(
logging
.
DEBUG
)
if
args
[
'--ldmdir'
]
is
None
:
logger
.
warning
(
"You should provide a valid path to the landmarks"
)
sys
.
exit
()
base_dir
=
args
[
'--ldmdir'
]
if
not
os
.
path
.
isdir
(
args
[
'--eyesdir'
]):
os
.
mkdir
(
args
[
'--eyesdir'
])
logfile
=
open
(
args
[
'--log'
],
'w'
)
# to compute various stats
total_counter
=
0
inexisting_counter
=
0
incomplete_counter
=
0
projection_counter
=
0
heuristic_counter
=
0
# go through the subjects
for
subject
in
os
.
listdir
(
base_dir
):
sessions
=
[
'controlled'
,
'dark'
,
'outdoor'
]
# small hack to process FdV subjects ...
if
int
(
subject
)
>=
129
:
sessions
=
[
'fdv'
]
for
session
in
sessions
:
session_dir
=
os
.
path
.
abspath
(
os
.
path
.
join
(
base_dir
,
subject
,
session
))
for
condition
in
[
'SR300-laptop'
,
'SR300-mobile'
]:
for
recording
in
[
'0'
,
'1'
]:
logger
.
debug
(
"===== Subject {0}, session {1}, device {2}, recording {3} ..."
.
format
(
subject
,
session
,
condition
,
recording
))
# create directories to save the extracted annotations
if
not
os
.
path
.
isdir
(
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
)):
os
.
makedirs
(
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
))
if
not
os
.
path
.
isdir
(
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'color'
)):
os
.
makedirs
(
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'color'
))
if
not
os
.
path
.
isdir
(
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'ir'
)):
os
.
makedirs
(
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'ir'
))
if
not
os
.
path
.
isdir
(
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'depth'
)):
os
.
makedirs
(
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'depth'
))
# the directories - input
recording_dir
=
os
.
path
.
join
(
session_dir
,
condition
,
recording
)
color_dir
=
os
.
path
.
join
(
recording_dir
,
'color'
)
ir_dir
=
os
.
path
.
join
(
recording_dir
,
'ir'
)
# the directories - output
color_eyes_dir
=
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'color'
)
ir_eyes_dir
=
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'ir'
)
depth_eyes_dir
=
os
.
path
.
join
(
args
[
'--eyesdir'
],
subject
,
session
,
condition
,
recording
,
'depth'
)
# check if annotations for this recording already exists
if
annotations_exist
(
color_eyes_dir
)
and
annotations_exist
(
ir_eyes_dir
)
and
annotations_exist
(
depth_eyes_dir
):
logger
.
warn
(
'Existing annotations for {0}'
.
format
(
recording_dir
))
continue
# loop on the images extracted from this sequences
for
i
in
range
(
0
,
10
):
# read the original landmarks - color
color_ldm_file
=
os
.
path
.
join
(
color_dir
,
'{:0>2d}.pos'
.
format
(
i
))
try
:
color_landmarks
=
get_landmarks
(
color_ldm_file
)
except
IOError
:
logger
.
warn
(
"No color annotations for recording {0}"
.
format
(
recording_dir
))
logfile
.
write
(
'[NO ANNOTATIONS] '
+
color_dir
+
'
\n
'
)
inexisting_counter
+=
1
# read the original landmarks - ir
ir_ldm_file
=
os
.
path
.
join
(
ir_dir
,
'{:0>2d}.pos'
.
format
(
i
))
try
:
ir_landmarks
=
get_landmarks
(
ir_ldm_file
)
except
IOError
:
logger
.
warn
(
"No ir annotations for recording {0}"
.
format
(
recording_dir
))
logfile
.
write
(
'[NO ANNOTATIONS] '
+
ir_dir
+
'
\n
'
)
inexisting_counter
+=
1
# check if we have all we need (possibly after re-projection)
if
is_annotation_complete
(
color_landmarks
)
and
is_annotation_complete
(
ir_landmarks
):
# get the eyes center
color_eyes
=
get_eyes_center
(
color_landmarks
)
ir_eyes
=
get_eyes_center
(
ir_landmarks
)
# and save the file(s) - note that ir and depth are the same
write_eyes_pos
(
color_eyes
,
color_eyes_dir
)
write_eyes_pos
(
ir_eyes
,
ir_eyes_dir
)
write_eyes_pos
(
ir_eyes
,
depth_eyes_dir
)
# plot stuff if asked for
if
bool
(
args
[
'--plot'
]):
if
args
[
'--imagesdir'
]
is
None
:
logger
.
warn
(
"You should provide an image directory if you want to plot something ..."
)
else
:
color_frame_dir
=
os
.
path
.
join
(
args
[
'--imagesdir'
],
subject
,
session
,
condition
,
recording
,
'color'
)
color_frame
=
get_frame
(
color_frame_dir
,
i
)
display_color
=
draw_eyes_center
(
color_frame
,
color_eyes
)
ir_frame_dir
=
os
.
path
.
join
(
args
[
'--imagesdir'
],
subject
,
session
,
condition
,
recording
,
'ir'
)
ir_frame
=
get_frame
(
ir_frame_dir
,
i
)
display_ir
=
draw_eyes_center
(
ir_frame
,
ir_eyes
)
from
matplotlib
import
pyplot
f
,
axarr
=
pyplot
.
subplots
(
1
,
2
)
pyplot
.
suptitle
(
'Inferred eyes center'
)
axarr
[
0
].
imshow
(
numpy
.
rollaxis
(
numpy
.
rollaxis
(
display_color
,
2
),
2
))
axarr
[
0
].
set_title
(
"Color"
)
axarr
[
1
].
imshow
(
display_ir
,
cmap
=
'gray'
)
axarr
[
1
].
set_title
(
"NIR"
)
pyplot
.
show
()
if
args
[
'--verbose'
]
>=
2
:
display_color
=
draw_landmarks
(
color_frame
,
color_landmarks
)
display_ir
=
draw_landmarks
(
ir_frame
,
ir_landmarks
)
f
,
axarr
=
pyplot
.
subplots
(
1
,
2
)
pyplot
.
suptitle
(
'Landmarks'
)
axarr
[
0
].
imshow
(
numpy
.
rollaxis
(
numpy
.
rollaxis
(
display_color
,
2
),
2
))
axarr
[
0
].
set_title
(
"Color"
)
axarr
[
1
].
imshow
(
display_ir
,
cmap
=
'gray'
)
axarr
[
1
].
set_title
(
"NIR"
)
pyplot
.
show
()
total_counter
+=
1
logger
.
info
(
"Processed {0} sequences"
.
format
(
total_counter
))
logger
.
info
(
"
\t
{0} had no annotations"
.
format
(
inexisting_counter
))
logger
.
info
(
"
\t
{0} needed reprojection"
.
format
(
projection_counter
))
logger
.
info
(
"
\t
{0} where incomplete"
.
format
(
incomplete_counter
))
logger
.
info
(
"
\t
{0} needed heuristic (incomplete after reprojection)"
.
format
(
heuristic_counter
))
logfile
.
close
()
setup.py
View file @
b0e78cef
...
...
@@ -38,6 +38,7 @@ setup(
'make_public_lists.py = bob.db.fargo.scripts.make_public_lists:main'
,
'make_pose_lists.py = bob.db.fargo.scripts.make_pose_lists:main'
,
'extract_eyes_center.py = bob.db.fargo.scripts.extract_eyes_center:main'
,
'eyes_center_from_landmarks.py = bob.db.fargo.scripts.eyes_center_from_landmarks:main'
,
'convert_ir_and_depth.py = bob.db.fargo.scripts.convert_ir_and_depth:main'
,
'reencode_color.py = bob.db.fargo.scripts.reencode_color:main'
,
'detect_faces_fargo.py = bob.db.fargo.scripts.detect_faces_fargo:main'
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment