Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
1c7bbbd4
Commit
1c7bbbd4
authored
Sep 15, 2017
by
Davis King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upgraded render_face_detections() and get_face_chip_details() to support 5
point face landmark models.
parent
3fff7f84
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
155 additions
and
86 deletions
+155
-86
render_face_detections.h
dlib/image_processing/render_face_detections.h
+52
-41
render_face_detections_abstract.h
dlib/image_processing/render_face_detections_abstract.h
+12
-5
interpolation.h
dlib/image_transforms/interpolation.h
+77
-36
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
.
03
8915
,
0
.
01
87482
,
0
.
0344
891
,
0
.
0773
906
,
0
.
0773
906
,
0
.
0344
891
,
0
.
01
87482
,
0
.
03
8915
,
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
.
03
8915
,
0
.
01
87482
,
0
.
0344
891
,
0
.
0773
906
,
0
.
0773
906
,
0
.
0344
891
,
0
.
01
87482
,
0
.
03
8915
,
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