📄 masm.cpp
字号:
}fclose(pFile);lprintf("\n");if (fgUserInt) // if user hit ^C then remove partially completed file { lprintf("Removing partial file %s\n", sFile); unlink(sFile); }}//-----------------------------------------------------------------------------static void TallyUnusedLandmarks (IntVec &nUnusedLandmarks, const SHAPE &Shape, const string &Tag, int nPointsToCheck){for (int iPoint = 0; iPoint < nPointsToCheck; iPoint++) if (Shape(iPoint, VX) == 0 && Shape(iPoint, VY) == 0) { static fWarned = false; if (!fWarned) { Warn("Landmark %d unused in %s (and possibly other shapes)", iPoint, Tag.c_str()); fWarned = true; } nUnusedLandmarks[iPoint]++; }}//-----------------------------------------------------------------------------// On entry nShapes is the max number of shapes// We standardize all shapes to the number of rows in the reference shape.// We align all shapes, using the reference shape as a reference.static void ReadMasmShapes (tShapes &Shapes, int &iRefShape, // out int nWantedShapes, char sTagRegExp[], // in unsigned Mask1, unsigned Mask2, // in: only read matrices where Attr&Mask1 == Mask2 (Attr is hex part of tag string) tSampleSpec *pSampleSpec, // in const char sShapeFile[], bool fVerbose) // in{ReadSelectedShapes(&Shapes.OrgShapes, Shapes.TagStrings, Shapes.sImageDirs, nWantedShapes, sTagRegExp, Mask1, Mask2, CONF_nRandomSeed, pSampleSpec, sShapeFile, fVerbose);iRefShape = iGetRefShapeIndex(Shapes.OrgShapes, Shapes.TagStrings, (Mask1|FA_ViolaJones|FA_Rowley|FA_Test1|FA_Test2), Mask2);#if CONF_nReducedNbrPoints > 0// convert all shapes to have the CONF_nReducedNbrPoints landmarks, unspecified landmarks are set to 0,0DASSERT(CONF_nReducedNbrPoints <= Shapes.OrgShapes[iRefShape].nrows());int nWantedPoints = CONF_nReducedNbrPoints;if (nWantedPoints != Shapes.OrgShapes[iRefShape].nrows()) lprintf("reducing to %d points, ", nWantedPoints);#else// convert all shapes to have CONF_nGenLandmarksUsedInternally landmarks, unspecified landmarks are set to 0,0int nWantedPoints = (CONF_nGenLandmarksUsedInternally == 0)? Shapes.OrgShapes[iRefShape].nrows(): CONF_nGenLandmarksUsedInternally;#endifif (nWantedPoints == Shapes.OrgShapes[iRefShape].nrows()) lprintf("no need to convert the number of landmarks");lprintf("\n");int nChanged = 0;int nShapes = Shapes.OrgShapes.size();IntVec nUnusedLandmarks(CONF_nMaxLandmarks, 0); // nUsedLandmarks[iPoint] gets bumped when iPoint isn't used in a shapeShapes.fExtraLEyeLandsUsed.resize(nShapes);Shapes.fExtraREyeLandsUsed.resize(nShapes);for (int iShape = 0; iShape < nShapes && !fgErr; iShape++) { if (Shapes.OrgShapes[iShape].nrows() > MLEye0 && fPointUsed(Shapes.OrgShapes[iShape], MLEye0)) Shapes.fExtraLEyeLandsUsed[iShape] = true; else Shapes.fExtraLEyeLandsUsed[iShape] = false; if (Shapes.OrgShapes[iShape].nrows() > MREye0 && fPointUsed(Shapes.OrgShapes[iShape], MREye0)) Shapes.fExtraREyeLandsUsed[iShape] = true; else Shapes.fExtraREyeLandsUsed[iShape] = false;#if CONF_fShowSampledImageWithShapes //TODO for now RgbImage Img; const char *sFile1 = Shapes.TagStrings[iShape].c_str()+FNAME_OFFSET; char sFile[SLEN]; sprintf(sFile, sFile1, ".pgm"); sLoadImageGivenDirs(Img, Shapes.sImageDirs, sFile, QUIET, TRUE); DrawShape(Img, Shapes.OrgShapes[iShape], C_DRED, 1.0, IM_NO_CONNECT_DOTS, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_TRANSPARENT); char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT], sPath[SLEN]; _splitpath(&Shapes.TagStrings[iShape][FNAME_OFFSET], sDrive, sDir, sFname, sExt); sprintf(sPath, "%s/%sx", CONF_sOutDir, sFname); WriteBmp(Img, sPath, VERBOSE);#endif TallyUnusedLandmarks(nUnusedLandmarks, Shapes.OrgShapes[iShape], Shapes.TagStrings[iShape], nWantedPoints); // this is just for a possible message to the user if (fConvertShapeToInternalFormat(Shapes.OrgShapes[iShape], nWantedPoints, CONF_GenSubModel, CONF_nSynthesizedEyePoints, &Shapes.TagStrings, iShape)) nChanged++; }if (nChanged) lprintf("Converted %d shape%s to %d points per shape, %d shape%s unchanged\n", nChanged, ((nChanged!=1)? "s":""), nWantedPoints, nShapes-nChanged, ((nShapes-nChanged!=1)? "s":""));if (CONF_GenSubModel != SM_All) lprintf("Extracted submodel %s (%d landmarks in reference shape)\n", sgSubModel[CONF_GenSubModel], nUsedLandmarks(Shapes.OrgShapes[iRefShape]));else if (nWantedPoints != CONF_nPointsXm2vts && nWantedPoints != CONF_nPoints84) Warn("Non-standard nWantedPoints %d", nWantedPoints);// list landmarks that aren't used in every shapebool fFirstTime = true;for (int iPoint = 0; iPoint < nWantedPoints; iPoint++) { if (nUnusedLandmarks[iPoint]) { if (fFirstTime) lprintf("Some shapes don't use the following landmarks: "); lprintf("%d ", iPoint); fFirstTime = false; } }if (!fFirstTime) lprintf("\n");#if CONF_nSynthesizedEyePointslprintf("Will synthesize %d eye landmarks for a total of %d landmarks\n", CONF_nSynthesizedEyePoints, CONF_nGenLandmarksUsedInternally);#endifShapes.nPoints = nWantedPoints; // We just converted all shapes to internal format so this is true for all shapes // Some points may be unused though (they wil have the value 0,0)Shapes.nShapes = nShapes;Shapes.TagInts.resize(nShapes);Shapes.nUsedLandmarks.resize(nShapes);Shapes.Shapes.resize(nShapes);bool fShapesAllHaveSameNbrOfUsedLandmarks = true;for (iShape = 0; iShape < nShapes; iShape++) { Shapes.Shapes[iShape] = Shapes.OrgShapes[iShape]; Shapes.nUsedLandmarks[iShape] = nUsedLandmarks(Shapes.Shapes[iShape]); if (Shapes.nUsedLandmarks[iShape] != Shapes.nUsedLandmarks[0]) fShapesAllHaveSameNbrOfUsedLandmarks = false; DASSERT(Shapes.TagStrings[iShape].c_str()[FNAME_OFFSET-1] == ' '); // tag string should be of the form: "1234 filename" DASSERT(isprint(Shapes.TagStrings[iShape].c_str()[FNAME_OFFSET]) && !isspace(Shapes.TagStrings[iShape].c_str()[FNAME_OFFSET])); if (1 != sscanf(Shapes.TagStrings[iShape].c_str(), "%x", &Shapes.TagInts[iShape])) SysErr("Can't convert tag in %s to a hex number: %s\n", sShapeFile, Shapes.TagStrings[iShape]); }if (!fShapesAllHaveSameNbrOfUsedLandmarks) Warn("Not all shapes have the same number of (used) landmarks as shape 0");if (CONF_GenSubModel == SM_All && nWantedPoints != Shapes.nUsedLandmarks[iRefShape]) { Warn("Only %d of %d landmarks are used in the reference shape %d", Shapes.nUsedLandmarks[iRefShape], nWantedPoints, iRefShape); if (fgExplicitPrevNext) { Warn("Forcing ExplicitPrevNext to 0 (overrides default setting fgGenExplicitPrevNext=1)"); fgExplicitPrevNext = false; } }Shapes.pLand = pSelectLand(Shapes.nPoints); // nbr of landmarks determine the landmark info format}//-----------------------------------------------------------------------------// Generate a series of bitmap files which show variations of the shape model.// For debugging.#if CONF_fShowDebugImagesstatic void ShowShapeVariations (const Vec &EigVals, Mat &EigVecs, const SHAPE& AvShape) // in{lprintf("%s/var*.bmp ", CONF_sOutDir);// calculate how many eigs are worth printing, up to a maximum of 30int nEigs;double MinEig = EigVals(0) / 1000; // 1000 is somewhat arbitraryfor (nEigs = 0; nEigs < EigVals.nrows(); nEigs++) if (EigVals(nEigs) <= MinEig || nEigs == 100) break;if (nEigs > 30) nEigs = 30;#define CONF_VariationLambdaMax 0.3//#define CONF_VarImageWidth 1000 // height is the same//double Scale = CONF_VarImageWidth / (xShapeExtent(AvShape) * 1.5); // make page width 1.5 times face width#define CONF_VarImageWidth 400double Scale = 1;for (int iEig = 0; iEig < nEigs; iEig++) { RgbImage Img(CONF_VarImageWidth, CONF_VarImageWidth); FillRgbImage(Img, 255, 255, 255); // white background VecView BaseVector(EigVecs, iEig); for (double Lambda = -CONF_VariationLambdaMax; Lambda <= CONF_VariationLambdaMax; Lambda += CONF_VariationLambdaMax) { Mat Shape(AvShape); Shape.viewAsCol() += BaseVector * Lambda * sqrt(EigVals(iEig));#if 0 unsigned Color = 150 * fabs(Lambda) / CONF_VariationLambdaMax; // shades of gray: lighter for bigger lambdas Color = (Color << 16) | (Color << 8) | Color;#else unsigned Color = 0; if (Lambda == 0) Color = C_RED; else if (Lambda == -CONF_VariationLambdaMax) Color = 0x000000; // black else Color = 0x9f9f9f; // gray#endif //char sMsg[100]; sprintf(sMsg, "iEig %d Lambda %g Color %x Scale %g\n", iEig, Lambda, Color, Scale); //Shape.print(sMsg); DrawShape(Img, Shape, Color, Scale, IM_CONNECT_DOTS, IM_NO_ANNOTATE, IM_NO_WHISKERS, 0, IM_NO_TRANSPARENT); } RgbPrintf(Img, 8, 3, C_BLACK, 160, "Shape variation (eig %d of %d, lamba %g)", iEig, EigVals.nrows(), double(CONF_VariationLambdaMax)); char sPath[SLEN]; sprintf(sPath, "%s/var%2.2d.bmp", CONF_sOutDir, iEig); WriteBmp(Img, sPath); }}#endif CONF_fShowDebugImages//-----------------------------------------------------------------------------int __cdecl main (int argc, const char *argv[]){int nWantedImages = 0;char sOutFile[SLEN], sTagRegExp[SLEN], sSampleSpec[SLEN];unsigned AttrMask1=0, AttrMask2=0;sOutFile[0] = 0; sTagRegExp[0] = 0; sSampleSpec[0] = 0;InitMallocDebug(false);while (--argc > 0 && (*++argv)[0] == '-') // command line arguments: masm [flags] FILE.shape { char *sQForHelp = "Use masm -? for help."; switch (*(*argv + 1)) { case 'f': GetOptBool(&argc, &argv, 'f', "v", &fgVerbose); // -fv break; case 'n': GetOptInt(&argc, &argv, 'n', "i", &nWantedImages, 1, 0, 10000); // -ni break; case 'o': // output file argv++; argc--; if (argc < 1) Err("-o needs an argument. %s", sQForHelp); strcpy(sOutFile, *argv); break; case 'p': // shape pattern filter argv++; argc--; if (sSampleSpec[0]) Err("You can't use both -p and -S. %s", sQForHelp); if (argc < 1) Err("-p needs an argument. %s", sQForHelp); strcpy(sTagRegExp, *argv); break; case 'P': // shape mask filter argv++; argc--; if (sSampleSpec[0]) Err("You can't use both -p and -S. %s", sQForHelp); if (argc < 1 || 1 != sscanf(*argv, "%x", &AttrMask1)) Err("-P needs two hex number arguments. %s", sQForHelp); argv++; argc--; if (argc < 1 || 1 != sscanf(*argv, "%x", &AttrMask2)) Err("-P needs two hex number arguments. %s", sQForHelp); break; case 'S': // sample set argv++; argc--; if (AttrMask1 || AttrMask2 || sTagRegExp[0]) Err("You can't use -S with -P or -p. %s", sQForHelp); if (argc < 1) Err("-S needs an argument. %s", sQForHelp); strcpy(sSampleSpec, *argv); break; case '?': Err(sgUsage); break; default: Err("Unrecognized option %s. %s", *argv, sQForHelp); break; } }if (argc != 1) // argv now points to FILE.shape Err("No shapes file, use masm -? for help");ASSERT(CONF_nSynthesizedEyePoints == 0 || CONF_nFencePosts == 0); // only one allowed because these interfere with each othertSampleSpec SampleSpec; SampleSpec.sFile[0] = 0;if (sSampleSpec[0]) ParseSampleSpec(SampleSpec, sSampleSpec);Init(VERBOSE, false, "masm.log"); // open log file etc.lprintf("masm version 1.5\n");// set global configuration optionsfgExplicitPrevNext = CONF_fGenExplicitPrevNext;gNormalizedProfLen = CONF_GenNormalizedProfLen;// generate file nameschar sShapeFile[PLEN];strcpy(sShapeFile, *argv);char *sSuffix = ".asm";if (sOutFile[0]) { // user specified an output file with -o? char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT], s[SLEN]; _splitpath(sOutFile, sDrive, sDir, sFname, sExt); sprintf(s, "%s%s", sFname, sgSubModel[CONF_GenSubModel]); _makepath(sOutFile, sDrive, sDir, s, sSuffix); // ensure correct suffix }else { char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT], s[SLEN]; _splitpath(sShapeFile, sDrive, sDir, sFname, sExt); // generate name from .shape file name sprintf(s, "%s%s", sFname, sgSubModel[CONF_GenSubModel]); _makepath(sOutFile, "", "", s, sSuffix); }// get shapes from shape filetShapes Shapes;int iRefShape;ReadMasmShapes(Shapes, iRefShape, nWantedImages, sTagRegExp, AttrMask1, AttrMask2, (SampleSpec.sFile[0]? &SampleSpec: NULL), // sample file specified by -S flag? sShape
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -