| 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 |
| 92 | const Shape& meanshape) // in |
| 93 | { |
| 94 | CV_Assert(pinned.rows == meanshape.rows); |
| 95 | |
| 96 | int ipoint, nused = 0; // number of points used in pinned |
| 97 | for (ipoint = 0; ipoint < meanshape.rows; ipoint++) |
| 98 | if (PointUsed(pinned, ipoint)) |
| 99 | nused++; |
| 100 | |
| 101 | if (nused < 2) |
| 102 | Err("Need at least two pinned landmarks"); |
| 103 | |
| 104 | // Create an anchor shape (the pinned landmarks) and an alignment shape (the |
| 105 | // points in meanshape that correspond to those pinned landmarks). Do that by |
| 106 | // copying the used points in pinned to pinned_used, and the corresponding |
| 107 | // points in meanshape to meanused. |
| 108 | |
| 109 | Shape pinned_used(nused, 2), mean_used(nused, 2); |
| 110 | int i = 0; |
| 111 | for (ipoint = 0; ipoint < meanshape.rows; ipoint++) |
| 112 | if (PointUsed(pinned, ipoint)) |
| 113 | { |
| 114 | pinned_used(i, IX) = pinned(ipoint, IX); |
| 115 | pinned_used(i, IY) = pinned(ipoint, IY); |
| 116 | mean_used(i, IX) = meanshape(ipoint, IX); |
| 117 | mean_used(i, IY) = meanshape(ipoint, IY); |
| 118 | i++; |
| 119 | } |
| 120 | CV_Assert(i == nused); |
| 121 | |
| 122 | // transform meanshape to pose generated by aligning mean_used to pinned_used |
| 123 | Shape TransformedShape( |
| 124 | TransformShape(meanshape, AlignmentMat(mean_used, pinned_used))); |
| 125 | |
| 126 | return JitterPointsAt00(TransformedShape); |
| 127 | } |
| 128 | |
| 129 | static bool HaveCanonical5Points( |
| 130 | const Shape& pinned17) // in: pinned landmarks |
no test coverage detected