📄 ms.cpp
字号:
// this is final iteration of while loop#if 0 // weigh fenceposts less than landmarks TODO gives worse results for (int i = 0; i < Weights.nelems(); i++) if (i >= Weights.nelems() - CONF_nFencePosts) Weights(i) = 0.5; else Weights(i) = 1;#endif Shape = ConformShapeToModel(b, ProfShape, Model, iLev, &Weights, fShapeModelFinalIter);#if CONF_fSelfEvaluate gDiff = (Shape - ProfShape).len(); gDiffAll += gDiff;#endif } iter++;#if CONF_fUseBestSoFar if (nWithinFifyPercent >= nBest) { BestShape = Shape; nBest = nWithinFifyPercent; }#endif }#if CONF_fUseBestSoFarShape = BestShape;#endif#if CONF_fSelfEvaluategLastFit /= iter;ngLastQualifyingDisplacements /= iter;gDiffAll /= iter;giIter = iter;#endifif (gImageBits & IM_AllImages) // show final shape { double ScaleOut = GetScaleOut(gImageBits, iLev); ShowSearchShape(Shape, iter, SearchImgs.ProgressImg, true, ScaleOut, nMaxSearchIters, Lands, AlignedMeanShape); }while (!fgBrief && iter++ < nMaxSearchIters) // print spaces to keep output prints in line bprintf(fgBrief, " ");}//-----------------------------------------------------------------------------// If we conform the reference shape RefShape to the model Model does it change? // This bit of code measures and logs the change.// The RefShape is the shape determined by manual landmarking.#if CONF_fMeasureRefAgainstModeltemplate<typename ModelT>static void MeasureRefAgainstModel (const SHAPE &RefShape, const ModelT &Model, const char sImageBase[], const Image &Img){#if 0Image Img1(Img);double xExtent = xShapeExtent(RefShape);double ScaleOut = 300 / xExtent; // display a fixed face width of approx 300 pixelsScaleImage(Img1, ScaleOut * Img1.width, ScaleOut * Img1.height, QUIET, IM_NEAREST_PIXEL);RgbImage RgbImg(Img1);if (gImageBits & IM_AllImages) { DrawShape(RgbImg, Model.FileMeanShape, C_GREEN, ScaleOut, IM_NO_CONNECT_DOTS, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_TRANSPARENT); DrawShape(RgbImg, RefShape, C_YELLOW, ScaleOut, CONF_fConnectDots, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_TRANSPARENT); }#endifVec b(Model.EigVecs.nrows()); // dummy variableint iLev = 0;SHAPE NewShape(ConformShapeToModel(b, RefShape, Model, iLev, NULL, false));#if 0if (gImageBits & IM_AllImages) { DrawShape(RgbImg, NewShape, C_RED, ScaleOut, IM_CONNECT_DOTS, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_TRANSPARENT); CropImageToFace(RgbImg, ScaleOut * NewShape); RgbPrintf(RgbImg, 8, 3, C_WHITE, 80, "%s Yel Ref, Green Base, Red Aligned", sgModel); char sPath[SLEN]; sprintf(sPath, "%s/RefAgainstModel_%s.bmp", CONF_sOutDir, sgImageOut); WriteBmp(RgbImg, sPath); }#endifAppendDistancesToDatFile(-1, NewShape, RefShape, GetNormDist(NewShape, RefShape), sImageBase, sgModel, "dAlignedRef", -1);}#endif CONF_fMeasureRefAgainstModel//-----------------------------------------------------------------------------// This calculates the total and max difference between the specified points in// Shape and RefShape and prints the results.//// We normalize by dividing the result by the inter-eye distance//// iStart and iEnd are M4 labels, so we translate to the shape landmarks in this functionstatic void PrintTotalFit (const SHAPE &Shape, const SHAPE &RefShape, // in int iLev, double PyrRatio, // in const char sLabel[], const char sPrefix[], // in int iStart, int iEnd, int nUnused, // in bool fPrintToScreen, bool fPrintNbrUnused) // in{double MaxFit = -1, Fit = 0; int nPoints = 0, iWorstPoint = -1;for (int iPoint = iStart; iPoint <= iEnd; iPoint++) { int iPoint1 = iTranslatedPoint(iPoint); if (iPoint1 > Shape.nrows()-1) nUnused++; else if (!fPointUsed(RefShape, iPoint1)) nUnused++; else { nPoints++; double ThisFit = PointDist(Shape, RefShape, iPoint1); if (ThisFit > MaxFit) { MaxFit = ThisFit; iWorstPoint = iPoint1; } Fit += ThisFit; } }double InterEyeDist = GetNormDist(Shape, RefShape);double NormalizedFit = 0;if (nPoints) { Fit /= nPoints; NormalizedFit = Fit / InterEyeDist; }else { Fit = -1; // all points unused, set to -1 to let user know NormalizedFit = -1; }bprintf(!fPrintToScreen, "%s%sFit %-5.3f (%.1f) ", sPrefix, sLabel, NormalizedFit, Fit * GetPyrScale(iLev, PyrRatio));if (fPrintNbrUnused) { // bprintf(!fPrintToScreen, "%s%sMax %-4.3f at %-2d ", sPrefix, sLabel, MaxFit/InterEyeDist, iWorstPoint); if (nUnused) bprintf(!fPrintToScreen, "for %-2d of %-2d points", nPoints, nPoints+nUnused); bprintf(!fPrintToScreen, " "); }if (MaxFit/InterEyeDist > 100) SysErr("PrintTotalFit");}//-----------------------------------------------------------------------------static void ShowImageBeforeSearch (const SHAPE &Shape, const SHAPE *pRefShape, int iLev, const Image &ScaledImg, const Image &FullImg, const Image &DoubleImg, const tLand Lands[]){if (gImageBits & IM_AllImages) { RgbImage RgbImg(GetDisplayImage(gImageBits, ScaledImg, FullImg, DoubleImg)); // convert image to color double ScaleOut = GetScaleOut(gImageBits, iLev); int iFontSize = iGetFontSize(gImageBits); SHAPE AlignedMeanShape(Shape); bool fWhiskers = (gImageBits & IM_Whiskers) != 0; if (fWhiskers) AlignShape(AlignedMeanShape, Shape); SHAPE Shape1(Shape); DrawShape(RgbImg, Shape1, C_DRED, ScaleOut, CONF_fConnectDots, IM_NO_ANNOTATE, fWhiskers, PROF_1d, IM_TRANSPARENT, Lands, &AlignedMeanShape); if (pRefShape) DrawShape(RgbImg, *pRefShape, C_YELLOW, ScaleOut, CONF_fConnectDots, IM_NO_ANNOTATE, IM_NO_WHISKERS, PROF_1d, IM_TRANSPARENT); CropRgbImageSoWidthIsDivisbleBy4(RgbImg); // this is unfortunately needed for RgbPrintf if (pRefShape) RgbPrintf(RgbImg, 8, 3, C_YELLOW, iFontSize, "%s lev %d start shape (red) ref (yellow)", sgModel, iLev); else RgbPrintf(RgbImg, 8, 3, C_YELLOW, iFontSize, "%s lev %d start shape (red)", sgModel, iLev); char sPath[SLEN]; sprintf(sPath, "%s/Start%d_%s.bmp", CONF_sOutDir, iLev, sgImageOut); WriteBmp(RgbImg, sPath); }}//-----------------------------------------------------------------------------static void ShowImagesAfterSearch (Image &Img, // io tSearchImages &SearchImgs, // in const SHAPE &MeanShape, // in const SHAPE &Shape, const SHAPE *pRefShape, // in int iLev, double PyrRatio, // in const tLand Lands[], const char sImageBase[]) // in{SHAPE ScaledRefShape;if ((gImageBits & (IM_FinalImageOnly|IM_AllImages)) && pRefShape) ScaledRefShape = *pRefShape / GetPyrScale(iLev, PyrRatio);Image DoubleImg; // image that is twice the size of original image, for IM_DoubleScaleif (gImageBits & IM_DoubleScale) { DoubleImg = Img; ScaleImage(DoubleImg, 2 * Img.width, 2 * Img.height, QUIET, IM_NEAREST_PIXEL); }if (gImageBits & IM_AllImages) { double ScaleOut = GetScaleOut(gImageBits, iLev); int iFontSize = iGetFontSize(gImageBits); SHAPE AlignedMeanShape(MeanShape); if (fgExplicitPrevNext) AlignShape(AlignedMeanShape, Shape); char sPath[SLEN]; CropRgbImageSoWidthIsDivisbleBy4(SearchImgs.ProgressImg); // this is unfortunately needed for RgbPrintf DrawShape(SearchImgs.ProgressImg, Shape, C_DRED, ScaleOut, CONF_fConnectDots, (gImageBits & IM_Annotate) != 0, (gImageBits & IM_Whiskers) != 0, PROF_1d, IM_TRANSPARENT, Lands, &AlignedMeanShape); if (pRefShape) DrawShape(SearchImgs.ProgressImg, ScaledRefShape, C_YELLOW, ScaleOut); if (gImageBits & (IM_FullScale|IM_DoubleScale)) // enough space for more detailed label? RgbPrintf(SearchImgs.ProgressImg, 8, 3, C_YELLOW, iFontSize, "%s lev %d search (1st=blue 2nd=green inter=cyan end=red)%s", sgModel, iLev, (pRefShape? " ref=yellow": "")); else RgbPrintf(SearchImgs.ProgressImg, 3, 3, C_YELLOW, iFontSize, "%s lev %d search%s", sgModel, iLev, (pRefShape? " ref=yellow": "")); sprintf(sPath, "%s/%dSearch_%s.bmp", CONF_sOutDir, iLev, sgImageOut); WriteBmp(SearchImgs.ProgressImg, sPath); }if ((gImageBits & (IM_FinalImageOnly|IM_AllImages)) && iLev == 0) { double ScaleOut = GetScaleOut(gImageBits, iLev); int iFontSize = iGetFontSize(gImageBits); RgbImage FinalImg(SearchImgs.ProgressImg.width, SearchImgs.ProgressImg.height); SHAPE AlignedMeanShape(MeanShape); if (fgExplicitPrevNext) AlignShape(AlignedMeanShape, Shape); char sPath[SLEN]; if (gImageBits & IM_AllImages) { // show reference shape on original image if (pRefShape) { // reference shape alone on image ConvertGrayImageToRgb(FinalImg, GetDisplayImage(gImageBits, SearchImgs.Img, Img, DoubleImg)); CropRgbImageSoWidthIsDivisbleBy4(FinalImg); DrawShape(FinalImg, ScaledRefShape, C_YELLOW, ScaleOut, CONF_fConnectDots, (gImageBits & IM_AnnotateRef) != 0, (gImageBits & IM_WhiskersRef) != 0, 0, IM_TRANSPARENT, Lands, &AlignedMeanShape, IM_NO_DRAW_CIRCLES); RgbPrintf(FinalImg, 8, 3, C_YELLOW, iFontSize, "%s lev %d ref shape", sgModel, iLev); sprintf(sPath, "%s/Ref_%s.bmp", CONF_sOutDir, sgImageOut); WriteBmp(FinalImg, sPath); } } if ((gImageBits & IM_AllImages) || ngModels == 1) { // show final image and result shape (final image is always displayed at same size as original image) RgbImage FinalImg1(SearchImgs.Img); // if we prescaled the image in PrescaleImageBaseRefShapes(), scale it back to original size ScaleRgbImage(FinalImg1, FinalImg1.width / gImagePreScale, FinalImg1.height / gImagePreScale, QUIET, IM_BILINEAR); AlignedMeanShape /= gImagePreScale; double Scale = gImagePreScale * ((gImageBits & IM_DoubleScale)? 2:1); CropRgbImageSoWidthIsDivisbleBy4(FinalImg1); // this is unfortunately needed for RgbPrintf DrawShape(FinalImg1, Shape / Scale, C_DRED, ScaleOut, CONF_fConnectDots, (gImageBits & IM_Annotate) != 0, (gImageBits & IM_Whiskers) != 0, 0, IM_TRANSPARENT, Lands, &AlignedMeanShape); if (pRefShape && (gImageBits & IM_RefShape)) { DrawShape(FinalImg1, ScaledRefShape / gImagePreScale, C_YELLOW, ScaleOut, IM_NO_CONNECT_DOTS, (gImageBits & IM_AnnotateRef) != 0, (gImageBits & IM_WhiskersRef) != 0, 0, IM_TRANSPARENT, Lands, &AlignedMeanShape); } CropImageToFace(FinalImg1, 1.1 * Shape / gImagePreScale); if (pRefShape && (gImageBits & IM_RefShape)) RgbPrintf(FinalImg1, 8, 3, C_YELLOW, iFontSize, "%s end (red) and ref (yellow)", sgModel, iLev); else RgbPrintf(FinalImg1, 8, 3, C_YELLOW, iFontSize, "%s end", sgModel, iLev); sprintf(sPath, "%s/0End_%s.bmp", CONF_sOutDir, sgImageOut); WriteBmp(FinalImg1, sPath); } }}//-----------------------------------------------------------------------------// iPoint is an M4 label, so we translate to the shape landmark in this functionstatic void PrintPointFit (int iPoint, const SHAPE &Shape, const SHAPE &RefShape, bool fPrintToScreen){if (CONF_iSearchPrintPoint >= 0 && iTranslatedPoint(CONF_iSearchPrintPoint) < Shape.nrows()) { int iPoint1 = iTranslatedPoint(iPoint); double x = Shape(iPoint1, VX) - RefShape(iPoint1, VX); double y = Shape(iPoint1, VY) - RefShape(iPoint1, VY); bprintf(!fPrintToScreen, "PointFit%d %6.4f %5.1f x %5.1f y %5.1f ", iPoint, sqrt(x * x + y * y) / GetNormDist(Shape, RefShape), sqrt(x * x + y * y), x, y); }}//-----------------------------------------------------------------------------static void PrintFits (const SHAPE &Shape, const SHAPE &RefShape, int iLev, double PyrRatio, bool fPrintToScreen){int nEndRow = CONF_nPointsXm2vts;if (CONF_nMaxPointsFitTest > 0 && nEndRow > CONF_nMaxPointsFitTest) nEndRow = CONF_nMaxPointsFitTest;PrintTotalFit(Shape, RefShape, iLev, PyrRatio, "", "", 0, nEndRow-1, Shape.nrows()-nEndRow, fPrintToScreen, true);PrintTotalFit(Shape, RefShape, iLev, PyrRatio, "LEye", "", MLEyeOuter, MLEye, 0, false, false);PrintTotalFit(Shape, RefShape, iLev, PyrRatio, "REye", "", MREyeOuter, MREye, 0, false, false);PrintTotalFit(Shape, RefShape, iLev, PyrRatio, "Mouth", "", MLMouthCorner, MMouthBotOfTopLip, 0, false, false);PrintTotalFit(Shape, RefShape, iLev, PyrRatio, "EBrows", "", MROuterEyeBrow, MLInnerEyeBrow, 0, false, false);PrintPointFit(CONF_iSearchPrintPoint, Shape, RefShape, fPrintToScreen);}//-----------------------------------------------------------------------------// Do a model search at the given level iLev for the given image Img.// Results returned in Shape.//// This is a wrapper for ShapeSearch. It prepares the params for ShapeSearch and// takes care of the messy code to write images and text which show search progress.//// Outline:// Scale image and shapes to this level, prepare SearchImgs// Possibly write some progress images and text// Call ShapeSearch// Possibly write some progress images and texttemplate<typename ModelT>static void ShapeSearchWrapper (SHAPE &Shape, // out Image &Img, // io int iLev, const ModelT &Model, // in const SHAPE *pRefShape, const tLand Lands[], const char sImageBase[], // in int nStartLev) // in{double LevScale = GetPyrScale(iLev, Model.PyrRatio); // scale in image pyramidSHAPE StartShape(Shape);SHAPE ScaledRefShape;tSearchImages SearchImgs; // the images used during searchif (pRefShape) { ScaledRefShape = *pRefShape / LevScale; int nEndRow = Shape.nrows()-1; if (CONF_nMaxPointsFitTest > 0 && nEndRow > CONF_nMaxPointsFitTest) nEndRow = CONF_nMaxPointsFitTest-1; PrintTotalFit(StartShape, ScaledRefShape, iLev, Model.PyrRatio, "Start", "", 0, nEndRow, Shape.nrows()-nEndRow+1, false, false); }SearchImgs.Img = Img;ReduceImage(SearchImgs.Img, LevScale, Model.PyrReduceMethod); // scale search image to this levelint nScaledWidth = Img.width/LevScale, nScaledHeight = Img.height/LevScale;double ScaleOut = GetScaleOut(gImageBits, iLev);int widthOut = ScaleOut * nScaledWidth, heightOut = ScaleOut * nScaledHeight;char sPath[SLEN]; sPath[0] = 0;if (gImageBits & IM_AllImages) sprintf(sPath, "%s/Grad%d_%s", CONF_sOutDir, iLev, sgImageOut);InitGradsIfNeededForModelSearch(SearchImgs.Grads, Model.AsmLevs[iLev].ProfSpecs, SearchImgs.Img, Shape.nrows(), sPath);Image DoubleImg;if ((gImageBits & IM_AllImages) || (gImageBits && iLev == 0)) { if (gImageBits & IM_DoubleScale) { DoubleImg = Img; ScaleImage(DoubleImg, 2 * Img.width, 2 * Img.height, QUIET, IM_NEAREST_PIXEL); } ConvertGrayImageToRgb(SearchImgs.ProgressImg, GetDisplayImage(gImageBits, SearchImgs.Img, Img, DoubleImg)); }ShowImageBeforeSearch(Shape, (pRefShape? &ScaledRefShape: NULL), iLev, SearchImgs.Img, Img, DoubleImg, Lands);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -