| 33 | } |
| 34 | |
| 35 | void ApplyShapeModelHacks( // adjust shape by applying various hacks |
| 36 | Shape& shape, // io: position of features possibly adjusted |
| 37 | unsigned hackbits) // in: which hacks to apply, see SHAPEHACKS defs |
| 38 | { |
| 39 | if (shape.rows != 77) // the shape hacks assume stasm77 points |
| 40 | return; // NOTE return |
| 41 | |
| 42 | const double eyemouth = EyeMouthDist(shape); |
| 43 | |
| 44 | if (hackbits & SHAPEHACKS_DEFAULT) |
| 45 | { |
| 46 | // Possibly shift the entire mouth down, if it is too close to the nose. |
| 47 | // Useful when the descriptor matchers think the nostrils are the mouth. |
| 48 | |
| 49 | const double nosemouth_gap = |
| 50 | shape(L_CTopOfTopLip, IY) - shape(L_CNoseBase, IY); |
| 51 | if (nosemouth_gap < .1 * eyemouth) |
| 52 | { |
| 53 | PossiblyPrint("ShiftMouthDown"); |
| 54 | for (int i = L_LMouthCorner; i <= L_LMouth76; i++) |
| 55 | shape(i, IY) += SHIFT_MOUTH_FROM_NOSE_FRAC * eyemouth; |
| 56 | } |
| 57 | // Shift the bottom of mouth down if it is above the top of mouth. |
| 58 | |
| 59 | const double gap = shape(L_CTopOfBotLip, IY) - shape(L_CTopOfTopLip, IY); |
| 60 | if (gap < 0) |
| 61 | { |
| 62 | PossiblyPrint("ShiftBottomOfMouthDown"); |
| 63 | for (int i = L_RMouthCorner; i <= L_LMouth76; i++) |
| 64 | shape(i, IY) -= gap; |
| 65 | } |
| 66 | // Possibly shift the chin down or up, if it too close to the mouth. |
| 67 | // Useful when the chin is on the mouth. |
| 68 | |
| 69 | const double y_mouth_center = |
| 70 | (shape(L_CTopOfTopLip, IY) + shape(L_CBotOfBotLip, IY)) / 2; |
| 71 | const double nosemouth_gap1 = |
| 72 | MAX(0, y_mouth_center - shape(L_CNoseBase, IY)); |
| 73 | const double mouthchin_gap = |
| 74 | shape(L_CTipOfChin, IY) - y_mouth_center; |
| 75 | if (mouthchin_gap < CHIN_DOWN_RATIO * nosemouth_gap1) |
| 76 | { |
| 77 | PossiblyPrint("ShiftChinDown"); |
| 78 | double yadjust = CHIN_DOWN_SHIFT * eyemouth; |
| 79 | shape(L_LJaw04, IY) += yadjust; |
| 80 | shape(L_LJaw05, IY) += yadjust; |
| 81 | shape(L_CTipOfChin, IY) += yadjust; |
| 82 | shape(L_RJaw07, IY) += yadjust; |
| 83 | shape(L_RJaw08, IY) += yadjust; |
| 84 | } |
| 85 | if (mouthchin_gap > CHIN_UP_RATIO * nosemouth_gap1) |
| 86 | { |
| 87 | PossiblyPrint("ShiftChinUp"); |
| 88 | double yadjust = CHIN_UP_SHIFT * eyemouth; |
| 89 | shape(L_LJaw04, IY) -= yadjust; |
| 90 | shape(L_LJaw05, IY) -= yadjust; |
| 91 | shape(L_CTipOfChin, IY) -= yadjust; |
| 92 | shape(L_RJaw07, IY) -= yadjust; |
no test coverage detected