| 50 | // 4 RMouthCorner |
| 51 | |
| 52 | static void EstRotAndYawFrom5PointShape( |
| 53 | double& rot, // out |
| 54 | double& yaw, // out |
| 55 | const Shape shape5) // in |
| 56 | { |
| 57 | CV_Assert(shape5.rows == 5); |
| 58 | |
| 59 | Shape workshape(shape5.clone()); // local copy we can modify |
| 60 | |
| 61 | // Derotate shape5 using eye angle as estimate of in-plane rotation. |
| 62 | // We rotate about the shape5 centroid. |
| 63 | // TODO EstYawFrom5PointShape was trained on shapes without this |
| 64 | // derotation, so must retrain the model for best results. |
| 65 | |
| 66 | rot = RadsToDegrees(-atan2(workshape(1, IY) - workshape(0, IY), |
| 67 | workshape(1, IX) - workshape(0, IX))); |
| 68 | |
| 69 | PossiblySetRotToZero(rot); // treat small Rots as zero Rots |
| 70 | |
| 71 | if (rot) |
| 72 | RotShapeInPlace(workshape, |
| 73 | -rot, |
| 74 | SumElems(workshape.col(IX)) / 5, |
| 75 | SumElems(workshape.col(IY)) / 5); |
| 76 | |
| 77 | // mean-center x and y |
| 78 | MAT X(workshape.col(IX)); X -= SumElems(X) / 5; |
| 79 | MAT Y(workshape.col(IY)); Y -= SumElems(Y) / 5; |
| 80 | |
| 81 | // normalize so workshape size is 1 |
| 82 | double norm = 0; |
| 83 | for (int i = 0; i < 5; i++) |
| 84 | norm += SQ(X(i)) + SQ(Y(i)); |
| 85 | workshape /= sqrt(norm); |
| 86 | |
| 87 | yaw = EstYawFrom5PointShape(Buf(workshape)); |
| 88 | } |
| 89 | |
| 90 | static Shape PinMeanShape( // align mean shape to the pinned points |
| 91 | const Shape& pinned, // in: at least two of these points must be set |
no test coverage detected