📄 ms.cpp
字号:
if (pRefShape && CONF_fPrintAllInDatFile) AppendDistancesToDatFile(iLev, Shape, ScaledRefShape, GetNormDist(Shape, ScaledRefShape), sImageBase, sgModel, "dStart", -1);if (fGenFeats()) // -G flag? GenFeats(Shape, SearchImgs, Model, iLev, Lands, sImageBase, nStartLev);else ShapeSearch(Shape, SearchImgs, Model, iLev, Lands, (pRefShape? &ScaledRefShape: NULL), sImageBase, nStartLev);if (pRefShape) { if (ngModels == 0 || !fgBrief || (CONF_fPrintAllModelFits && Model.iModel < ngModels-1)) PrintFits(Shape, ScaledRefShape, iLev, Model.PyrRatio, !fgBrief || (fgBrief && iLev == 0)); if (fDatFile() && CONF_fPrintAllInDatFile) AppendDistancesToDatFile(iLev, Shape, ScaledRefShape, GetNormDist(Shape, ScaledRefShape), sImageBase, sgModel, "aLev", -1); }ShowImagesAfterSearch(Img, SearchImgs, Model.AsmLevs[iLev].MeanShape, Shape, pRefShape, iLev, Model.PyrRatio, Lands, sImageBase);bprintf(fgBrief, "\n");}//-----------------------------------------------------------------------------static void ShapeSearchWrapper1 ( SHAPE &Shape, // io: on entry approximate start shape, on exit contains search results Image &Img, // io const tAsmModel &Asm, // in const SHAPE *pRefShape, const tLand *pLands, const char sImageBase[], const int nStartLev){// search for the facial features at each level in the image pyramidShape /= GetPyrScale(nStartLev, Asm.PyrRatio);#if CONF_fStartShapeOffsetOffsetStartShape(Shape, Img);#endiffor (int iLev = nStartLev; iLev >= 0; iLev--) // for each level in the image pyramid { if (!fgBrief || CONF_fPrintAllModelFits) bprintf((Asm.iModel != 0) || (iLev != 0 && fgBrief), "%s ", sgModel); bprintf(fgBrief, "Lev %d Scale %.3f ", iLev, 1/GetPyrScale(iLev, Asm.PyrRatio)); ShapeSearchWrapper(Shape, Img, iLev, Asm, pRefShape, pLands, sImageBase, nStartLev); if (iLev != 0) // use best shape from this iter as starting point for next Shape *= Asm.PyrRatio; }#if CONF_fShowFitVersusFaceSizeif (pRefShape) ShowFitVersusFaceSize(Shape, *pRefShape, sImageBase);#endif}//-----------------------------------------------------------------------------static void PrintRelativeLen (SHAPE &Shape, SHAPE &RefShape, int iPoint1, int iPoint2, const char sMsg[]){double Diff = 0;if (iTranslatedPoint(iPoint1) < RefShape.nrows() && iTranslatedPoint(iPoint2) < RefShape.nrows()) { double Len = PointDist(Shape, iPoint1, iPoint2); double RefLen = PointDist(RefShape, iPoint1, iPoint2); Diff = 100 * (Len - RefLen) / RefLen; }bprintf(fgBrief, "%s %3.0f%% ", sMsg, Diff);}//-----------------------------------------------------------------------------static void PrintStartShapeStats (SHAPE &StartShape, SHAPE &RefShape){bprintf(fgBrief, "%s Start", sgModel);PrintRelativeLen(StartShape, RefShape, MLEye, MREye, "EyeToEye");PrintRelativeLen(StartShape, RefShape, MLTemple, MRTemple, "EarToEar");PrintRelativeLen(StartShape, RefShape, MLEye, MTipOfChin, "LEyeToChin");PrintFits(StartShape, RefShape, 0 /* iLev */, 1 /* PyrRatio, can be anything because iLev==0 */, !fgBrief);bprintf(fgBrief, "\n");}//-----------------------------------------------------------------------------// This logs the average eye distance for each file type// The file type is determined by the first char of sImageBase//// TODO I think this is no longer correct because we prescale the imagesstatic void LogInterEyeDist (const char sImageBase[]="", const SHAPE *pRefShape=NULL){static double InterEyeDist = 0; //TODO this won't work across multiple modelsstatic int nShapes = 0;static char cLast = 0;if (nShapes && (sImageBase[0] != cLast)) { logprintf("MeanInterEyeDist for filetype '%c' using ref shapes is %g pixels\n", cLast, InterEyeDist/nShapes); InterEyeDist = 0; nShapes = 0; }if (pRefShape) { InterEyeDist += GetNormDist(*pRefShape, *pRefShape); nShapes++; cLast = sImageBase[0]; }}//-----------------------------------------------------------------------------static void PostSearch (SHAPE &CombinedShape, // io const tAsmModel &Model, // in int iModel, int nModels, SHAPE &Shape, // in const char sImageBase[], const int nInFiles, const clock_t StartTime, SHAPE *pRefShape, const Image &Img, const char sModel[], const char sImageOut[]){CombineModelSearchResults(CombinedShape, iModel, Shape);#if CONF_fPrintShapeSizelprintf("\nim%d %g %c %.0f ", iModel, gImagePreScale, sImageOut[0], xShapeExtent(CombinedShape));int nEndRow = CombinedShape.nrows();PrintTotalFit(CombinedShape, *pRefShape, 0 /* iLev */, 1 /* PyrRatio, can be anything because iLev==0 */, "", "", 0, nEndRow-1, 0, true, false);lprintf("\n");#endifif (iModel == nModels-1) // last model? { //TODO if (nModels > 1) { // show final image and fits if (gImageBits & (IM_AllImages|IM_FinalImageOnly)) { RgbImage FinalImg(Img); SHAPE Shape1(CombinedShape); DrawShape(FinalImg, Shape1, C_DRED, 1.0, CONF_fConnectDots, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_TRANSPARENT); CropImageToFace(FinalImg, 1.1 * CombinedShape); RgbPrintf(FinalImg, 8, 3, C_YELLOW, 80, "%s final %s", sModel, sImageBase); char sPath[SLEN]; sprintf(sPath, "%s/0Final_%s.bmp", CONF_sOutDir, sImageOut); WriteBmp(FinalImg, sPath); } if (pRefShape) {#if 0 if (nModels > 1 && fgBrief) lprintf("\n");#endif if (sModel[0]) lprintf("%s ", sModel); //if (CONF_fPrintAllModelFits && fgBrief) // lprintf(" "); // keep output aligned with "-mod%d" used in previous prints if (!fgBrief) lprintf("Final------------------------------- "); PrintFits(CombinedShape, *pRefShape, 0 /* iLev */, 1 /* PyrRatio, can be anything because iLev==0 */, true); }#if CONF_fSelfEvaluate double Est = -0.06 + 0.0035 * gDiffAll; lprintf("\nEval "); int nEndRow = CombinedShape.nrows(); gDiff = gDiffAll / xShapeExtent(CombinedShape); gDiffAll /= xShapeExtent(CombinedShape) * yShapeExtent(CombinedShape); lprintf("%9.6f %.3f ", gDiffAll, gDiff); PrintTotalFit(CombinedShape, *pRefShape, 0 /* iLev */, 1 /* PyrRatio, can be anything because iLev==0 */, "", "", 0, nEndRow-1, 0, true, false); lprintf("\n");#endif } double TimeTaken = (double)(clock() - gTime) / CLOCKS_PER_SEC; lprintf("%s [done in %.2f secs, %.2f secs per image]", sImageBase, TimeTaken, (double)(clock() - StartTime) / (nInFiles * CLOCKS_PER_SEC)); if (fDatFile()) // generate aLev0 line { char s[SLEN]; sprintf(s, "%s", sModel); AppendDistancesToDatFile(0, CombinedShape, *pRefShape, GetNormDist(CombinedShape, *pRefShape), sImageBase, s, "aLev", TimeTaken); } // Save final combined shape to log file // If we prescaled the image in PrescaleImageBaseRefShapes, then descale the shape first (CombinedShape / gImagePreScale).print("\nBest shape, in image coordinates:\n", "%g ", CONF_MsLogFilename, pgLogFile); // tell the user where the result images are if (gImageBits && !fgBrief) { lprintf("\nResults in "); if (gImageBits & IM_FinalImageOnly) lprintf( "%s/0End_%s.bmp", CONF_sOutDir, sImageOut); else lprintf("%s/*%s*.bmp", CONF_sOutDir, sImageOut); } lprintf("\n"); }}//-----------------------------------------------------------------------------static void GenFileNames (char *sImageOut, char *sImagePath, char *sImageBase, // out const char sInFile[], char sSuffix[]) // in{strcpy(sImagePath, sInFile);char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sExt[_MAX_EXT];_splitpath(sImagePath, sDrive, sDir, sImageBase, sExt); // create ImageBasechar sBase[PLEN];sprintf(sBase, "%s%s", sImageBase, sSuffix);_makepath(sImageOut, "", "", sBase, ""); // create sImageOut}//-----------------------------------------------------------------------------// Get RefShape from the reference shape file sRefShapeFile and convert it to have nWantedPoints if necessary// sImageBase tells us what RefShape to search forstatic void GetRefShape (SHAPE &RefShape, // out char sRefShapeFile[], char sImageBase[], int nModelPoints) // in: will convert ref shape to nPoints{bprintf(fgBrief, "RefShapeFile %s ", sRefShapeFile);char sTagRegExp[PLEN];sprintf(sTagRegExp, "^[048]... %s\\.", sImageBase); // magic [048] specifies normal, testSet1 or testSet2 fileif (!fGetNamedShape(RefShape, sTagRegExp, sRefShapeFile, MAT_REGEX_STRING, fgBrief)) Err("Can't get reference shape");int nrows = RefShape.nrows();// warn if make an easy mistake (use model m3.asm but reference m4.asm)if (fConvertShapeToInternalFormat(RefShape, nModelPoints)) bprintf(fgBrief, ", translated %d landmarks in RefShape to %d", nrows, nModelPoints);bprintf(fgBrief, "\n");static fWarned = false;if (!fWarned && nrows != nModelPoints) { fWarned = true; Warn("Model shape has %d landmarks but reference shape has %d landmarks", nModelPoints, nrows); if (fgBrief) lprintf("\n"); }}//-----------------------------------------------------------------------------// Is face width in pixels too small or too big for our model?// If so, then rescale Img, StartShape, and RefShape.// Also set the global variable gImagePreScale so we can descale later.//// The aim is to make the face width comparable to the range of face widths// in the training set.//// We assume StartShape is roughly aligned to the face (by GetStartShapeFromGlobalDet)// so we can use it to see how wide the face is.static void PrescaleImageBaseRefShapes (Image &Img1, SHAPE &StartShape1, SHAPE &RefShape1, // out const Image &Img, const SHAPE &StartShape, SHAPE *pRefShape, // in double OrgFaceWidth, // in const SHAPE &FileMeanShape, int nScaledFaceWidth, bool fBilinearRescale) // in{gImagePreScale = 1.0; // assume no scalingImg1 = Img;StartShape1 = StartShape;if (pRefShape) RefShape1 = *pRefShape;if (nScaledFaceWidth > 0) gImagePreScale = (double)nScaledFaceWidth / OrgFaceWidth;// following is old code, used before I scaled face widths to a uniform size// defines for prescaling the image before search, only used if CONF_nGenPrescaleFaceWidth==0else { #define CONF_OptimumFaceWidth 280 // search: #define CONF_MinFaceSize 120 // search: faces smaller than this are scaled up #define CONF_MaxFaceSize 350 // search: faces bigger than this are scaled down // If face image is too big or too small, scale it // We scale by integral amounts, so no pixel interpolation has to take place. if (OrgFaceWidth < CONF_MinFaceSize) // to small? { gImagePreScale = 2; // testing shows that simply multiplying by 2 works best // gImagePreScale = int(0.5 + CONF_OptimumFaceWidth / OrgFaceWidth); } // After possibly scaling by an integral power, we use this strategy for faces that are still too big. // CONF_MaxFaceSize is how big a face has to be before we rescale it. // But if face is too big then we rescale it to FaceWidthOptimum. // We try to avoid changing the face (because pixel interpolation caused by rescaling // causes a loss of search accuracy) but if we have to, we change it to the optimum size. if (OrgFaceWidth >= CONF_MaxFaceSize) // face still too big after above scaling? gImagePreScale *= (double)CONF_OptimumFaceWidth / (gImagePreScale * OrgFaceWidth); }// end of old codeif (gImagePreScale != 1) { int nNewWidth = Img1.width * gImagePreScale; int nNewHeight = Img1.height * gImagePreScale; ScaleImage(Img1, nNewWidth, nNewHeight, QUIET, fBilinearRescale); if (pRefShape) RefShape1 *= gImagePreScale; StartShape1 *= gImagePreScale; bprintf(fgBrief, "Face scaled by %g, new estimated face size is %.0f, new image width is %d\n", gImagePreScale, StartShape1(MRJaw2, VX) - StartShape1(MLJaw2, VX), Img1.width); }}//-----------------------------------------------------------------------------static void EqualizeImageForSearch (Image &Img, // out const SHAPE &Shape, const char sImageBase[]) // in{int nxMin, nxMax, nyMin, nyMax;GetEqualizationMask(nxMin, nxMax, nyMin, nyMax, Shape, Img, CONF_EqualizationMaskMargin); //TODO should read CONF_EqualizationMaskMargin from asm fileEqualizeAndCorrectImage(Img, nxMin, nxMax, nyMin, nyMax, QUIET);if (gImageBits & IM_AllImages) { RgbImage RgbImg(Img); // convert gray image to color SHAPE MaskShape(5,2); MaskShape(0,VX) = nxMin; MaskShape(0,VY) = nyMin; MaskShape(1,VX) = nxMin; MaskShape(1,VY) = nyMax; MaskShape(2,VX) = nxMax; MaskShape(2,VY) = nyMax; MaskShape(3,VX) = nxMax; MaskShape(3,VY) = nyMin; MaskShape(4,VX) = nxMin; MaskShape(4,VY) = nyMin; DrawShape(RgbImg, MaskShape, C_RED, 1.0, IM_CONNECT_DOTS, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_NO_TRANSPARENT); DrawShape(RgbImg, Shape, C_YELLOW, 1.0, IM_CONNECT_DOTS, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_NO_TRANSPARENT); char sPath[SLEN]; sprintf(sPath, "%s/Eq_%s.bmp", CONF_sOutDir, sImageBase); WriteBmp(RgbImg, sPath); }}//-----------------------------------------------------------------------------#if CONF_fShowFitVersusFaceSizestatic void ShowFitVersusFaceSize (SHAPE &Shape, SHAPE &RefShape, const char sImageBase[]){lprintf("%s FaceSize %.2f EyeDist %.2f PreScale %g ", sImageBase, Shape(MRJaw2, VX) - Shape(MLJaw2, VX), Shape(MREye, VX) - Shape(MLEye, VX), gImagePreScale);PrintTotalFit(Shape, RefShape, 0 /* iLev */, 1 /* PyrRatio, can be anything because iLev==0 */, "", "Total", 0, CONF_nPointsXm2vts-1, 0, true, false);lprintf("\n");}#endif // CONF_fShowFitVersusFaceSize//-----------------------------------------------------------------------------#if CONF_fStartShapeOffsetstatic void OffsetStartShape (SHAPE &Shape const Image &Img) // io{double Width = xShapeExtent(Shape);for (int iRow = 0; iRow < Shape.nrows(); iRow++) { if (pLands[iRow].StartShapeOffset) {#if 1 // shrink points double Sign = 1; if (Shape(iRow, VX) > Shape(MNoseTip)) Sign = -1; Shape(iRow, VX) += Sign * Width / 10; Shape(iRow, VY) += Width / 10;#else // expand points int nImgHeight = Img.height; // TODO correct here? double Sign = 1; if (Shape(iRow, VX) < Shape(MNoseTip)) Sign = -1; Shape(iRow, VX) += Sign * Width / 20; Shape(iRow, VY) -= Width / 20; if (Shape(iRow, VY) < -nImgHeight/2 + 1) // don't move point off image Shape(iRow, VY) = -nImgHeight/2 + 1;#endif } }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -