Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dlib
Commits
1c7bbbd4
Commit
1c7bbbd4
authored
Sep 15, 2017
by
Davis King
Browse files
Upgraded render_face_detections() and get_face_chip_details() to support 5
point face landmark models.
parent
3fff7f84
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
155 additions
and
86 deletions
+155
-86
dlib/image_processing/render_face_detections.h
dlib/image_processing/render_face_detections.h
+52
-41
dlib/image_processing/render_face_detections_abstract.h
dlib/image_processing/render_face_detections_abstract.h
+12
-5
dlib/image_transforms/interpolation.h
dlib/image_transforms/interpolation.h
+77
-36
dlib/image_transforms/interpolation_abstract.h
dlib/image_transforms/interpolation_abstract.h
+14
-4
No files found.
dlib/image_processing/render_face_detections.h
View file @
1c7bbbd4
...
@@ -18,52 +18,63 @@ namespace dlib
...
@@ -18,52 +18,63 @@ namespace dlib
std
::
vector
<
image_window
::
overlay_line
>
lines
;
std
::
vector
<
image_window
::
overlay_line
>
lines
;
for
(
unsigned
long
i
=
0
;
i
<
dets
.
size
();
++
i
)
for
(
unsigned
long
i
=
0
;
i
<
dets
.
size
();
++
i
)
{
{
DLIB_CASSERT
(
dets
[
i
].
num_parts
()
==
68
,
DLIB_CASSERT
(
dets
[
i
].
num_parts
()
==
68
||
dets
[
i
].
num_parts
()
==
5
,
"
\t
std::vector<image_window::overlay_line> render_face_detections()"
"
\t
std::vector<image_window::overlay_line> render_face_detections()"
<<
"
\n\t
Invalid inputs were given
to this function. "
<<
"
\n\t
You have to give either a 5 point or 68 point face landmarking output
to this function. "
<<
"
\n\t
dets["
<<
i
<<
"].num_parts(): "
<<
dets
[
i
].
num_parts
()
<<
"
\n\t
dets["
<<
i
<<
"].num_parts(): "
<<
dets
[
i
].
num_parts
()
);
);
const
full_object_detection
&
d
=
dets
[
i
];
const
full_object_detection
&
d
=
dets
[
i
];
// Around Chin. Ear to Ear
for
(
unsigned
long
i
=
1
;
i
<=
16
;
++
i
)
if
(
d
.
num_parts
()
==
5
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
{
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
0
),
d
.
part
(
1
),
color
));
// Line on top of nose
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
1
),
d
.
part
(
4
),
color
));
for
(
unsigned
long
i
=
28
;
i
<=
30
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
4
),
d
.
part
(
3
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
3
),
d
.
part
(
2
),
color
));
}
// left eyebrow
else
for
(
unsigned
long
i
=
18
;
i
<=
21
;
++
i
)
{
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Around Chin. Ear to Ear
// Right eyebrow
for
(
unsigned
long
i
=
1
;
i
<=
16
;
++
i
)
for
(
unsigned
long
i
=
23
;
i
<=
26
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Bottom part of the nose
// Line on top of nose
for
(
unsigned
long
i
=
31
;
i
<=
35
;
++
i
)
for
(
unsigned
long
i
=
28
;
i
<=
30
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Line from the nose to the bottom part above
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
30
),
d
.
part
(
35
),
color
));
// left eyebrow
for
(
unsigned
long
i
=
18
;
i
<=
21
;
++
i
)
// Left eye
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
for
(
unsigned
long
i
=
37
;
i
<=
41
;
++
i
)
// Right eyebrow
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
for
(
unsigned
long
i
=
23
;
i
<=
26
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
36
),
d
.
part
(
41
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Bottom part of the nose
// Right eye
for
(
unsigned
long
i
=
31
;
i
<=
35
;
++
i
)
for
(
unsigned
long
i
=
43
;
i
<=
47
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Line from the nose to the bottom part above
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
42
),
d
.
part
(
47
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
30
),
d
.
part
(
35
),
color
));
// Lips outer part
// Left eye
for
(
unsigned
long
i
=
49
;
i
<=
59
;
++
i
)
for
(
unsigned
long
i
=
37
;
i
<=
41
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
48
),
d
.
part
(
59
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
36
),
d
.
part
(
41
),
color
));
// Lips inside part
// Right eye
for
(
unsigned
long
i
=
61
;
i
<=
67
;
++
i
)
for
(
unsigned
long
i
=
43
;
i
<=
47
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
60
),
d
.
part
(
67
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
42
),
d
.
part
(
47
),
color
));
// Lips outer part
for
(
unsigned
long
i
=
49
;
i
<=
59
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
48
),
d
.
part
(
59
),
color
));
// Lips inside part
for
(
unsigned
long
i
=
61
;
i
<=
67
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
60
),
d
.
part
(
67
),
color
));
}
}
}
return
lines
;
return
lines
;
}
}
...
...
dlib/image_processing/render_face_detections_abstract.h
View file @
1c7bbbd4
...
@@ -18,14 +18,21 @@ namespace dlib
...
@@ -18,14 +18,21 @@ namespace dlib
/*!
/*!
requires
requires
- for all valid i:
- for all valid i:
- dets[i].num_parts() == 68
- dets[i].num_parts() == 68
|| dets[i].num_parts() == 5
ensures
ensures
- Interprets the given objects as face detections with parts annotated using
- Interprets the given objects as face detections with parts annotated using
the iBUG face landmark scheme. We then return a set of overlay lines that
either the iBUG face landmark scheme or a 5 point face annotation. We then
will draw the objects onto the screen in a way that properly draws the
return a set of overlay lines that will draw the objects onto the screen in a
outline of the face features defined by the part locations.
way that properly draws the outline of the face features defined by the part
locations.
- returns a vector with dets.size() elements, each containing the lines
- returns a vector with dets.size() elements, each containing the lines
necessary to render a face detection from dets.
necessary to render a face detection from dets.
- The 5 point face annotation scheme is assumed to be:
- det part 0 == left eye corner, outside part of eye.
- det part 1 == left eye corner, inside part of eye.
- det part 2 == right eye corner, outside part of eye.
- det part 3 == right eye corner, inside part of eye.
- det part 4 == immediately under the nose, right at the top of the philtrum.
!*/
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
...
@@ -36,7 +43,7 @@ namespace dlib
...
@@ -36,7 +43,7 @@ namespace dlib
);
);
/*!
/*!
requires
requires
- det.num_parts() == 68
- det.num_parts() == 68
|| det.num_parts() == 5
ensures
ensures
- This function is identical to the above render_face_detections() routine
- This function is identical to the above render_face_detections() routine
except that it takes just a single full_object_detection instead of a
except that it takes just a single full_object_detection instead of a
...
...
dlib/image_transforms/interpolation.h
View file @
1c7bbbd4
...
@@ -1991,9 +1991,9 @@ namespace dlib
...
@@ -1991,9 +1991,9 @@ namespace dlib
const
double
padding
=
0.2
const
double
padding
=
0.2
)
)
{
{
DLIB_CASSERT
(
det
.
num_parts
()
==
68
,
DLIB_CASSERT
(
det
.
num_parts
()
==
68
||
det
.
num_parts
()
==
5
,
"
\t
chip_details get_face_chip_details()"
"
\t
chip_details get_face_chip_details()"
<<
"
\n\t
You
must give a detection with exactly 68 parts in it.
"
<<
"
\n\t
You
have to give either a 5 point or 68 point face landmarking output to this function.
"
<<
"
\n\t
det.num_parts(): "
<<
det
.
num_parts
()
<<
"
\n\t
det.num_parts(): "
<<
det
.
num_parts
()
);
);
DLIB_CASSERT
(
padding
>=
0
&&
size
>
0
,
DLIB_CASSERT
(
padding
>=
0
&&
size
>
0
,
...
@@ -2003,43 +2003,84 @@ namespace dlib
...
@@ -2003,43 +2003,84 @@ namespace dlib
<<
"
\n\t
size: "
<<
size
<<
"
\n\t
size: "
<<
size
);
);
// Average positions of face points 17-67
const
double
mean_face_shape_x
[]
=
{
0.000213256
,
0.0752622
,
0.18113
,
0.29077
,
0.393397
,
0.586856
,
0.689483
,
0.799124
,
0.904991
,
0.98004
,
0.490127
,
0.490127
,
0.490127
,
0.490127
,
0.36688
,
0.426036
,
0.490127
,
0.554217
,
0.613373
,
0.121737
,
0.187122
,
0.265825
,
0.334606
,
0.260918
,
0.182743
,
0.645647
,
0.714428
,
0.793132
,
0.858516
,
0.79751
,
0.719335
,
0.254149
,
0.340985
,
0.428858
,
0.490127
,
0.551395
,
0.639268
,
0.726104
,
0.642159
,
0.556721
,
0.490127
,
0.423532
,
0.338094
,
0.290379
,
0.428096
,
0.490127
,
0.552157
,
0.689874
,
0.553364
,
0.490127
,
0.42689
};
const
double
mean_face_shape_y
[]
=
{
0.106454
,
0.038915
,
0.0187482
,
0.0344891
,
0.0773906
,
0.0773906
,
0.0344891
,
0.0187482
,
0.038915
,
0.106454
,
0.203352
,
0.307009
,
0.409805
,
0.515625
,
0.587326
,
0.609345
,
0.628106
,
0.609345
,
0.587326
,
0.216423
,
0.178758
,
0.179852
,
0.231733
,
0.245099
,
0.244077
,
0.231733
,
0.179852
,
0.178758
,
0.216423
,
0.244077
,
0.245099
,
0.780233
,
0.745405
,
0.727388
,
0.742578
,
0.727388
,
0.745405
,
0.780233
,
0.864805
,
0.902192
,
0.909281
,
0.902192
,
0.864805
,
0.784792
,
0.778746
,
0.785343
,
0.778746
,
0.784792
,
0.824182
,
0.831803
,
0.824182
};
COMPILE_TIME_ASSERT
(
sizeof
(
mean_face_shape_x
)
/
sizeof
(
double
)
==
68
-
17
);
std
::
vector
<
dpoint
>
from_points
,
to_points
;
if
(
det
.
num_parts
()
==
5
)
{
dpoint
p0
(
0.8595674595992
,
0.2134981538014
);
dpoint
p1
(
0.6460604764104
,
0.2289674387677
);
dpoint
p2
(
0.1205750620789
,
0.2137274526848
);
dpoint
p3
(
0.3340850613712
,
0.2290642403242
);
dpoint
p4
(
0.4901123135679
,
0.6277975316475
);
p0
=
(
padding
+
p0
)
/
(
2
*
padding
+
1
);
p1
=
(
padding
+
p1
)
/
(
2
*
padding
+
1
);
p2
=
(
padding
+
p2
)
/
(
2
*
padding
+
1
);
p3
=
(
padding
+
p3
)
/
(
2
*
padding
+
1
);
p4
=
(
padding
+
p4
)
/
(
2
*
padding
+
1
);
from_points
.
push_back
(
p0
*
size
);
to_points
.
push_back
(
det
.
part
(
0
));
from_points
.
push_back
(
p1
*
size
);
to_points
.
push_back
(
det
.
part
(
1
));
std
::
vector
<
dlib
::
vector
<
double
,
2
>
>
from_points
,
to_points
;
from_points
.
push_back
(
p2
*
size
);
for
(
unsigned
long
i
=
17
;
i
<
det
.
num_parts
();
++
i
)
to_points
.
push_back
(
det
.
part
(
2
));
from_points
.
push_back
(
p3
*
size
);
to_points
.
push_back
(
det
.
part
(
3
));
from_points
.
push_back
(
p4
*
size
);
to_points
.
push_back
(
det
.
part
(
4
));
}
else
{
{
// Ignore the lower lip
// Average positions of face points 17-67
if
((
55
<=
i
&&
i
<=
59
)
||
(
65
<=
i
&&
i
<=
67
))
const
double
mean_face_shape_x
[]
=
{
continue
;
0.000213256
,
0.0752622
,
0.18113
,
0.29077
,
0.393397
,
0.586856
,
0.689483
,
0.799124
,
// Ignore the eyebrows
0.904991
,
0.98004
,
0.490127
,
0.490127
,
0.490127
,
0.490127
,
0.36688
,
0.426036
,
if
(
17
<=
i
&&
i
<=
26
)
0.490127
,
0.554217
,
0.613373
,
0.121737
,
0.187122
,
0.265825
,
0.334606
,
0.260918
,
continue
;
0.182743
,
0.645647
,
0.714428
,
0.793132
,
0.858516
,
0.79751
,
0.719335
,
0.254149
,
0.340985
,
0.428858
,
0.490127
,
0.551395
,
0.639268
,
0.726104
,
0.642159
,
0.556721
,
dlib
::
vector
<
double
,
2
>
p
;
0.490127
,
0.423532
,
0.338094
,
0.290379
,
0.428096
,
0.490127
,
0.552157
,
0.689874
,
p
.
x
()
=
(
padding
+
mean_face_shape_x
[
i
-
17
])
/
(
2
*
padding
+
1
);
0.553364
,
0.490127
,
0.42689
p
.
y
()
=
(
padding
+
mean_face_shape_y
[
i
-
17
])
/
(
2
*
padding
+
1
);
};
from_points
.
push_back
(
p
*
size
);
const
double
mean_face_shape_y
[]
=
{
to_points
.
push_back
(
det
.
part
(
i
));
0.106454
,
0.038915
,
0.0187482
,
0.0344891
,
0.0773906
,
0.0773906
,
0.0344891
,
0.0187482
,
0.038915
,
0.106454
,
0.203352
,
0.307009
,
0.409805
,
0.515625
,
0.587326
,
0.609345
,
0.628106
,
0.609345
,
0.587326
,
0.216423
,
0.178758
,
0.179852
,
0.231733
,
0.245099
,
0.244077
,
0.231733
,
0.179852
,
0.178758
,
0.216423
,
0.244077
,
0.245099
,
0.780233
,
0.745405
,
0.727388
,
0.742578
,
0.727388
,
0.745405
,
0.780233
,
0.864805
,
0.902192
,
0.909281
,
0.902192
,
0.864805
,
0.784792
,
0.778746
,
0.785343
,
0.778746
,
0.784792
,
0.824182
,
0.831803
,
0.824182
};
COMPILE_TIME_ASSERT
(
sizeof
(
mean_face_shape_x
)
/
sizeof
(
double
)
==
68
-
17
);
for
(
unsigned
long
i
=
17
;
i
<
det
.
num_parts
();
++
i
)
{
// Ignore the lower lip
if
((
55
<=
i
&&
i
<=
59
)
||
(
65
<=
i
&&
i
<=
67
))
continue
;
// Ignore the eyebrows
if
(
17
<=
i
&&
i
<=
26
)
continue
;
if
(
1
+
i
!=
37
&&
1
+
i
!=
40
&&
1
+
i
!=
43
&&
1
+
i
!=
46
&&
1
+
i
!=
34
)
continue
;
dpoint
p
;
p
.
x
()
=
(
padding
+
mean_face_shape_x
[
i
-
17
])
/
(
2
*
padding
+
1
);
p
.
y
()
=
(
padding
+
mean_face_shape_y
[
i
-
17
])
/
(
2
*
padding
+
1
);
from_points
.
push_back
(
p
*
size
);
to_points
.
push_back
(
det
.
part
(
i
));
}
}
}
return
chip_details
(
from_points
,
to_points
,
chip_dims
(
size
,
size
));
return
chip_details
(
from_points
,
to_points
,
chip_dims
(
size
,
size
));
...
...
dlib/image_transforms/interpolation_abstract.h
View file @
1c7bbbd4
...
@@ -1365,20 +1365,30 @@ namespace dlib
...
@@ -1365,20 +1365,30 @@ namespace dlib
);
);
/*!
/*!
requires
requires
- det.num_parts() == 68
- det.num_parts() == 68
|| det.num_parts() == 5
- size > 0
- size > 0
- padding >= 0
- padding >= 0
ensures
ensures
- This function assumes det contains a human face detection with face parts
- This function assumes det contains a human face detection with face parts
annotated using the annotation scheme from the iBUG 300-W face landmark
annotated using the annotation scheme from the iBUG 300-W face landmark
dataset. Given these assumptions, it creates a chip_details object that will
dataset or a 5 point face annotation. Given these assumptions, it creates a
extract a copy of the face that has been rotated upright, centered, and
chip_details object that will extract a copy of the face that has been
scaled to a standard size when given to extract_image_chip().
rotated upright, centered, and scaled to a standard size when given to
extract_image_chip().
- This function is specifically calibrated to work with one of these models:
- http://dlib.net/files/shape_predictor_5_face_landmarks.dat.bz2
- http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
- The extracted chips will have size rows and columns in them.
- The extracted chips will have size rows and columns in them.
- if padding == 0 then the chip will be closely cropped around the face.
- if padding == 0 then the chip will be closely cropped around the face.
Setting larger padding values will result a looser cropping. In particular,
Setting larger padding values will result a looser cropping. In particular,
a padding of 0.5 would double the width of the cropped area, a value of 1
a padding of 0.5 would double the width of the cropped area, a value of 1
would triple it, and so forth.
would triple it, and so forth.
- The 5 point face annotation scheme is assumed to be:
- det part 0 == left eye corner, outside part of eye.
- det part 1 == left eye corner, inside part of eye.
- det part 2 == right eye corner, outside part of eye.
- det part 3 == right eye corner, inside part of eye.
- det part 4 == immediately under the nose, right at the top of the philtrum.
!*/
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a 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