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

📄 shapemodel.cpp

📁 这是个人脸识别程序
💻 CPP
字号:
// $masm\shapeModel.cpp 1.5 milbo$ routines for using the shape model during search// Warning: this is raw research code -- expect it to be quite messy.// milbo durban jun 06//-----------------------------------------------------------------------------// 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"//-----------------------------------------------------------------------------// Utilities for SortVec (which is defined below)static const Vec *pgVec;static int __cdecl CompareForSortVec (const void *pArg1, const void *pArg2){int i1 = *(int *)pArg1;int i2 = *(int *)pArg2;double  diff = (*pgVec)(i1) - (*pgVec)(i2);if (diff > 0)	return -1;else if (diff < 0)	return 1;else	return 0;}//-----------------------------------------------------------------------------// SortVec(v) returns the INDICES of v, sorted such that v(Sorted[i]) >= v(Sorted[i+1])//// v is unchanged//// Caller must free the returned array of indicesstatic void SortVec (int Sorted[],			// out						const Vec &v)		// in{for (int i = 0; i < v.nelems(); i++)	Sorted[i] = i;pgVec = &v;qsort(Sorted, v.nelems(), sizeof(int), CompareForSortVec);}//-----------------------------------------------------------------------------// Set unused points to 0,0// TODO look for a more efficient way of doing thisvoid SetUnusedPointsToZero (SHAPE &Shape, const SHAPE &RefShape){for (int iPoint = 0; iPoint < RefShape.nrows(); iPoint++)	if (!fPointUsed(RefShape, iPoint))		{		Shape(iPoint, VX) = 0;		Shape(iPoint, VY) = 0;		}}//-----------------------------------------------------------------------------// Limit the values of b to make sure the generated shape is plausible.// See CootesTaylor section 4.6 www.isbe.man.ac.uk/~bim/Models/app_models.pdfstatic void nLimitB (Vec &b, 												// io			 		const Vec EigVals, int nPrincipalEigs, double BMax)		// in{#if CONF_fClipB //---------------------------------------// Method 1: apply hard limits i.e. clip each b[i] to BMax * sqrt(lambda_i)for (int iEig = 0; iEig < nPrincipalEigs; iEig++)	{	double Limit = BMax * sqrt(EigVals(iEig));	if (b(iEig) < -Limit)		b(iEig) = -Limit;	else if (b(iEig) > Limit)		b(iEig) = Limit;	}#else //------------------------------------------------// Method 2: constrain b to be in a hyperellipsoid// i.e. scale each b[i] so sqrt(total) < BMaxdouble Limit = 0;for (int iEig = 0; iEig < nPrincipalEigs; iEig++)	Limit += (b(iEig) * b(iEig)) / EigVals(iEig);Limit = sqrt(Limit);if (Limit > BMax)	for (iEig = 0; iEig < nPrincipalEigs; iEig++)		b(iEig) *= BMax / Limit;		// pro-rated reduction#if _DEBUG	// sanity check: recalculate with the new b and check that total < BMaxLimit = 0;for (int i = 0; i < nPrincipalEigs; i++)	Limit += (b(i) * b(i)) / EigVals(i);if (sqrt(Limit) > BMax + 0.001)	SysErr("LimitB %g %g", sqrt(Limit), BMax);#endif#endif //-----------------------------------------------// discard unused higher componentswhile (iEig < EigVals.nrows())	b(iEig++) = 0.0;}//-----------------------------------------------------------------------------static SHAPE ConformShapeToModel_Simple (Vec &b,										// io								const SHAPE &InShape, const tAsmModel &Model, int iLev,	// in								const Vec *pWeights)									// in{Vec	MeanShape(Model.AsmLevs[iLev].MeanShape);SetUnusedPointsToZero(MeanShape, InShape);// For some calculations we need to see shapes (nrows x 2) as vectors (1 x 2*nrows).// This is an alias to do this for MeanShape.// Note that this is a "view" so if you change MeanShapeAsVec you are changing MeanShape too, and vice versa.VecView	MeanShapeAsVec(MeanShape.viewAsCol());// Find the Model b that best fits InShape to the Model.// CootesTaylor 2004 Sec 7.2 says just one iteration is best, so there is no loop here.// In fact, slightly improved results (especially for AR shapes) can be got// by iterating, see ConformShapeToModel_FancySHAPE x(InShape.nrows(), 2);x.viewAsCol() = MeanShapeAsVec + Model.EigVecs * b;			// generate a model shape (this actually updates x)Mat Pose(AlignShape(x, InShape, pWeights));					// find pose to best map the model shape x to InShapeSHAPE y(TransformShape(InShape, Pose.inverse()));			// project InShape into the model spaceb = Model.EigInverse * (y.viewAsCol() - MeanShapeAsVec);	// update model params to match ynLimitB(b, Model.AsmLevs[iLev].EigVals, Model.AsmLevs[iLev].nEigs, Model.AsmLevs[iLev].BMax);						// make sure we stay within model limits// We now have b// Generate OutShape from the model using our calculated b, and align OutShape to InShapeSHAPE OutShape(InShape.nrows(), 2);OutShape.viewAsCol() = Model.EigVecs * b;OutShape = TransformShape(Model.AsmLevs[iLev].MeanShape + OutShape, Pose);SetUnusedPointsToZero(OutShape, InShape);return OutShape;}//-----------------------------------------------------------------------------// Like ConformShapeToModel_Simple but iterates looking for the best fit// TODO need to add code to deal with unused points?static SHAPE ConformShapeToModel_Fancy (Vec &b,												// io								const SHAPE &InShape, const tAsmModel &Model, int iLev,		// in								const Vec *pWeights, 										// in								bool fShapeModelFinalIter)									// in{Vec	MeanShape(Model.AsmLevs[iLev].MeanShape);SetUnusedPointsToZero(MeanShape, InShape);// For some calculations we need to see shapes (nrows x 2) as vectors (1 x 2*nrows).// This is an alias to do this for MeanShape.// Note that this is a "view" so if you change MeanShapeAsVec you are changing MeanShape too, and vice versa.VecView	MeanShapeAsVec(MeanShape.viewAsCol());// find the Model b that best fits InShape to the ModelSHAPE Shape(InShape);						// working shape#if CONF_fRetainOrgBVec OrgB(b);								// remember b passed in to this function#endifint nEigs = Model.AsmLevs[iLev].nEigs;double BMax = Model.AsmLevs[iLev].BMax;if (fShapeModelFinalIter)										// if final iter in main ASM search loop then loosen up the model	{	nEigs = Model.AsmLevs[iLev].nEigsFinal;	BMax = Model.AsmLevs[iLev].BMaxFinal;	}for (int iter = 0; iter < Model.nShapeModelIters; iter++)	{	SHAPE x(InShape.nrows(), 2);	x.viewAsCol() = MeanShapeAsVec + Model.EigVecs * b;			// generate a model shape (this actually updates x)#if CONF_fAffineShapeModelAlign	DASSERT(pWeights == NULL);	Mat Pose(AlignShape_Affine(x, InShape));					// find pose to best map the model shape x to InShape#elif CONF_fIterativeShapeModelAlign	Mat Pose(AlignShape_Iteration(x, InShape, pWeights));#else	Mat Pose(AlignShape(x, InShape, pWeights));#endif	SHAPE y(TransformShape(InShape, Pose.inverse()));			// project InShape into the model space	b = Model.EigInverse * (y.viewAsCol() - MeanShapeAsVec);	// update model params to match y	nLimitB(b, Model.AsmLevs[iLev].EigVals, nEigs, BMax);		// make sure we stay within model limits	// We now have b.	// Generate Shape from the model using our calculated b, and align Shape to InShape.	Shape.viewAsCol() = Model.EigVecs * b;	Shape = TransformShape(Model.AsmLevs[iLev].MeanShape + Shape, Pose);#if 0	//TODO put this into report	#define CONF_fUseInShapeInFinalIter 0	#define CONF_MinDist 				0		// 0.0 to use only model points, 1.0 to use InShape points whose dist < 1.0	if (fShapeModelFinalIter && (CONF_MinDist != 0) && (CONF_fUseInShapeInFinalIter || iter < Model.nShapeModelIters-1))		{		// Replace points in Shape with the original InShape points if the InShape-model distance is small.		// The idea is to prevent bad points from pulling the whole model off.		Vec Dist(ShapeDist(Shape, InShape));	// distances between corresponding points in Shape and InShape		int *iSortedIndices = (int *)malloc(Dist.nelems() * sizeof(int));		SortVec(iSortedIndices, Dist);		for (int i = 0; i < Shape.nrows(); i++)			{			if (Dist(i) < CONF_MinDist / pow(2, iLev))				{				int iRow = iSortedIndices[i];				Shape(iRow, VX) = InShape(iRow, VX);				Shape(iRow, VY) = InShape(iRow, VY);				}			}		free(iSortedIndices);		}#endif#if CONF_fRetainOrgB	if (iter < Model.nShapeModelIters-1)		b = OrgB;#endif	}return Shape;}//-----------------------------------------------------------------------------// Copy InShape and return it conformed to the model.// In other words, generate a model shape that is as close as possible to InShape.// InShape itself isn't changed.//// To match the model to Shape we need to find Pose and b in the following equation://// Shape = Pose * (MeanShape + EigVecs * b)		(where = actually means approx equal)//// Note: The returned shape has all the points in the model, even if InShape// has unused points (i.e. equal to 0,0)SHAPE ConformShapeToModel (Vec &b,									// io								const SHAPE &InShape, 				// in								const tAsmModel &Model, int iLev,	// in								const Vec *pWeights,				// in								bool fShapeModelFinalIter)			// in{if (Model.fFancyShapeModel)	return ConformShapeToModel_Fancy(b, InShape, Model, iLev, pWeights, fShapeModelFinalIter);else	return ConformShapeToModel_Simple(b, InShape, Model, iLev, pWeights);}//-----------------------------------------------------------------------------void PrintEigInfo (bool fgBrief, const Vec &EigVals, int nPrincipalEigs){double Total = 0;for (int i = 0; i < nPrincipalEigs; i++)	Total += EigVals(i);bprintf(fgBrief, "Fraction of shape variation %.3f Ratio of first eig to last used eig %.3f\n",	Total / EigVals.sum(), EigVals(0) / EigVals(nPrincipalEigs-1));}

⌨️ 快捷键说明

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