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

📄 startshape.cpp

📁 这是个人脸识别程序
💻 CPP
字号:
// $masm\startshape.cpp 1.5 milbo$ routines for finding the start shape//-----------------------------------------------------------------------------// 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"// following are for aligning base shape to Rowley detector shapestatic const double CONF_RowleyHeightRatio  = 0.60;static const double CONF_RowleyWidthRatio   = 0.07;static const double CONF_RowleyEyeWeight    = 1.0;static const double CONF_RowleyWidthWeight  = 0.5;static const double CONF_RowleyHeightWeight = 0.5;static const double CONF_MaxEyeToFaceWidth 	= 0.52;static const double CONF_EyeFaceBlend       = 0.60;// following are for aligning base shape to Viola Jones detector shapestatic const double CONF_VjHeightShift = 0.15;	// shift height down by 15%static const double CONF_VjShrink 	   = 0.8;	// shrink size of VJ box by 20%//-----------------------------------------------------------------------------// Align MeanShape to the Rowley detector eyes (ignore the overall face box).static voidAlignToRowleyEyes (SHAPE &StartShape,                    // out        const SHAPE &MeanShape, const SHAPE &DetShape)   // in{SHAPE Base(2, 2), Rowley(2, 2);   // points are MLEye MrEyeDASSERT(iTranslatedPoint(MLEye) < MeanShape.nrows() &&       iTranslatedPoint(MREye) < MeanShape.nrows());Base.row(0) = MeanShape.row(iTranslatedPoint(MLEye));Base.row(1) = MeanShape.row(iTranslatedPoint(MREye));ASSERT(!Base.fARowIsZero());// In practice the Rowley detector sometimes misaligns the eyes so here// it's better to just use the average height of the eyes.double yMean = (DetShape(DETECTOR_LEye, VY) + DetShape(DETECTOR_REye, VY)) / 2;Rowley(0, VX) = DetShape(DETECTOR_LEye, VX);Rowley(0, VY) = yMean;Rowley(1, VX) = DetShape(DETECTOR_REye, VX);Rowley(1, VY) = yMean;ASSERT(!Rowley.fARowIsZero());Mat Pose(AlignShape(Base, Rowley, NULL));StartShape = TransformShape(MeanShape, Pose);}//-----------------------------------------------------------------------------// Align MeanShape to the Rowley detector overall face box and the eyes.static voidAlignToRowleyFaceAndEyes (SHAPE &StartShape,             // out        const SHAPE &MeanShape, const SHAPE &DetShape)   // in{SHAPE Base(4, 2), Rowley(4, 2);   // points are MLEye MrEye MlJaw2 MRJaw2DASSERT(iTranslatedPoint(MLEye) < MeanShape.nrows() &&       iTranslatedPoint(MREye) < MeanShape.nrows());Base.row(0) = MeanShape.row(iTranslatedPoint(MLEye));Base.row(1) = MeanShape.row(iTranslatedPoint(MREye));Base.row(2) = MeanShape.row(iTranslatedPoint(MLJaw2));Base.row(3) = MeanShape.row(iTranslatedPoint(MRJaw2));ASSERT(!Base.fARowIsZero());// In practice the Rowley detector sometimes misaligns the eyes so here// it's better to just use the average height of the eyes.double yMean = (DetShape(DETECTOR_LEye, VY) + DetShape(DETECTOR_REye, VY)) / 2;Rowley(0, VX) = DetShape(DETECTOR_LEye, VX);Rowley(0, VY) = yMean;Rowley(1, VX) = DetShape(DETECTOR_REye, VX);Rowley(1, VY) = yMean;double xMin = DetShape(DETECTOR_TopLeft, VX);double xMax = DetShape(DETECTOR_BotRight, VX);// recenter the face on the midpoint of eyes (found to give better results)double EyeMidpoint = (DetShape(DETECTOR_LEye, VX)+DetShape(DETECTOR_REye, VX))/2;xMin = EyeMidpoint - (xMax - xMin)/2;xMax = EyeMidpoint + (xMax - xMin)/2;double yMin = DetShape(DETECTOR_TopLeft, VY);double yMax = DetShape(DETECTOR_BotRight, VY);// y position of Jaw2 in Rowley boxdouble HeightCorrect = CONF_RowleyHeightRatio * (yMax - yMin);// difference between MLJaw2-to-MRJaw2 and Rowley boxdouble WidthCorrect  = CONF_RowleyWidthRatio * (xMax - xMin);Rowley(2, VX) = xMin + WidthCorrect;   Rowley(2, VY) = yMin + HeightCorrect;Rowley(3, VX) = xMax - WidthCorrect;   Rowley(3, VY) = yMin + HeightCorrect;ASSERT(!Rowley.fARowIsZero());Vec Weights(Base.nrows());Weights(0) = CONF_RowleyEyeWeight;Weights(1) = CONF_RowleyEyeWeight;Weights(2) = CONF_RowleyWidthWeight;Weights(3) = CONF_RowleyHeightWeight;Mat Pose(AlignShape(Base, Rowley, &Weights));StartShape = TransformShape(MeanShape, Pose);}//-----------------------------------------------------------------------------// Possbily blend the StartShape with a shape generated from the eye positions.// In detail:// Align the MeanShape using only the Rowley eye positions, to give// the shape StartEyes.// Measure the eye positions in StartEyes against those in the StartShape// we got above (which was aligned to both the detector face and detector eyes).// If the eye positions are very different, then form a new StartShape by blending// StartShape and StartEyes.//// This has proven effective in improving the fit in faces with large// alignment errors, without affecting other faces.static void Blend (SHAPE &StartShape, 							// io				  const SHAPE MeanShape, const SHAPE DetShape)	// in{SHAPE StartEyes;AlignToRowleyEyes(StartEyes, MeanShape, DetShape);double EyeToFaceWidth =	(StartEyes(MREye, VX) - StartEyes(MLEye, VX)) /	(StartShape(MRJaw2, VX) - StartShape(MLJaw2, VX));double Blend = 0;   // assume no blendingif (EyeToFaceWidth > CONF_MaxEyeToFaceWidth)	Blend = CONF_EyeFaceBlend;int i;for (i = 0; i <= MNoseTip; i++)	StartShape.row(i) = (1-Blend) * StartShape.row(i) + Blend * StartEyes.row(i);for (i = MLEye0; i < StartShape.nrows(); i++)   // extra eye points	StartShape.row(i) = (1-Blend) * StartShape.row(i) + Blend * StartEyes.row(i);}//-----------------------------------------------------------------------------static voidAlignToRowley (SHAPE &StartShape,                            // out            const SHAPE &MeanShape, const SHAPE &DetShape)   // in{AlignToRowleyFaceAndEyes(StartShape, MeanShape, DetShape);Blend(StartShape, MeanShape, DetShape);}//-----------------------------------------------------------------------------// Make the Rowley Jones face box smaller and move it down a bit.// This gives a better position for the start shape and also// is needed so we can find the eyes using the Rowley detector.void AdjustViolaJonesShape (SHAPE &Shape)	// io{double xMin = Shape(DETECTOR_TopLeft, VX);double yMin = Shape(DETECTOR_TopLeft, VY);double xMax = Shape(DETECTOR_BotRight, VX);double yMax = Shape(DETECTOR_BotRight, VY);double NewHeight = CONF_VjShrink * (yMax - yMin);double yMean =	(Shape(DETECTOR_TopLeft, VY) + Shape(DETECTOR_BotRight, VY)) / 2;yMean += CONF_VjHeightShift * (yMax - yMin);	// move face downdouble NewWidth = CONF_VjShrink * (xMax - xMin);double xMean =	(Shape(DETECTOR_TopLeft, VX) + Shape(DETECTOR_BotRight, VX)) / 2;Shape(DETECTOR_TopLeft,  VX) = xMean - .5 * NewWidth;Shape(DETECTOR_TopLeft,  VY) = yMean - .5 * NewHeight;Shape(DETECTOR_BotRight, VX) = xMean + .5 * NewWidth;Shape(DETECTOR_BotRight, VY) = yMean + .5 * NewHeight;}//-----------------------------------------------------------------------------// Align MeanShape to the Viola Jones detector face box.static voidAlignToViolaJonesFace (SHAPE &StartShape,                // out        const SHAPE &MeanShape, const SHAPE &DetShape)   // in{SHAPE Base(2, 2), VjAlign(2, 2);   // MlJaw2 MRJaw2Base.row(0) = MeanShape.row(iTranslatedPoint(MLJaw2));Base.row(1) = MeanShape.row(iTranslatedPoint(MRJaw2));ASSERT(!Base.fARowIsZero());double yMean = (DetShape(DETECTOR_TopLeft, VY) + DetShape(DETECTOR_BotRight, VY)) / 2;VjAlign(0, VX) = DetShape(DETECTOR_TopLeft, VX);VjAlign(0, VY) = yMean;VjAlign(1, VX) = DetShape(DETECTOR_BotRight, VX);VjAlign(1, VY) = yMean;ASSERT(!VjAlign.fARowIsZero());Mat Pose(AlignShape(Base, VjAlign, NULL));StartShape = TransformShape(MeanShape, Pose);}//-----------------------------------------------------------------------------static voidAlignToViolaJones (SHAPE &StartShape,       // out		SHAPE &DetShape,					// io: two rows added if fViolaJonesEyes		bool fViolaJonesEyes, Image &Img,   // in        const SHAPE &MeanShape,   			// in        const char sDataDir[])	            // in{AdjustViolaJonesShape(DetShape);AlignToViolaJonesFace(StartShape, MeanShape, DetShape);if (fViolaJonesEyes)	{	int xRightEye, yRightEye, xLeftEye, yLeftEye;	FindEyesGivenFace(&xRightEye, &yRightEye, &xLeftEye, &yLeftEye,		DetShape, Img, sDataDir);	if (xRightEye != -1 && yRightEye != -1 && xLeftEye != -1 && yLeftEye != -1)		{		// found both the left and right eye positions, so use them		DetShape.dimKeep(4, 2);	// add two extra rows for the eyes		DetShape(DETECTOR_LEye, VX) = xRightEye  - Img.width / 2;		DetShape(DETECTOR_LEye, VY) = Img.height / 2 - yRightEye;		DetShape(DETECTOR_REye, VX) = xLeftEye - Img.width / 2;		DetShape(DETECTOR_REye, VY) = Img.height / 2 - yLeftEye;		Blend(StartShape, MeanShape, DetShape);		}	}}//-----------------------------------------------------------------------------// Generate StartShape by aligning the MeanShape to a noised// reference shape (instead of the global detector shape).//// This is invoked during testing if the global detector failed, but we// have a reference shape.//// A test of how good an estimate this is compared to using real Rowley// detector data is as follows: use this instead of the Rowley detector// data on images for which the detector data is available.  Then compare// fit results against using the actual Rowley detector data.  On large// sample sizes you will get the same results to within less than 1// percent.static void GenerateStartShapeFromRefShape (SHAPE &StartShape,		 // out								  			const SHAPE &MeanShape,	 // in								  			const SHAPE &RefShape,	 // in											const char sImageBase[]) // in{lprintf("Using noised ref shape instead of face detector shape\n");StartShape = MeanShape;SHAPE AnchorShape(StartShape.nrows(), 2);// We align to three points of RefShape.// These three points are defined in all three atasets (XM2VTS, BioId and AR sets).double StdDev = 0;switch (sImageBase[0])	{	case 'a':		StdDev = 1.2;		break;	case 'B':		StdDev = 1.06;		break;	case 'm':		StdDev = 3.20;		break;	default:		SysErr("GenerateStartShapeFromRefShape %s", sImageBase);		break;	}// multiplying MTipOfChin noise by 5 keeps fit error roughly constant across the entire faceAnchorShape.row(MTipOfChin) = RefShape.row(MTipOfChin) + RandGauss(5 * StdDev);AnchorShape.row(MLEye)      = RefShape.row(MLEye) 	   + RandGauss(StdDev);AnchorShape.row(MREye)      = RefShape.row(MREye) 	   + RandGauss(StdDev);Mat Pose(AlignShape(StartShape, AnchorShape, NULL));StartShape = TransformShape(MeanShape, Pose);}//-----------------------------------------------------------------------------// Align MeanShape to a global detector shape to provide a// good starting point for the search.// Results are returned in StartShape.boolfGetStartShape (SHAPE &StartShape,  // out	SHAPE &DetShape,			    // out: see DETECTOR_ defs in landmarks.hpp for format    bool fBrief,	                // in	bool fViolaJones,               // in	bool fViolaJonesEyes,           // in	bool fUseRefShapeIfNoDetFace,   // in	Image &Img,                     // in	const char sImageFile[],        // in	const char sImageBase[],        // in	const SHAPE &MeanShape,    		// in	const char sDataDir[],          // in	const char *sRefShapeFile, 		// in	const SHAPE *pRefShape)			// in{bool fSuccess = false;if (sRefShapeFile && sRefShapeFile[0])	{	// Use the pre-calculated global detector shape in sShapeFile.  The global	// detector shapes in sShapeFile were determined by a prior off-line search.	// This is equivalent to doing a global detector search using a global detector	// but is much faster -- nice for testing new models.	bprintf(fBrief, "Precalculated detector shape ");	char sTagString[SLEN];	sprintf(sTagString, "%4.4x %s", (fViolaJones? FA_ViolaJones: FA_Rowley), sImageBase);	fSuccess = fGetNamedShape(DetShape, sTagString, sRefShapeFile, MAT_PLAIN_STRING, fBrief);    if (fSuccess)		if (fViolaJones)			AlignToViolaJones(StartShape, DetShape, fViolaJonesEyes,					          Img, MeanShape, sDataDir);		else			AlignToRowley(StartShape, MeanShape, DetShape);	bprintf(fBrief, "\n");	}else if (fViolaJones)    {    fSuccess = fViolaJonesFindFace(DetShape, Img, sImageFile, sDataDir);    if (fSuccess)		AlignToViolaJones(StartShape, DetShape, fViolaJonesEyes,					      Img, MeanShape, sDataDir);    }else    // Rowley detector    {    fSuccess = fRowleyFindFace(DetShape, Img, sImageFile, sDataDir);    if (fSuccess)	    AlignToRowley(StartShape, MeanShape, DetShape);    }if (!fSuccess && fUseRefShapeIfNoDetFace && pRefShape)	{	GenerateStartShapeFromRefShape(StartShape, MeanShape, *pRefShape, sImageBase);	fSuccess = true;	}// An all zero row means both the x and y coords are zero.// But x and y both equal to 0 means the point is "unused".// So assert that that is not the case.// TODO should do this properly by setting all 0 row to a small nbr.ASSERT(!fSuccess || !StartShape.fARowIsZero());return fSuccess;}

⌨️ 快捷键说明

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