1/*M/////////////////////////////////////////////////////////////////////////////////////// 2// 3// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4// 5// By downloading, copying, installing or using the software you agree to this license. 6// If you do not agree to this license, do not download, install, 7// copy or use the software. 8// 9// 10// Intel License Agreement 11// For Open Source Computer Vision Library 12// 13// Copyright (C) 2000, Intel Corporation, all rights reserved. 14// Third party copyrights are property of their respective owners. 15// 16// Redistribution and use in source and binary forms, with or without modification, 17// are permitted provided that the following conditions are met: 18// 19// * Redistribution's of source code must retain the above copyright notice, 20// this list of conditions and the following disclaimer. 21// 22// * Redistribution's in binary form must reproduce the above copyright notice, 23// this list of conditions and the following disclaimer in the documentation 24// and/or other materials provided with the distribution. 25// 26// * The name of Intel Corporation may not be used to endorse or promote products 27// derived from this software without specific prior written permission. 28// 29// This software is provided by the copyright holders and contributors "as is" and 30// any express or implied warranties, including, but not limited to, the implied 31// warranties of merchantability and fitness for a particular purpose are disclaimed. 32// In no event shall the Intel Corporation or contributors be liable for any direct, 33// indirect, incidental, special, exemplary, or consequential damages 34// (including, but not limited to, procurement of substitute goods or services; 35// loss of use, data, or profits; or business interruption) however caused 36// and on any theory of liability, whether in contract, strict liability, 37// or tort (including negligence or otherwise) arising in any way out of 38// the use of this software, even if advised of the possibility of such damage. 39// 40//M*/ 41/////////////////////////////////////////////// 42//// Created by Khudyakov V.A. bober@gorodok.net 43// FaceDetection.h: interface for the FaceDetection class. 44// 45////////////////////////////////////////////////////////////////////// 46 47#ifndef _CVFACEDETECTION_H_ 48#define _CVFACEDETECTION_H_ 49 50#define MAX_LAYERS 64 51 52class FaceFeature 53{ 54public: 55 FaceFeature(double dWeight,void * lpContour,bool bIsFeature); 56 FaceFeature(); 57 virtual ~FaceFeature(); 58 inline bool isFaceFeature(); 59 inline void * GetContour(); 60 inline double GetWeight(); 61 inline void SetContour(void * lpContour); 62 inline void SetWeight(double dWeight); 63 inline void SetFeature(bool bIsFeature); 64private: 65 double m_dWeight; 66 void * m_lpContour; 67 bool m_bIsFaceFeature; 68};//class FaceFeature 69 70inline void FaceFeature::SetFeature(bool bIsFeature) 71{ 72 m_bIsFaceFeature = bIsFeature; 73} 74 75inline bool FaceFeature::isFaceFeature() 76{ 77 return m_bIsFaceFeature; 78}//inline bool FaceFeature::isFaceFeature() 79 80inline void * FaceFeature::GetContour() 81{ 82 return m_lpContour; 83}//inline void * FaceFeature::GetContour() 84 85inline double FaceFeature::GetWeight() 86{ 87 return m_dWeight; 88}//inline long FaceFeature::GetWeight() 89 90inline void FaceFeature::SetContour(void * lpContour) 91{ 92 m_lpContour = lpContour; 93}//inline void FaceFeature::SetContour(void * lpContour) 94 95inline void FaceFeature::SetWeight(double dWeight) 96{ 97 m_dWeight = dWeight; 98}//inline void FaceFeature::SetWeight(double * dWeight) 99 100 101 102class FaceTemplate 103{ 104public: 105 FaceTemplate(long lFeatureCount) {m_lFeaturesCount = lFeatureCount; m_lpFeaturesList = new FaceFeature[lFeatureCount];}; 106 virtual ~FaceTemplate(); 107 108 inline long GetCount(); 109 inline FaceFeature * GetFeatures(); 110 111protected: 112 FaceFeature * m_lpFeaturesList; 113private: 114 long m_lFeaturesCount; 115};//class FaceTemplate 116 117 118inline long FaceTemplate::GetCount() 119{ 120 return m_lFeaturesCount; 121}//inline long FaceTemplate::GetCount() 122 123 124inline FaceFeature * FaceTemplate::GetFeatures() 125{ 126 return m_lpFeaturesList; 127}//inline FaceFeature * FaceTemplate::GetFeatures() 128 129//////////// 130//class RFaceTemplate 131/////////// 132 133class MouthFaceTemplate:public FaceTemplate 134{ 135public: 136 inline MouthFaceTemplate(long lNumber,CvRect rect,double dEyeWidth,double dEyeHeight,double dDistanceBetweenEye,double dDistanceEyeAboveMouth); 137 ~MouthFaceTemplate(); 138};//class MouthFaceTemplate:public FaceTemplate 139 140 141inline MouthFaceTemplate::MouthFaceTemplate(long lNumber,CvRect rect,double dEyeWidth,double dEyeHeight, 142 double dDistanceBetweenEye,double dDistanceEyeAboveMouth):FaceTemplate(lNumber) 143{ 144 145 CvRect MouthRect = rect; 146 147 148 CvRect LeftEyeRect = cvRect(cvRound(rect.x - (dEyeWidth + dDistanceBetweenEye/(double)2 - (double)rect.width/(double)2)), 149 cvRound(rect.y - dDistanceEyeAboveMouth - dEyeHeight), 150 cvRound(dEyeWidth), 151 cvRound(dEyeHeight) ); 152 153 CvRect RightEyeRect = cvRect(cvRound(rect.x + (double)rect.width/(double)2 + dDistanceBetweenEye/(double)2), 154 cvRound(rect.y - dDistanceEyeAboveMouth - dEyeHeight), 155 cvRound(dEyeWidth), 156 cvRound(dEyeHeight) ); 157 158// CvRect NoseRect = cvRect(cvRound(rect.x + (double)rect.width/(double)4), 159// cvRound(rect.y - (double)rect.width/(double)2 - (double)rect.height/(double)4), 160// cvRound((double)rect.width/(double)2), 161// cvRound((double)rect.width/(double)2) ); 162/* 163 CvRect CheenRect = cvRect(rect.x,rect.y + 3*rect.height/2,rect.width,rect.height); 164 165*/ 166 167 CvRect * lpMouthRect = new CvRect(); 168 *lpMouthRect = MouthRect; 169 m_lpFeaturesList[0].SetContour(lpMouthRect); 170 m_lpFeaturesList[0].SetWeight(1); 171 m_lpFeaturesList[0].SetFeature(false); 172 173 174 CvRect * lpLeftEyeRect = new CvRect(); 175 *lpLeftEyeRect = LeftEyeRect; 176 m_lpFeaturesList[1].SetContour(lpLeftEyeRect); 177 m_lpFeaturesList[1].SetWeight(1); 178 m_lpFeaturesList[1].SetFeature(true); 179 180 CvRect * lpRightEyeRect = new CvRect(); 181 *lpRightEyeRect = RightEyeRect; 182 m_lpFeaturesList[2].SetContour(lpRightEyeRect); 183 m_lpFeaturesList[2].SetWeight(1); 184 m_lpFeaturesList[2].SetFeature(true); 185 186 187// CvRect * lpNoseRect = new CvRect(); 188// *lpNoseRect = NoseRect; 189// m_lpFeaturesList[3].SetContour(lpNoseRect); 190// m_lpFeaturesList[3].SetWeight(0); 191// m_lpFeaturesList[3].SetFeature(true); 192 193/* CvRect * lpCheenRect = new CvRect(); 194 *lpCheenRect = CheenRect; 195 m_lpFeaturesList[4].SetContour(lpCheenRect); 196 m_lpFeaturesList[4].SetWeight(1); 197 m_lpFeaturesList[4].SetFeature(false); 198 199*/ 200 201}//constructor MouthFaceTemplate(long lNumFeatures,CvRect rect,double dEyeWidth,double dEyeHeight,double dDistanceBetweenEye,double dDistanceEyeAboveMouth); 202 203 204typedef struct CvContourRect 205{ 206 int iNumber; 207 int iType; 208 int iFlags; 209 CvSeq *seqContour; 210 int iContourLength; 211 CvRect r; 212 CvPoint pCenter; 213 int iColor; 214} CvContourRect; 215 216class Face 217{ 218public: 219 Face(FaceTemplate * lpFaceTemplate); 220 virtual ~Face(); 221 222 inline bool isFeature(void * lpElem); 223 224 virtual void Show(IplImage * /*Image*/){}; 225 virtual void ShowIdeal(IplImage* /*Image*/){}; 226 227 virtual void CreateFace(void * lpData) = 0; 228 virtual bool CheckElem(void * lpCandidat,void * lpIdeal) = 0; 229 virtual double GetWeight() = 0; 230protected: 231 FaceFeature * m_lpIdealFace;//ideal face definition 232 long m_lFaceFeaturesNumber; //total number of diferent face features 233 long * m_lplFaceFeaturesCount;//number of each features fouded for this face 234 FaceFeature ** m_lppFoundedFaceFeatures;//founded features of curen face 235 double m_dWeight; 236}; 237 238inline bool Face::isFeature(void * lpElem) 239{ 240 for (int i = 0;i < m_lFaceFeaturesNumber;i ++) 241 { 242 void * lpIdeal = m_lpIdealFace[i].GetContour(); 243 244 if ( CheckElem( lpElem,lpIdeal) ) 245 { 246 if (m_lplFaceFeaturesCount[i] < 3*MAX_LAYERS) 247 { 248 double dWeight = m_lpIdealFace[i].GetWeight(); 249 bool bIsFeature = m_lpIdealFace[i].isFaceFeature(); 250 251 252 if (bIsFeature) 253 { 254 m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetWeight(dWeight); 255 m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetContour(lpElem); 256 m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetFeature(bIsFeature); 257 m_lplFaceFeaturesCount[i] ++; 258 } 259 260 m_dWeight += dWeight; 261 262 if (bIsFeature) 263 return true; 264 } 265 } 266 267 } 268 269 return false; 270}//inline bool RFace::isFeature(void * lpElem); 271 272 273struct FaceData 274{ 275 CvRect LeftEyeRect; 276 CvRect RightEyeRect; 277 CvRect MouthRect; 278 double Error; 279};//struct FaceData 280 281class RFace:public Face 282{ 283public: 284 RFace(FaceTemplate * lpFaceTemplate); 285 virtual ~RFace(); 286 virtual bool CheckElem(void * lpCandidat,void * lpIdeal); 287 virtual void CreateFace(void * lpData); 288 virtual void Show(IplImage* Image); 289 virtual void ShowIdeal(IplImage* Image); 290 virtual double GetWeight(); 291private: 292 bool isPointInRect(CvPoint p,CvRect rect); 293 bool m_bIsGenerated; 294 void ResizeRect(CvRect Rect,CvRect * lpRect,long lDir,long lD); 295 void CalculateError(FaceData * lpFaceData); 296}; 297 298 299class ListElem 300{ 301public: 302 ListElem(); 303 ListElem(Face * pFace,ListElem * pHead); 304 virtual ~ListElem(); 305 ListElem * m_pNext; 306 ListElem * m_pPrev; 307 Face * m_pFace; 308};//class ListElem 309 310class List 311{ 312public: 313 List(); 314 int AddElem(Face * pFace); 315 virtual ~List(); 316 Face* GetData(); 317 long m_FacesCount; 318private: 319 ListElem * m_pHead; 320 ListElem * m_pCurElem; 321};//class List 322 323 324class FaceDetection 325{ 326public: 327 void FindFace(IplImage* img); 328 void CreateResults(CvSeq * lpSeq); 329 FaceDetection(); 330 virtual ~FaceDetection(); 331 void SetBoosting(bool bBoosting) {m_bBoosting = bBoosting;} 332 bool isPostBoosting() {return m_bBoosting;} 333protected: 334 335 IplImage* m_imgGray; 336 IplImage* m_imgThresh; 337 int m_iNumLayers; 338 CvMemStorage* m_mstgContours; 339 CvSeq* m_seqContours[MAX_LAYERS]; 340 CvMemStorage* m_mstgRects; 341 CvSeq* m_seqRects; 342 343 bool m_bBoosting; 344 List * m_pFaceList; 345 346protected: 347 void ResetImage(); 348 void FindContours(IplImage* imgGray); 349 void AddContours2Rect(CvSeq* seq, int color, int iLayer); 350 void ThresholdingParam(IplImage* imgGray, int iNumLayers, int& iMinLevel, int& iMaxLevel, int& iStep); 351 void FindCandidats(); 352 void PostBoostingFindCandidats(IplImage * FaceImage); 353}; 354 355inline void ReallocImage(IplImage** ppImage, CvSize sz, long lChNum) 356{ 357 IplImage* pImage; 358 if( ppImage == NULL ) 359 return; 360 pImage = *ppImage; 361 if( pImage != NULL ) 362 { 363 if (pImage->width != sz.width || pImage->height != sz.height || pImage->nChannels != lChNum) 364 cvReleaseImage( &pImage ); 365 } 366 if( pImage == NULL ) 367 pImage = cvCreateImage( sz, IPL_DEPTH_8U, lChNum); 368 *ppImage = pImage; 369} 370 371//////////// 372//class RFaceTemplate 373/////////// 374 375class BoostingFaceTemplate:public FaceTemplate 376{ 377public: 378 inline BoostingFaceTemplate(long lNumber,CvRect rect); 379 ~BoostingFaceTemplate() {}; 380};//class RFaceTemplate:public FaceTemplate 381 382 383inline BoostingFaceTemplate::BoostingFaceTemplate(long lNumber,CvRect rect):FaceTemplate(lNumber) 384{ 385 long EyeWidth = rect.width/5; 386 long EyeHeight = EyeWidth; 387 388 CvRect LeftEyeRect = cvRect(rect.x + EyeWidth,rect.y + rect.height/2 - EyeHeight,EyeWidth,EyeHeight); 389 CvRect RightEyeRect = cvRect(rect.x + 3*EyeWidth,rect.y + rect.height/2 - EyeHeight,EyeWidth,EyeHeight); 390 CvRect MouthRect = cvRect(rect.x + 3*EyeWidth/2,rect.y + 3*rect.height/4 - EyeHeight/2,2*EyeWidth,EyeHeight); 391 392 CvRect * lpMouthRect = new CvRect(); 393 *lpMouthRect = MouthRect; 394 m_lpFeaturesList[0].SetContour(lpMouthRect); 395 m_lpFeaturesList[0].SetWeight(1); 396 m_lpFeaturesList[0].SetFeature(true); 397 398 CvRect * lpLeftEyeRect = new CvRect(); 399 *lpLeftEyeRect = LeftEyeRect; 400 m_lpFeaturesList[1].SetContour(lpLeftEyeRect); 401 m_lpFeaturesList[1].SetWeight(1); 402 m_lpFeaturesList[1].SetFeature(true); 403 404 CvRect * lpRightEyeRect = new CvRect(); 405 *lpRightEyeRect = RightEyeRect; 406 m_lpFeaturesList[2].SetContour(lpRightEyeRect); 407 m_lpFeaturesList[2].SetWeight(1); 408 m_lpFeaturesList[2].SetFeature(true); 409 410}//inline BoostingFaceTemplate::BoostingFaceTemplate(long lNumber,CvRect rect):FaceTemplate(lNumber) 411 412#endif // !defined(AFX_FACEDETECTION_H__55865033_D8E5_4DD5_8925_34C2285BB1BE__INCLUDED_) 413