⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ms.cpp

📁 这是个人脸识别程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// $masm\ms.cpp 1.5 milbo$ facial feature search using a pre-built model// Warning: this is raw research code -- expect it to be quite messy.// milbo Petaluma jun 05//-----------------------------------------------------------------------------// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// A copy of the GNU General Public License is available at// http://www.r-project.org/Licenses///-----------------------------------------------------------------------------#include "all.hpp"#define CONF_MsLogFilename			"ms.log"static char	sgImageOut[SLEN];		// name of image file minus path and minus extensionstatic char sgModel[SLEN];			// -s flag: model string prepended to printouts and appended to filenamesstatic bool fgBrief;				// -fb flag: print brief output (as opposed to more verbose output)static clock_t gTime;static double gImagePreScale;		// if input face is too big or too small we scale it by this amountunsigned gImageBits = IM_FinalImageOnly;	// -xi flag: see IM_ defs in imagebits.hppconst static char sgUsage[] =    "ms [FLAGS] IMAGES\n"    "\n"	"Writes face feature coordinates to %s\n"    "\n"    "Optional FLAGS              Range   Default\n"    "\n"    "-fa F   append to log " CONF_MsLogFilename " 0..1    0: create new log file " CONF_MsLogFilename "\n"    "-fb F   brief messages       0..1    0: full progress messages\n"    "\n"    "-xi N   image output in hex (default 1: FinalImageOnly)\n"	"                            GlobalDetector 80    Whiskers     8\n"	"                            WhiskersRef    40    Annotate     4\n"	"         DoubleScale 200    AnnotateRef    20    AllImages    2\n"	"         FullScale   100    ShowRefShape   10    EndImageOnly 1 (AllImages supercedes this)\n"    "\n"    "-m FILE.asm   select model file (specify multiple models with multiple -m flags)\n"    "\n"    "-s STRING      model name: use STRING as a prefix/suffix for progress prints and filenames (default: none)\n"    "               If specified, as a side effect append results to " CONF_sMsDatFilename "\n"    "\n"    "-r REF.shape   align base shape to nn shape in REF.shape and print stats using ref shape in REF.shape\n"    "               Default: do NN search to align base shape, don't print stats\n"    "\n"    "-p PATTERN     get input images matching regex PAT in REF.shape specified by -r (use masm -? for details)\n"	"-P Mask1 Mask2 additional filter for -p shapes [default 0 0 for all]\n"	"-ni N          max number of images [default 0 for all matching -p and -P specs]\n"	"-nr N          0 means no random selection, any other val select randomly with rand seed=N [default 1]\n"	"               (only applies when -ni N not equal to 0)\n"    "\n"    "-v             use Viola Jones global face detector (instead of Rowley neural net detector)\n"    "-ve            use Viola Jones global face detector with Rowley eye positions\n"    "               (gives worse results than plain -v)\n"    "\n"    "-G             generate feature data for post analysis\n"    "-S             skip image with a warning if global detector fails (else if -r then synthesize from ref shape)";#define CONF_fShowFitVersusFaceSize 0#define CONF_fSelfEvaluate	0	//TODO experimental code to try to predict how good the fit is#if CONF_fSelfEvaluatestatic double gLastFit;static int ngLastQualifyingDisplacements;static int ngStartLev;static double gDiffAll;static double gDiff;static int giIter;#endif#define CONF_fPrintShapeSize 0	//TODO print the final size and fitstatic int ngModels; 			//TODO must remove this global variable// following externs are listed here because they can't be defined in masmconf.hpp because of .h file order dependenciesvoid InitAsmsForSearch(tAsmModel Model[],					// out, except sFile must be initialized on entry						int nModels, unsigned ImageBits);	// invoid CombineModelSearchResults(SHAPE &CombinedShape,		// io: best shape formed by combining all searches					int iModel, const SHAPE &Shape);		// in: results of current search//-----------------------------------------------------------------------------// Return best fit value and the offsets ixBest and iyBest// Do this by getting an image profile at a range of offsets from iPoint// and matching each profile against the Modelstatic double FindBestMatchingProf (int &ixBest, int &iyBest, 			// out: for 1D profiles: ix is along whisker, iy is perp to whisker				int iPoint, const SHAPE& Shape, const tLand Lands[],	// in				const SHAPE &AlignedMeanShape, int nPixSearch,			// in				tSearchImages &SearchImgs, const tAsmLev &Model,		// in except SearchImgs.ProgressImg is modified				int nTrimCovar){int nxMinOffset = -nPixSearch;int nxMaxOffset = nPixSearch;int nyMaxOffset;unsigned ProfSpec = Model.ProfSpecs[iPoint];if (ProfSpec & PROF_2d)										// two dimensional profile?	nyMaxOffset = CONF_nyMaxOffset(nPixSearch);				// if so, we need to offset in y direction as wellelse	{	PrepareProf1D(SearchImgs.Img, Shape, ProfSpec, Lands, AlignedMeanShape, 		iPoint, nGetProfWidthFromModel(iPoint, 0, Model) + 2 * nPixSearch, 0, 0);	nyMaxOffset = 0;										// no y offset for 2D profiles	}double BestFit = DBL_MAX;ixBest = 0, iyBest = 0;for (int iy = -nyMaxOffset; iy <= nyMaxOffset; iy++)		// 1D; no offset            2D: offset vertically	for (int ix = nxMinOffset; ix <= nxMaxOffset; ix++)		// 1D: offset along whisker 2D: offset horizontally		{		// call model-specific fitness routine		double Fit = GetProfileFit(SearchImgs, iPoint, ix, iy, Model, Shape, Lands, ProfSpec, nTrimCovar);		// Test for a new best fit		// We test against ix<=0 and iy<=0 so if there are exact matches then ixBest=0 (no change)		if ((ix <= 0) && (iy <= 0)? Fit <= BestFit:  Fit < BestFit)			{			ixBest = ix;			iyBest = iy;			BestFit = Fit;			}		}return BestFit;}//-----------------------------------------------------------------------------static inline bool fPassQualifyingDisplacementCriterion (const int ixBest, const int iyBest, const int nPixSearch){#if CONF_nQualifyingDisplacementMethod == 1	return ABS(ixBest) + ABS(iyBest) <= nPixSearch;			// manhattan distance#elif CONF_nQualifyingDisplacementMethod == 2	return ABS(ixBest) <= nPixSearch/2;						// original code#elif CONF_nQualifyingDisplacementMethod == 3	return sqrt(SQR(ixBest) + SQR(iyBest)) <= nPixSearch/2;	// euclidean distance#elif CONF_nQualifyingDisplacementMethod == 4	return ABS(ixBest) <= (nPixSearch-1)/2;#elif CONF_nQualifyingDisplacementMethod == 5	return ABS(ixBest) + ABS(iyBest) <= (nPixSearch-1);#elif CONF_nQualifyingDisplacementMethod == 6	return sqrt(SQR(ixBest) + SQR(iyBest)) <= (nPixSearch-1)/2;#else	SysErr("CONF_nQualifyingDisplacementMethod");#endif}//-----------------------------------------------------------------------------// Updates NewShape to suggested new value, and returns number of pixels within// the central 50% of the profiletemplate<typename ModelT>static int GetSuggestedShape (SHAPE& SuggestedShape, Vec &Weights,	// out		const SHAPE& Shape, int nPixSearch, tSearchImages &SearchImgs, // in except SearchImgs.ProgressImg is modified		const ModelT &Model, const double Momentum,				// in		const tLand Lands[], const SHAPE &AlignedMeanShape, 	// in		int nTrimCovar){int nWithinFifyPercent = 0;int ixBest, iyBest;int nPoints = SuggestedShape.nrows();for (int iPoint = 0; iPoint < nPoints; iPoint++) 	if (fPointUsed(Shape, iPoint))		{		double Fit = FindBestMatchingProf(ixBest, iyBest, iPoint, 						Shape, Lands, AlignedMeanShape, nPixSearch, 						SearchImgs, Model, nTrimCovar);#if CONF_fSelfEvaluate		gLastFit += Fit;#endif		// set SuggestedShape(iPoint) to best offset from current position		if (Model.ProfSpecs[iPoint] & PROF_2d)						// two dimensional profile?			{			SuggestedShape(iPoint, VX) = Shape(iPoint, VX) - ixBest;		// x,y orthogonal to image sides (not to whisker)			SuggestedShape(iPoint, VY) = Shape(iPoint, VY) - iyBest;			if (fPassQualifyingDisplacementCriterion(ixBest, iyBest, nPixSearch))				nWithinFifyPercent++;			}		else														// must move point along the whisker			{			double DeltaX = 0, DeltaY = 0;										if (ixBest || iyBest)				GetProfStepSize(&DeltaX, &DeltaY, Shape, iPoint, 0, Lands, AlignedMeanShape);#if CONF_nSearchMomentumLev <= CONF_nMaxLevs			SuggestedShape(iPoint, VX) = Shape(iPoint, VX) + Momentum * ((ixBest * DeltaX) + (iyBest * DeltaY));			SuggestedShape(iPoint, VY) = Shape(iPoint, VY) + Momentum * ((ixBest * DeltaY) - (iyBest * DeltaX));			if (Momemtum * ABS(ixBest) <= nPixSearch/2)				nWithinFifyPercent++;#else	// ignore momentum			SuggestedShape(iPoint, VX) = GetX(Shape(iPoint, VX), ixBest, iyBest, DeltaX, DeltaY);			SuggestedShape(iPoint, VY) = GetY(Shape(iPoint, VY), ixBest, iyBest, DeltaX, DeltaY);			if (ABS(ixBest) <= nPixSearch/2)				nWithinFifyPercent++;#endif			}		if (CONF_fWeightedAlign)			{			if (Fit < .001)					// prevent div by zero and also limit too high weight for spurious good match				Fit = .001;					// magic nbr determined by basic testing, could perhaps be improved TODO			Weights(iPoint) = 1 / Fit;		// a better fit has a bigger weight TODO should adjust for Prof.nrows()			}		else			Weights(iPoint) = 1;		}return nWithinFifyPercent;}//-----------------------------------------------------------------------------// Show shape as search progresses, bitmap format. Gaudy colors, but useful for debugging.static void ShowSearchShape (const SHAPE &Shape, int iter, 					// in					  RgbImage &ProgressImg, 								// out					  bool fLastPass, double ScaleOut,						// in					  int nMaxSearchIters,									// in					  const tLand Lands[], const SHAPE &AlignedMeanShape)	// in{unsigned Color;if (iter == 0)			// 1st pass?	Color = C_DBLUE;else if (fLastPass)		// last pass	Color = C_RED;else if (iter == 1)		// 2nd pass?	Color = C_GREEN;else					// intermediate pass, use shades of gray, darker for higher generations	{	Color = 200 * (nMaxSearchIters - iter) / nMaxSearchIters;	 	Color |= Color << 16;	// convert to cyan	}bool fWhiskers = false;	// (gImageBits & IM_Whiskers) && iter == 0;DrawShape(ProgressImg, Shape, Color, ScaleOut, CONF_fConnectDots, fWhiskers, fWhiskers, 0, 			IM_TRANSPARENT, Lands, &AlignedMeanShape);}//-----------------------------------------------------------------------------const Image &GetDisplayImage (unsigned ImageBits, const Image &ScaledImg, const Image &FullImg, const Image &DoubleImg){if (ImageBits & IM_DoubleScale)	return DoubleImg;else if (ImageBits & IM_FullScale)	return FullImg;else	return ScaledImg;}//-----------------------------------------------------------------------------static void ShowSearchProgress (RgbImage &ProgressImg,  								// io						 int iter, int nWithinFifyPercent, SHAPE Shape, 				// in					  	 int nMaxSearchIters,											// in						 const tLand Lands[], const SHAPE &AlignedMeanShape, int iLev)	// in{if (gImageBits & IM_AllImages)	{	double ScaleOut = GetScaleOut(gImageBits, iLev);	ShowSearchShape(Shape, iter, ProgressImg, false, ScaleOut, nMaxSearchIters, Lands, AlignedMeanShape);	}bprintf(fgBrief, "%2.2d ", nWithinFifyPercent);if ((iter + 1) % 16 == 0)		// time to print a newline?	bprintf(fgBrief, "\n%s                            ", sgModel); 	}//-----------------------------------------------------------------------------// This returns the inter-eye distance, or 1 if we aren't normalizing to the inter-eye distance.// The results is used (later) as follows: we divide the fitness by inter-eye distance // to normalize the fitness for printingstatic double GetNormDist (const SHAPE &Shape, const SHAPE &RefShape){#if CONF_nMethodNormSearchResults==NormSearchResults_Noreturn 1;#elif CONF_nMethodNormSearchResults==NormSearchResults_FittedEyeToEyereturn PointDist(Shape, MLEye, MREye);#elif CONF_nMethodNormSearchResults==NormSearchResults_RefEyeToEyereturn PointDist(RefShape, MLEye, MREye);#elseSysErr("GetNormDist");#endif}//-----------------------------------------------------------------------------template<typename ModelT>static void ShapeSearch (SHAPE &Shape,								// io				tSearchImages &SearchImgs,							// in except SearchImgs.ProgressImg is modified				const ModelT &Model, 								// in				int iLev, const tLand Lands[],	SHAPE *pRefShape, 	// in				const char sImageBase[], int nStartLev)				// in{SHAPE ProfShape(Shape);									// Shape after profile matchingint	  iter = 0, nWithinFifyPercent = 0;// if fgExplicitPrevNext is true://   AlignedMeanShape is used to figure out prev and next landmarks, but only if //   those landmarks are missing (i.e. have value 0,0) in Shape.  So if Shape has a full //   complement of landmarks, AlignedMeanShape isn't used during the search// if fgExplicitPrevNext is false: AlignedMeanShape isn't usedSHAPE AlignedMeanShape(Shape);// The shape params, initialized to 0// The original formulation called for this to be set to 0 each time we run the model (search// for "Model.EigVecs * b" below).  I find we get slightly better results if we remember the// shape params from the previous run.  Thus this is outside the loop.Vec	b(Model.EigVecs.nrows());		 	Vec Weights(Shape.nrows());bprintf(fgBrief, "Search ");int nUsedPoints = nGetNbrUsedPoints(Shape, Shape.nrows());#if CONF_fSelfEvaluategLastFit = 0;ngLastQualifyingDisplacements = 0;gDiffAll = 0;gDiff = 0;#endifint nMaxSearchIters = Model.nMaxSearchIters;#if CONF_fUseBestSoFarMatView BestShape(Shape);		// best shape seen so far (ie highest nBest)int nBest = 0;#endifwhile ((iter < nMaxSearchIters) && (nWithinFifyPercent <= (Model.nQualifyingDisplacments * nUsedPoints)/100))	{	if (fgExplicitPrevNext && (nUsedPoints != Model.nPoints))  // AlignedMeanShape is only needed if don't have all landmarks 		AlignShape(AlignedMeanShape, Shape);	// Estimate the best ProfShape by profile matching the landmarks in Shape.  Also initialize Weights.	double Momentum = 1.0;#if CONF_nSearchMomentumLev <= CONF_nMaxLevs	if (iLev >= CONF_nSearchMomentumLev && iter == 0)		Momentum = CONF_SearchMomentum;#endif	nWithinFifyPercent = GetSuggestedShape(ProfShape, Weights, Shape, Model.nPixSearch, SearchImgs, 							Model.AsmLevs[iLev], Momentum, Lands, AlignedMeanShape, Model.nTrimCovar);#if CONF_fSelfEvaluate	ngLastQualifyingDisplacements += nWithinFifyPercent;#endif	ShowSearchProgress(SearchImgs.ProgressImg, iter, nWithinFifyPercent, Shape, nMaxSearchIters, Lands, AlignedMeanShape, iLev);	if (CONF_fPrintAllInDatFile && pRefShape)		AppendDistancesToDatFile(iLev, ProfShape, *pRefShape, 								 GetNormDist(ProfShape, *pRefShape), sImageBase, sgModel, "bProf", -1);	// align ProfShape to the shape model, put result in Shape	if (iter < CONF_nItersBeforeModelFit)	// CONF_nItersBeforeModelFit is actually always 0 unless changed for debugging		Shape = ProfShape;					// don't conform ProfShape to model i.e. use profile matches as is	else		{		bool fShapeModelFinalIter = (iter >= nMaxSearchIters-1);	// true if reached max iters and

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -