| 31 | // iteration of the ASM, which gives as good landmark fit results, empirically. |
| 32 | |
| 33 | Shape ConformShapeToMod( // Return a copy of inshape conformed to the model |
| 34 | VEC& b, // io: eigvec weights, 2n x 1 |
| 35 | const Shape& inshape, // in: the current position of the landmarks |
| 36 | const Shape& meanshape, // in: n x 2 |
| 37 | const VEC& eigvals, // in: neigs x 1 |
| 38 | const MAT& eigvecs, // in: 2n x neigs |
| 39 | const MAT& eigvecsi, // in: neigs x 2n, inverse of eigvecs |
| 40 | const double bmax, // in: for LimitB |
| 41 | const VEC& pointweights) // in: contribution of each point to the pose |
| 42 | { |
| 43 | Shape shape(inshape.clone()); |
| 44 | |
| 45 | // estimate the pose which transforms the shape into the model space |
| 46 | // (use the b from previous iterations of the ASM) |
| 47 | |
| 48 | MAT modelshape(AsColVec(meanshape) + eigvecs * b); |
| 49 | modelshape = DimKeep(modelshape, shape.rows, 2); // redim back to 2 columns |
| 50 | const MAT pose(AlignmentMat(modelshape, shape, Buf(pointweights))); |
| 51 | |
| 52 | // transform the shape into the model space |
| 53 | |
| 54 | modelshape = TransformShape(shape, pose.inv(cv::DECOMP_LU)); |
| 55 | |
| 56 | // update shape model params b to match modelshape, then limit b |
| 57 | |
| 58 | b = eigvecsi * AsColVec(modelshape - meanshape); |
| 59 | LimitB(b, eigvals, bmax); |
| 60 | |
| 61 | // generate conformedshape from the model using the limited b |
| 62 | // (we generate as a column vec, then redim back to 2 columns) |
| 63 | |
| 64 | const Shape conformedshape(DimKeep(eigvecs * b, shape.rows, 2)); |
| 65 | |
| 66 | // back to image space |
| 67 | |
| 68 | return JitterPointsAt00(TransformShape(meanshape + conformedshape, pose)); |
| 69 | } |
| 70 | |
| 71 | VEC PointWeights(void) // return point weights from LANDMARK_INFO_TAB |
| 72 | { |
no test coverage detected