-
Notifications
You must be signed in to change notification settings - Fork 0
/
eyedist.cpp
138 lines (131 loc) · 4.89 KB
/
eyedist.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// eyedist.cpp: calculate eye-mouth and inter-eye dist
//
// The functions in this file know how to deal with missing points. This
// matters during testing when we are comparing results to manually
// landmarked reference shapes. For example, a reference eye pupil may be
// concealed by the side of the nose. When calculating the inter-eye
// distance, if the pupil is missing we can instead use a point near the
// pupil. We must then adjust the point-to-point distance calculated using
// this surrogate point. We use the mean face shape to figure out the
// adjustment. The accuracy of the resulting estimated inter-eye distance will
// depend upon how similar the proportions of the face are to the mean face.
//
// Copyright (C) 2005-2013, Stephen Milborrow
#include "stasm.h"
namespace stasm
{
static int TabPoint( // return first used point in tab, -1 if none
const int* tab, // in
int ntab, // in
const Shape& shape) // in
{
for (int i = 0; i < ntab; i++)
if (PointUsed(shape, tab[i]))
return tab[i]; // note return
return -1;
}
static double CanonicalEyeMouthDist( // return 0 if pupils and mouth not avail
const Shape& shape17) // in
{
if (!PointUsed(shape17, L17_LPupil) ||
!PointUsed(shape17, L17_RPupil) ||
!PointUsed(shape17, L17_CBotOfBotLip))
{
return 0; // note return
}
return PointDist(
MeanPoint(shape17, L17_LPupil, L17_RPupil, IX), // eye mid point
MeanPoint(shape17, L17_LPupil, L17_RPupil, IY),
shape17(L17_CBotOfBotLip, IX), // bot of bot lip
shape17(L17_CBotOfBotLip, IY));
}
double EyeMouthDist( // eye-mouth distance of a face shape, return 1 if not a face
const Shape& shape) // in
{
static const int eyes[] = // surrogates for pupil midpoint
{
L17_LPupil,
L17_RPupil,
L17_LEyeOuter,
L17_REyeOuter,
L17_LEyeInner,
L17_REyeInner,
L17_LEyebrowInner,
L17_REyebrowInner,
L17_LEyebrowOuter,
L17_REyebrowOuter
};
static const int mouths[] = // surrogates for bot of bot lip
{
L17_CBotOfBotLip,
L17_CTopOfTopLip,
L17_LMouthCorner,
L17_RMouthCorner
};
const Shape shape17(Shape17OrEmpty(shape));
if (shape17.rows == 0) // could not convert the shape to a Shape17?
return ShapeWidth(shape) / 2; // fallback, note return
double eyemouth = CanonicalEyeMouthDist(shape17);
if (eyemouth == 0) // pupils and mouth not available?
{
const int eye = TabPoint(eyes, NELEMS(eyes), shape17);
const int mouth = TabPoint(mouths, NELEMS(mouths), shape17);
if (eye >= 0 && mouth >= 0) // actual or surrogate points available?
{
eyemouth = PointDist(shape17, eye, mouth) *
CanonicalEyeMouthDist(MEANSHAPE17) /
PointDist(MEANSHAPE17, eye, mouth);
}
}
if (eyemouth == 0)
{
// last resort, estimate eyemouth dist from shape extent
eyemouth = MAX(ShapeWidth(shape17), ShapeHeight(shape17)) *
PointDist(MEANSHAPE17, L17_LPupil, L17_CBotOfBotLip) /
MAX(ShapeWidth(MEANSHAPE17), ShapeHeight(MEANSHAPE17));
}
CV_Assert(eyemouth > 1 && eyemouth < 1e5); // sanity check
return eyemouth;
}
double InterEyeDist( // inter-pupil distance of a face shape
const Shape& shape) // in
{
static const int leyes[] = // surrogates for left pupil
{
L17_LPupil,
L17_LEyeOuter,
L17_LEyeInner,
L17_LEyebrowInner,
L17_LEyebrowOuter
};
static const int reyes[] = // surrogates for right pupil
{
L17_RPupil,
L17_REyeOuter,
L17_REyeInner,
L17_REyebrowInner,
L17_REyebrowOuter
};
const Shape shape17(Shape17OrEmpty(shape));
if (shape17.rows == 0) // could not convert the shape to a Shape17?
return ShapeWidth(shape) / 2; // fallback, note return
double eyedist = 0;
const int leye = TabPoint(leyes, NELEMS(leyes), shape17);
const int reye = TabPoint(reyes, NELEMS(reyes), shape17);
if (leye >= 0 && reye >= 0 && // actual or surrogate points available?
PointDist(shape17, leye, reye) > 1) // surrogates aren't co-located?
{
eyedist = PointDist(shape17, leye, reye) *
PointDist(MEANSHAPE17, L17_LPupil, L17_RPupil) /
PointDist(MEANSHAPE17, leye, reye);
}
else // last resort, estimate inter-pupil distance from shape extent
{
eyedist = MAX(ShapeWidth(shape17), ShapeHeight(shape17)) *
PointDist(MEANSHAPE17, L17_LPupil, L17_RPupil) /
MAX(ShapeWidth(MEANSHAPE17), ShapeHeight(MEANSHAPE17));
}
CV_Assert(eyedist > 1 && eyedist < 1e5); // sanity check
return eyedist;
}
} // namespace stasm