static Shape AlignMeanShapeToFaceDet(
    const DetPar& detpar,                 // in
    const Shape&  meanshape,              // in
    double        scale,                  // in: scale the face rectangle
    const Image&  img)                    // io: the image (grayscale)
{
    if (trace_g)
        lprintf("AlignToFaceDet           ");

    DetPar detpar1(detpar);

    if (IsLeftFacing(detpar.eyaw))
        detpar1 = FlipDetPar(detpar, img.cols);

    CV_Assert(meanshape.rows > 0 && meanshape.cols == 2);

    const double xscale = detpar1.width  * scale / DET_FACE_WIDTH;
    const double yscale = detpar1.height * scale / DET_FACE_WIDTH;

    Shape startshape = TransformShape(meanshape,
                                     xscale,      0, detpar1.x,
                                          0, yscale, detpar1.y);

    return startshape;
}
static Shape AlignMeanShapeToBothEyesNoMouth(
    const DetPar& detpar,                      // in
    const Shape&  meanshape)                   // in
{
    if (trace_g)
        lprintf("AlignToBothEyesNoMouth   ");

    CV_Assert(NSIZE(meanshape) > 0 && PointUsed(meanshape, 0));
    CV_Assert(Valid(detpar.lex));
    CV_Assert(Valid(detpar.rex));

    Shape meanline(2, 2), detline(2, 2);       // line from eye to eye

    const Shape shape17(Shape17(meanshape));

    meanline(0, IX) = shape17(L17_LPupil, IX); // left eye
    meanline(0, IY) = shape17(L17_LPupil, IY);
    meanline(1, IX) = shape17(L17_RPupil, IX); // right eye
    meanline(1, IY) = shape17(L17_RPupil, IY);

    detline(0, IX) = detpar.lex;               // left eye
    detline(0, IY) = detpar.ley;
    detline(1, IX) = detpar.rex;               // right eye
    detline(1, IY) = detpar.rey;

    return TransformShape(meanshape, AlignmentMat(meanline, detline));
}
static Shape AlignMeanShapeToRightEyeMouth(
    const DetPar& detpar,                             // in
    const Shape&  meanshape)                          // in
{
    if (trace_g)
        lprintf("AlignToRightEyeMouth     ");

    CV_Assert(NSIZE(meanshape) > 0 && PointUsed(meanshape, 0));
    CV_Assert(!Valid(detpar.lex));   // left eye invalid? (else why are we here?)
    CV_Assert(Valid(detpar.rex));    // right eye valid?
    CV_Assert(Valid(detpar.mouthx)); // mouth valid?

    const Shape shape17(Shape17(meanshape));

    const double x_meanmouth =
       (shape17(L17_CTopOfTopLip, IX) + shape17(L17_CBotOfBotLip, IX)) / 2;

    const double y_meanmouth =
       (shape17(L17_CTopOfTopLip, IY) + shape17(L17_CBotOfBotLip, IY)) / 2;

    Shape meanline(2, 2), detline(2, 2);              // line from eye to mouth

    meanline(0, IX) = shape17(L17_RPupil, IX);        // right eye
    meanline(0, IY) = shape17(L17_RPupil, IY);
    meanline(1, IX) = x_meanmouth;                    // mouth
    meanline(1, IY) = y_meanmouth;

    detline(0, IX) = detpar.rex;                      // right eye
    detline(0, IY) = detpar.rey;
    detline(1, IX) = detpar.mouthx;                   // mouth
    detline(1, IY) = detpar.mouthy;

    return TransformShape(meanshape, AlignmentMat(meanline, detline));
}
Example #4
0
SHAPE
ConformShapeToModel (Vec &b,                    // io
                     const SHAPE &Shape,        // in
                     const ASM_MODEL &Model,    // in
                     int iLev,                  // in
                     bool fShapeModelFinalIter) // in
{
Vec MeanShape(Model.AsmLevs[iLev].MeanShape);

// For calculations below we need to see shapes (nrows x 2) as vectors (1 x 2*nrows).
// Note that this is a "view" so if you change MeanShapeAsVec you
// are changing MeanShape too, and vice versa.

VecView MeanShapeAsVec(MeanShape.viewAsCol());

// find y, the model shape that best fits Shape

SHAPE OutShape(Shape);
int nEigs = Model.AsmLevs[iLev].nEigs;
double BMax = Model.AsmLevs[iLev].BMax;
if (fShapeModelFinalIter)
    {
    // final iter in main ASM search loop so loosen up the model
    nEigs = Model.AsmLevs[iLev].nEigsFinal;
    BMax = Model.AsmLevs[iLev].BMaxFinal;
    }
ASSERT(BMax > 0);
ASSERT(nEigs > 0);
SHAPE x(Shape.nrows(), 2);
x.viewAsCol() = MeanShapeAsVec + Model.EigVecs * b; // generate a model shape x
Mat Pose(AlignShape(x, Shape));
SHAPE y(TransformShape(Shape, Pose.inverse())); // project Shape into model space

// update model params b to match y
// We limit b to ensure we stay within model limits

b = Model.EigInverse * (y.viewAsCol() - MeanShapeAsVec);
LimitB(b, Model.AsmLevs[iLev].EigVals, nEigs, BMax);

// generate OutShape from the model using our calculated b,
// and align OutShape to Shape

OutShape.viewAsCol() = Model.EigVecs * b;
OutShape = TransformShape(Model.AsmLevs[iLev].MeanShape + OutShape, Pose);
return OutShape;
}
Example #5
0
Mat AlignShape (SHAPE &Shape,               // io
                const SHAPE &AnchorShape,   // in
                const Vec *pWeights)        // in: can be NULL
{
CheckSameNbrRows(Shape, AnchorShape, "AlignShape");
if (pWeights && pWeights->nrows() == 0)
    pWeights = NULL;
if (pWeights)
    ASSERT(Shape.nrows() == pWeights->nelems());
double X1 = 0, Y1 = 0, X2 = 0, Y2 = 0, W = 0, Z = 0, C1 = 0, C2 = 0;
int iRow = Shape.nrows();
while (iRow--)
    {
    const double x1 = AnchorShape(iRow, VX);
    const double y1 = AnchorShape(iRow, VY);
    const double x2 = Shape(iRow, VX);
    const double y2 = Shape(iRow, VY);

    if (x1 == 0 && y1 == 0)         // is anchor landmark unused?
        ;
    else if (x2 == 0 && y2 == 0)    // is landmark unused?
        ;
    else
        {
        const double w = (pWeights? (*pWeights)(iRow): 1.0);
        W  += w;
        Z  += w * (x2 * x2 + y2 * y2);
        X1 += w * x1;
        Y1 += w * y1;
        X2 += w * x2;
        Y2 += w * y2;
        C1 += w * (x1 * x2 + y1 * y2);
        C2 += w * (y1 * x2 - x1 * y2);
        }
    }
double SolnData[] = { X2, -Y2,   W,   0,
                      Y2,  X2,   0,   W,
                       Z,   0,  X2,  Y2,
                       0,   Z, -Y2,  X2 };

MatView Mat4(SolnData, 4, 4, 0);            // 4x4, tda=0

double  VecData[] = { X1, Y1, C1, C2 };
VecView Vec4(VecData, 4);

Vec Soln(SolveWithLU(Mat4, Vec4));

double TransformData[] = { Soln(0), -Soln(1), Soln(2),  // a b tx
                           Soln(1),  Soln(0), Soln(3),  // c d ty
                                0,         0,       1 };

Mat Transform(TransformData, 3, 3);

Shape = TransformShape(Shape, Transform);

return Transform;
}
Example #6
0
void TransformInPlace (SHAPE &Shape,                     // io
                       double x0, double y0, double z0,  // in
                       double x1, double y1, double z1)  // in
{
double Tr[] = { x0, y0, z0,
                x1, y1, z1 };

Mat Transform(Tr, 2, 3);

Shape = TransformShape(Shape, Transform);
}
Example #7
0
SHAPE TransformShape (const SHAPE &Shape,               // in
                      double x0, double y0, double z0,  // in
                      double x1, double y1, double z1)  // in
{
double Tr[] = { x0, y0, z0,
                x1, y1, z1 };

Mat Transform(Tr, 2, 3);

return TransformShape(Shape, Transform);
}
Example #8
0
static void
AlignStartShapeToDet (SHAPE &StartShape,            // out
                      const DET_PARAMS &DetParams,  // in
                      const SHAPE &DetAv,           // in
                      double Scale)
{
ASSERT(DetAv.nrows() > 0 && DetAv.ncols() == 2);

const double xScale = DetParams.width  * Scale / DET_FACE_WIDTH;
const double yScale = DetParams.height * Scale / DET_FACE_WIDTH;

StartShape = TransformShape(DetAv, xScale,       0, DetParams.x,
                                        0,  yScale, DetParams.y);
}
Example #9
0
Shape ConformShapeToMod( // Return a copy of inshape conformed to the model
    VEC&         b,             // io: eigvec weights, 2n x 1
    const Shape& inshape,       // in: the current position of the landmarks
    const Shape& meanshape,     // in: n x 2
    const VEC&   eigvals,       // in: neigs x 1
    const MAT&   eigvecs,       // in: 2n x neigs
    const MAT&   eigvecsi,      // in: neigs x 2n, inverse of eigvecs
    const double bmax,          // in: for LimitB
    const VEC&   pointweights)  // in: contribution of each point to the pose
{
    Shape shape(inshape.clone());

    // estimate the pose which transforms the shape into the model space
    // (use the b from previous iterations of the ASM)

    MAT modelshape(AsColVec(meanshape) + eigvecs * b);
    modelshape = DimKeep(modelshape, shape.rows, 2); // redim back to 2 columns
    const MAT pose(AlignmentMat(modelshape, shape, Buf(pointweights)));

    // transform the shape into the model space

    modelshape = TransformShape(shape, pose.inv(cv::DECOMP_LU));

    // update shape model params b to match modelshape, then limit b

    b = eigvecsi * AsColVec(modelshape - meanshape);
    LimitB(b, eigvals, bmax);

    // generate conformedshape from the model using the limited b
    // (we generate as a column vec, then redim back to 2 columns)

    const Shape conformedshape(DimKeep(eigvecs * b, shape.rows, 2));

    // back to image space

    return JitterPointsAt00(TransformShape(meanshape + conformedshape, pose));
}
static Shape AlignMeanShapeToBothEyesMouth(
    const DetPar& detpar,                   // in
    const Shape&  meanshape)                // in
{
    if (trace_g)
        lprintf("AlignToBothEyesMouth     ");

    CV_Assert(NSIZE(meanshape) > 0 && PointUsed(meanshape, 0));
    CV_Assert(Valid(detpar.mouthx));
    CV_Assert(Valid(detpar.lex));
    CV_Assert(Valid(detpar.rex));

    Shape mean_tri(3, 2), det_tri(3, 2);       // triangle of eyes and mouth

    const double x_meanmouth =
       (meanshape(L_CTopOfTopLip, IX) + meanshape(L_CBotOfBotLip, IX)) / 2.;

    const double y_meanmouth =
       (meanshape(L_CTopOfTopLip, IY) + meanshape(L_CBotOfBotLip, IY)) / 2.;

    const Shape shape17(Shape17(meanshape));

    mean_tri(0, IX) = shape17(L17_LPupil, IX); // left eye
    mean_tri(0, IY) = shape17(L17_LPupil, IY);
    mean_tri(1, IX) = shape17(L17_RPupil, IX); // right eye
    mean_tri(1, IY) = shape17(L17_RPupil, IY);
    mean_tri(2, IX) = x_meanmouth;             // mouth
    mean_tri(2, IY) = y_meanmouth;

    det_tri(0, IX) = detpar.lex;               // left eye
    det_tri(0, IY) = detpar.ley;
    det_tri(1, IX) = detpar.rex;               // right eye
    det_tri(1, IY) = detpar.rey;
    det_tri(2, IX) = detpar.mouthx;            // mouth
    det_tri(2, IY) = detpar.mouthy;

    return TransformShape(meanshape, AlignmentMat(mean_tri, det_tri));
}
static Shape AlignMeanShapeToBothEyesEstMouth(
    const DetPar& detpar,                      // in
    const Shape&  meanshape)                   // in
{
    // .48 was tested to give slightly better worse case results than .50
    static const double EYEMOUTH_TO_FACERECT_RATIO = .48;

    if (trace_g)
        lprintf("AlignToBothEyesEstMouth  ");

    CV_Assert(NSIZE(meanshape) > 0 && PointUsed(meanshape, 0));
    CV_Assert(Valid(detpar.lex));
    CV_Assert(Valid(detpar.rex));

    // estimate the mouth's position

    double x_eyemid = 0;
    switch (detpar.eyaw)
    {
    case EYAW00:                                 //  mid point
        x_eyemid = .50 * detpar.lex + .50 * detpar.rex;
        break;
    // TODO The constants below have not been empirically optimized.
    case EYAW_45:                                // closer to left eye
        x_eyemid = .30 * detpar.lex + .70 * detpar.rex;
        break;
    case EYAW_22:                                // closer to left eye
        x_eyemid = .30 * detpar.lex + .70 * detpar.rex;
        break;
    case EYAW22:                                 // closer to right eye
        x_eyemid = .30 * detpar.lex + .70 * detpar.rex;
        break;
    case EYAW45:                                 // closer to right eye
        x_eyemid = .30 * detpar.lex + .70 * detpar.rex;
        break;
    default:
        Err("AlignMeanShapeToBothEyesEstMouth: Invalid eyaw %d", detpar.eyaw);
        break;
    }
    const double y_eyemid = (detpar.ley + detpar.rey) / 2;

    Shape mean_tri(3, 2), det_tri(3, 2);             // triangle of eyes and mouth

    const Shape shape17(Shape17(meanshape));

    mean_tri(0, IX) = shape17(L17_LPupil, IX);       // left eye
    mean_tri(0, IY) = shape17(L17_LPupil, IY);
    mean_tri(1, IX) = shape17(L17_RPupil, IX);       // right eye
    mean_tri(1, IY) = shape17(L17_RPupil, IY);
    mean_tri(2, IX) = shape17(L17_CBotOfBotLip, IX); // mouth
    mean_tri(2, IY) = shape17(L17_CBotOfBotLip, IY);

    det_tri(0, IX) = detpar.lex;                     // left eye
    det_tri(0, IY) = detpar.ley;
    det_tri(1, IX) = detpar.rex;                     // right eye
    det_tri(1, IY) = detpar.rey;
    det_tri(2, IX) = x_eyemid;                       // mouth
    det_tri(2, IY) = y_eyemid + EYEMOUTH_TO_FACERECT_RATIO * detpar.width;

    return TransformShape(meanshape, AlignmentMat(mean_tri, det_tri));
}