Beispiel #1
0
static Shape StartShapeFromDetPar(
    const DetPar& detpar_roi,      // in: detpar wrt the ROI
    const Image&  face_roi,        // in
    const Shape&  meanshape,       // in
    ESTART        estart)          // in: use mouth etc. to posn start shape?
{
    CV_Assert(estart == ESTART_RECT_ONLY ||
              estart == ESTART_EYES ||
              estart == ESTART_EYE_AND_MOUTH);

    Shape startshape;
    Shape meanshape1(meanshape);

    if (estart == ESTART_EYE_AND_MOUTH &&             // use both eyes and mouth?
        Valid(detpar_roi.mouthx) &&
        Valid(detpar_roi.lex) &&
        Valid(detpar_roi.rex))
    {
        FlipIfLeftFacing(meanshape1, detpar_roi.eyaw, face_roi.cols);
        startshape = AlignMeanShapeToBothEyesAndMouth(detpar_roi, meanshape1);
        FlipIfLeftFacing(startshape, detpar_roi.eyaw, face_roi.cols);
    }
    else if (Valid(detpar_roi.lex) &&                 // use both eyes?
             Valid(detpar_roi.rex))
    {
        FlipIfLeftFacing(meanshape1, detpar_roi.eyaw, face_roi.cols);
        // TODO Tune the following code, what approach is best?
        if (detpar_roi.eyaw == EYAW00)
            startshape = AlignMeanShapeToBothEyesEstMouth(detpar_roi, meanshape1);
        else
            startshape = AlignMeanShapeToBothEyesNoMouth(detpar_roi, meanshape1);
        FlipIfLeftFacing(startshape, detpar_roi.eyaw, face_roi.cols);
    }
    else if (estart == ESTART_EYE_AND_MOUTH &&        // use left eye and mouth?
             Valid(detpar_roi.mouthx) &&
             Valid(detpar_roi.lex))
    {
        FlipIfLeftFacing(meanshape1, detpar_roi.eyaw, face_roi.cols);
        startshape = AlignMeanShapeToLeftEyeAndMouth(detpar_roi, meanshape1);
        FlipIfLeftFacing(startshape, detpar_roi.eyaw, face_roi.cols);
    }
    else if (estart == ESTART_EYE_AND_MOUTH &&        // use right eye and mouth?
             Valid(detpar_roi.mouthx) &&
             Valid(detpar_roi.rex))
    {
        FlipIfLeftFacing(meanshape1, detpar_roi.eyaw, face_roi.cols);
        startshape = AlignMeanShapeToRightEyeAndMouth(detpar_roi, meanshape1);
        FlipIfLeftFacing(startshape, detpar_roi.eyaw, face_roi.cols);
    }
    else // last resort: use the face det rectangle (can't use facial features)
    {
        startshape =
            AlignMeanShapeToFaceDetRect(detpar_roi, meanshape1,
                                        FACERECT_SCALE_WHEN_NO_EYES, face_roi);
    }
    return JitterPointsAt00(startshape);
}
Beispiel #2
0
static Shape PinMeanShape(  // align mean shape to the pinned points
    const Shape& pinned,    // in: at least two of these points must be set
    const Shape& meanshape) // in
{
    CV_Assert(pinned.rows == meanshape.rows);

    int ipoint, nused = 0;  // number of points used in pinned
    for (ipoint = 0; ipoint < meanshape.rows; ipoint++)
        if (PointUsed(pinned, ipoint))
            nused++;

    if (nused < 2)
        Err("Need at least two pinned landmarks");

    // Create an anchor shape (the pinned landmarks) and an alignment shape (the
    // points in meanshape that correspond to those pinned landmarks).  Do that by
    // copying the used points in pinned to pinned_used, and the corresponding
    // points in meanshape to meanused.

    Shape pinned_used(nused, 2), mean_used(nused, 2);
    int i = 0;
    for (ipoint = 0; ipoint < meanshape.rows; ipoint++)
        if (PointUsed(pinned, ipoint))
        {
            pinned_used(i, IX) = pinned(ipoint, IX);
            pinned_used(i, IY) = pinned(ipoint, IY);
            mean_used(i, IX)   = meanshape(ipoint, IX);
            mean_used(i, IY)   = meanshape(ipoint, IY);
            i++;
        }
    CV_Assert(i == nused);

    // transform meanshape to pose generated by aligning mean_used to pinned_used
    Shape TransformedShape(
                    AlignShape(meanshape, AlignmentMat(mean_used, pinned_used)));

    return JitterPointsAt00(TransformedShape);
}
static Shape StartShapeFromDetPar(
    const DetPar& detpar_roi,      // in: detpar wrt the ROI
    const Image&  face_roi,        // in
    const Shape&  meanshape,       // in
    ESTART        estart)          // in: use mouth etc. to posn start shape?
{
    Shape startshape;
    switch (estart)
    {
    case ESTART_RECT_ONLY:
        startshape = EstartRectOnly(detpar_roi, face_roi, meanshape);
        break;
    case ESTART_EYES:
        startshape = EstartEyes(detpar_roi, face_roi, meanshape);
        break;
    case ESTART_EYE_AND_MOUTH:
        startshape = EstartEyeMouth(detpar_roi, face_roi, meanshape);
        break;
    default:
        Err("Invalid estart %d", estart);
    }
    return JitterPointsAt00(startshape);
}
Beispiel #4
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));
}
Beispiel #5
0
static void StartShapeAndRoi(  // we have the facerect, now get the rest
    Shape&         startshape, // out: the start shape we are looking for
    Image&         face_roi,   // out: ROI around face, possibly rotated upright
    DetPar&        detpar_roi, // out: detpar wrt to face_roi
    DetPar&        detpar,     // io:  detpar wrt to img (has face rect on entry)
    const Image&   img,        // in:  the image (grayscale)
    const vec_Mod& mods,       // in:  a vector of models, one for each yaw range
                               //       (use only estart, and meanshape)
    StasmCascadeClassifier cascade)
{
    PossiblySetRotToZero(detpar.rot);         // treat small rots as zero rots

    FaceRoiAndDetPar(face_roi, detpar_roi,    // get ROI around face
                     img, detpar, false);

    DetectEyesAndMouth(detpar_roi,            // use OpenCV eye and mouth detectors
                       face_roi, cascade);

    // Some face detectors return the face rotation, some don't (in
    // the call to NextFace_ just made via NextStartShapeAndRoi).
    // If we don't have the rotation, then estimate it from the eye
    // angle, if the eyes are available.

    if (!Valid(detpar.rot)) // don't have the face rotation?
    {
        detpar_roi.rot = EstRotFromEyeAngle(detpar_roi);
        PossiblySetRotToZero(detpar_roi.rot);
        detpar.rot = detpar_roi.rot;
        if (detpar.rot != 0)
        {
            // face is rotated: rotate ROI and re-get the eyes and mouth

            // TODO: Prevent bogus OpenCV assert fail face_roi.data == img.data.
            face_roi = Image(0,0);

            FaceRoiAndDetPar(face_roi, detpar_roi,
                             img, detpar, false);

            DetectEyesAndMouth(detpar_roi,    // use OpenCV eye and mouth detectors
                               face_roi, cascade);
        }
    }
    if (trace_g)
        lprintf("%-6.6s yaw %3.0f rot %3.0f ",
            EyawAsString(detpar_roi.eyaw), detpar_roi.yaw, detpar_roi.rot);
    else
        logprintf("%-6.6s yaw %3.0f rot %3.0f ",
            EyawAsString(detpar_roi.eyaw), detpar_roi.yaw, detpar_roi.rot);

    // select an ASM model based on the face's yaw
    const Mod* mod = mods[ABS(EyawAsModIndex(detpar_roi.eyaw, mods))];

    const ESTART estart = mod->Estart_();
    CV_Assert(estart == ESTART_EYES || estart == ESTART_EYE_AND_MOUTH);

    startshape = StartShapeFromDetPar(detpar_roi,
                                      face_roi, mod->MeanShape_(), estart);

    if (IsLeftFacing(detpar_roi.eyaw))
        FlipImgInPlace(face_roi);

    JitterPointsAt00(startshape);

}