static Shape AlignMeanShapeToFaceDetRect( 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("AlignToFaceDetBox "); 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 = AlignShape(meanshape, xscale, 0, detpar1.x, 0, yscale, detpar1.y); return startshape; }
static void FlipIfLeftFacing( Shape& shape, // io EYAW eyaw, // in int ncols) // in { if (IsLeftFacing(eyaw)) shape = FlipShape(shape, ncols); }
void PinnedStartShapeAndRoi( // use the pinned landmarks to init the start shape Shape& startshape, // out: the start shape (in ROI frame) Image& face_roi, // out: ROI around face, possibly rotated upright DetPar& detpar_roi, // out: detpar wrt to face_roi DetPar& detpar, // out: detpar wrt to img Shape& pinned_roi, // out: pinned arg translated to ROI frame const Image& img, // in: the image (grayscale) const vec_Mod& mods, // in: a vector of models, one for each yaw range const Shape& pinned) // in: manually pinned landmarks { double rot, yaw; EstRotAndYawFrom5PointShape(rot, yaw, As5PointShape(pinned, mods[0]->MeanShape_())); const EYAW eyaw = DegreesAsEyaw(yaw, NSIZE(mods)); const int imod = EyawAsModIndex(eyaw, mods); // select ASM model based on yaw if (trace_g) lprintf("%-6.6s yaw %3.0f rot %3.0f ", EyawAsString(eyaw), yaw, rot); pinned_roi = pinned; // use pinned_roi as a temp shape we can change Image workimg(img); // possibly flipped image if (IsLeftFacing(eyaw)) // left facing? (our models are for right facing faces) { pinned_roi = FlipShape(pinned_roi, workimg.cols); FlipImgInPlace(workimg); } const Mod* mod = mods[ABS(imod)]; startshape = PinMeanShape(pinned_roi, mod->MeanShape_()); startshape = mod->ConformShapeToMod_Pinned_(startshape, pinned_roi); detpar = PseudoDetParFromStartShape(startshape, rot, yaw, NSIZE(mods)); if (IsLeftFacing(eyaw)) detpar.rot *= -1; FaceRoiAndDetPar(face_roi, detpar_roi, workimg, detpar, false); startshape = ImgShapeToRoiFrame(startshape, detpar_roi, detpar); pinned_roi = ImgShapeToRoiFrame(pinned_roi, detpar_roi, detpar); // following line not strictly necessary because don't actually need eyes/mouth InitDetParEyeMouthFromShape(detpar_roi, startshape); if (IsLeftFacing(eyaw)) { detpar = FlipDetPar(detpar, img.cols); detpar.rot = -detpar.rot; detpar_roi.x += 2. * (face_roi.cols/2. - detpar_roi.x); } }
Shape RoiShapeToImgFrame( // return shape in image frame const Shape& shape, // in: shape in roi frame const Image& face_roi, // in const DetPar& detpar_roi, // in: detpar wrt the ROI const DetPar& detpar) // in: detpar wrt the image { Shape outshape(shape.clone()); if (IsLeftFacing(detpar.eyaw)) outshape = FlipShape(outshape, face_roi.cols); if (Valid(detpar.rot) && detpar.rot) { const MAT rotmat = getRotationMatrix2D(cv::Point2f(float(detpar_roi.x), float(detpar_roi.y)), detpar.rot, 1.); TransformShapeInPlace(outshape, rotmat); } return ShiftShape(outshape, detpar.x - detpar_roi.x, detpar.y - detpar_roi.y); }
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); }