shapehacks.cpp
4.8 KB
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
// shapehacks.cpp:
//
// The shape model sometimes allows implausible point layouts. For
// example, the mouth on the nose, or the chin inside the mouth. The
// functions in this module fix the most egregious cases. These hacks
// don't necessarily make the overall fitness measure (FM29) better,
// but minimize the occurrence of ridiculous shapes, although also
// occasionally worsen a good shape.
//
// Copyright (C) 2005-2013, Stephen Milborrow
#include "shapehacks.h"
#include "print.h"
#include "stasm_lib.h"
#include "eyedist.h"
#include "stasm_landmarks.h"
namespace stasm
{
static double SHIFT_MOUTH_FROM_NOSE_FRAC = 0.06; // .06 from tuning on D1 set
static double CHIN_DOWN_RATIO = 0.5; // chin must be this far from mouth
static double CHIN_DOWN_SHIFT = 0.2;
static double CHIN_UP_RATIO = 2.4; // chin cannot be further than this from mouth
static double CHIN_UP_SHIFT = 0.1;
static double TEMPLE_RATIO = .1; // temple must be this far from eye, 0 disables
static double TEMPLE_SHIFT = 3;
//-----------------------------------------------------------------------------
static void PossiblyPrint(const char* s) // debugging print
{
if (trace_g)
lprintf("%s ", s);
}
void ApplyShapeModelHacks( // adjust shape by applying various hacks
Shape& shape, // io: position of features possibly adjusted
unsigned hackbits) // in: which hacks to apply, see SHAPEHACKS defs
{
CV_Assert(shape.rows == stasm_NLANDMARKS); // the hacks assume stasm77 points
CV_Assert(shape.rows == 77);
const double eyemouth = EyeMouthDist(shape);
if (hackbits & SHAPEHACKS_DEFAULT)
{
// Possibly shift the entire mouth down, if it is too close to the nose.
// Useful when the descriptor matchers think the nostrils are the mouth.
const double nosemouth_gap =
shape(L_CTopOfTopLip, IY) - shape(L_CNoseBase, IY);
if (nosemouth_gap < .1 * eyemouth)
{
PossiblyPrint("ShiftMouthDown");
for (int i = L_LMouthCorner; i <= L_LMouth76; i++)
shape(i, IY) += SHIFT_MOUTH_FROM_NOSE_FRAC * eyemouth;
}
// Shift the bottom of mouth down if it is above the top of mouth.
const double gap = shape(L_CTopOfBotLip, IY) - shape(L_CTopOfTopLip, IY);
if (gap < 0)
{
PossiblyPrint("ShiftBottomOfMouthDown");
for (int i = L_RMouthCorner; i <= L_LMouth76; i++)
shape(i, IY) -= gap;
}
// Possibly shift the chin down or up, if it too close to the mouth.
// Useful when the chin is on the mouth.
const double y_mouth_center =
(shape(L_CTopOfTopLip, IY) + shape(L_CBotOfBotLip, IY)) / 2;
const double nosemouth_gap1 =
MAX(0, y_mouth_center - shape(L_CNoseBase, IY));
const double mouthchin_gap =
shape(L_CTipOfChin, IY) - y_mouth_center;
if (mouthchin_gap < CHIN_DOWN_RATIO * nosemouth_gap1)
{
PossiblyPrint("ShiftChinDown");
double yadjust = CHIN_DOWN_SHIFT * eyemouth;
shape(L_LJaw04, IY) += yadjust;
shape(L_LJaw05, IY) += yadjust;
shape(L_CTipOfChin, IY) += yadjust;
shape(L_RJaw07, IY) += yadjust;
shape(L_RJaw08, IY) += yadjust;
}
if (mouthchin_gap > CHIN_UP_RATIO * nosemouth_gap1)
{
PossiblyPrint("ShiftChinUp");
double yadjust = CHIN_UP_SHIFT * eyemouth;
shape(L_LJaw04, IY) -= yadjust;
shape(L_LJaw05, IY) -= yadjust;
shape(L_CTipOfChin, IY) -= yadjust;
shape(L_RJaw07, IY) -= yadjust;
shape(L_RJaw08, IY) -= yadjust;
}
}
// Possibly shift the side of face away from eye.
// Useful when the side of face is on the eye.
if (hackbits & SHAPEHACKS_SHIFT_TEMPLE_OUT)
{
if (shape(L_LTemple, IX) >
shape(L_LEyeOuter, IX) - TEMPLE_RATIO * eyemouth)
{
PossiblyPrint("LTempleOut");
double xadjust =
TEMPLE_SHIFT * ABS(shape(L_LEyeOuter, IX) - shape(L_LTemple, IX));
shape(L_LTemple, IX) -= xadjust;
shape(L_LJaw01, IX) -= xadjust;
shape(L_LJawNoseline, IX) -= xadjust;
shape(L_LJawMouthline, IX) -= .5 * xadjust;
}
if (shape(L_RTemple, IX) <
shape(L_REyeOuter, IX) + TEMPLE_RATIO * eyemouth)
{
PossiblyPrint("RTempleOut");
double xadjust =
TEMPLE_SHIFT * ABS(shape(L_REyeOuter, IX) - shape(L_RTemple, IX));
shape(L_RTemple, IX) += xadjust;
shape(L_RJaw11, IX) += xadjust;
shape(L_RJawNoseline, IX) += xadjust;
shape(L_RJawMouthline, IX) += .5 * xadjust;
}
}
}
} // namespace stasm