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
std
::
vector
<
image_window
::
overlay_line
>
lines
;
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()"
<<
"
\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
()
);
const
full_object_detection
&
d
=
dets
[
i
];
// Around Chin. Ear to Ear
for
(
unsigned
long
i
=
1
;
i
<=
16
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Line on top of nose
for
(
unsigned
long
i
=
28
;
i
<=
30
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// left eyebrow
for
(
unsigned
long
i
=
18
;
i
<=
21
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Right eyebrow
for
(
unsigned
long
i
=
23
;
i
<=
26
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Bottom part of the nose
for
(
unsigned
long
i
=
31
;
i
<=
35
;
++
i
)
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 eye
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
(
36
),
d
.
part
(
41
),
color
));
// Right eye
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
(
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
));
if
(
d
.
num_parts
()
==
5
)
{
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
0
),
d
.
part
(
1
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
1
),
d
.
part
(
4
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
4
),
d
.
part
(
3
),
color
));
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
3
),
d
.
part
(
2
),
color
));
}
else
{
// Around Chin. Ear to Ear
for
(
unsigned
long
i
=
1
;
i
<=
16
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Line on top of nose
for
(
unsigned
long
i
=
28
;
i
<=
30
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// left eyebrow
for
(
unsigned
long
i
=
18
;
i
<=
21
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Right eyebrow
for
(
unsigned
long
i
=
23
;
i
<=
26
;
++
i
)
lines
.
push_back
(
image_window
::
overlay_line
(
d
.
part
(
i
),
d
.
part
(
i
-
1
),
color
));
// Bottom part of the nose
for
(
unsigned
long
i
=
31
;
i
<=
35
;
++
i
)
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 eye
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
(
36
),
d
.
part
(
41
),
color
));
// Right eye
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
(
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
;
}
...
...
dlib/image_processing/render_face_detections_abstract.h
View file @
1c7bbbd4
...
...
@@ -18,14 +18,21 @@ namespace dlib
/*!
requires
- for all valid i:
- dets[i].num_parts() == 68
- dets[i].num_parts() == 68
|| dets[i].num_parts() == 5
ensures
- 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
will draw the objects onto the screen in a way that properly draws the
outline of the face features defined by the part locations.
either the iBUG face landmark scheme or a 5 point face annotation. We then
return a set of overlay lines that will draw the objects onto the screen in a
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
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
);
/*!
requires
- det.num_parts() == 68
- det.num_parts() == 68
|| det.num_parts() == 5
ensures
- This function is identical to the above render_face_detections() routine
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
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()"
<<
"
\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
()
);
DLIB_CASSERT
(
padding
>=
0
&&
size
>
0
,
...
...
@@ -2003,43 +2003,84 @@ namespace dlib
<<
"
\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
;
for
(
unsigned
long
i
=
17
;
i
<
det
.
num_parts
();
++
i
)
from_points
.
push_back
(
p2
*
size
);
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
if
((
55
<=
i
&&
i
<=
59
)
||
(
65
<=
i
&&
i
<=
67
))
continue
;
// Ignore the eyebrows
if
(
17
<=
i
&&
i
<=
26
)
continue
;
dlib
::
vector
<
double
,
2
>
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
));
// 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
);
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
));
...
...
dlib/image_transforms/interpolation_abstract.h
View file @
1c7bbbd4
...
...
@@ -1365,20 +1365,30 @@ namespace dlib
);
/*!
requires
- det.num_parts() == 68
- det.num_parts() == 68
|| det.num_parts() == 5
- size > 0
- padding >= 0
ensures
- This function assumes det contains a human face detection with face parts
annotated using the annotation scheme from the iBUG 300-W face landmark
dataset. Given these assumptions, it creates a chip_details object that will
extract a copy of the face that has been rotated upright, centered, and
scaled to a standard size when given to extract_image_chip().
dataset or a 5 point face annotation. Given these assumptions, it creates a
chip_details object that will extract a copy of the face that has been
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.
- if padding == 0 then the chip will be closely cropped around the face.
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
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