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 
52 class FaceFeature
53 {
54 public:
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);
64 private:
65     double m_dWeight;
66     void * m_lpContour;
67     bool m_bIsFaceFeature;
68 };//class FaceFeature
69 
70 inline void FaceFeature::SetFeature(bool bIsFeature)
71 {
72     m_bIsFaceFeature = bIsFeature;
73 }
74 
75 inline bool FaceFeature::isFaceFeature()
76 {
77     return m_bIsFaceFeature;
78 }//inline bool FaceFeature::isFaceFeature()
79 
80 inline void * FaceFeature::GetContour()
81 {
82     return m_lpContour;
83 }//inline void * FaceFeature::GetContour()
84 
85 inline double FaceFeature::GetWeight()
86 {
87     return m_dWeight;
88 }//inline long FaceFeature::GetWeight()
89 
90 inline void FaceFeature::SetContour(void * lpContour)
91 {
92     m_lpContour = lpContour;
93 }//inline void FaceFeature::SetContour(void * lpContour)
94 
95 inline void FaceFeature::SetWeight(double  dWeight)
96 {
97     m_dWeight = dWeight;
98 }//inline void FaceFeature::SetWeight(double * dWeight)
99 
100 
101 
102 class FaceTemplate
103 {
104 public:
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 
111 protected:
112     FaceFeature * m_lpFeaturesList;
113 private:
114     long m_lFeaturesCount;
115 };//class FaceTemplate
116 
117 
118 inline long FaceTemplate::GetCount()
119 {
120     return m_lFeaturesCount;
121 }//inline long FaceTemplate::GetCount()
122 
123 
124 inline FaceFeature * FaceTemplate::GetFeatures()
125 {
126     return m_lpFeaturesList;
127 }//inline FaceFeature * FaceTemplate::GetFeatures()
128 
129 ////////////
130 //class RFaceTemplate
131 ///////////
132 
133 class MouthFaceTemplate:public FaceTemplate
134 {
135 public:
136     inline MouthFaceTemplate(long lNumber,CvRect rect,double dEyeWidth,double dEyeHeight,double dDistanceBetweenEye,double dDistanceEyeAboveMouth);
137     ~MouthFaceTemplate();
138 };//class MouthFaceTemplate:public FaceTemplate
139 
140 
141 inline 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 
204 typedef 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 
216 class Face
217 {
218 public:
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;
230 protected:
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 
238 inline 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 
273 struct FaceData
274 {
275     CvRect LeftEyeRect;
276     CvRect RightEyeRect;
277     CvRect MouthRect;
278     double Error;
279 };//struct FaceData
280 
281 class RFace:public Face
282 {
283 public:
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();
291 private:
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 
299 class ListElem
300 {
301 public:
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 
310 class List
311 {
312 public:
313     List();
314     int AddElem(Face * pFace);
315     virtual ~List();
316     Face* GetData();
317         long m_FacesCount;
318 private:
319     ListElem * m_pHead;
320     ListElem * m_pCurElem;
321 };//class List
322 
323 
324 class FaceDetection
325 {
326 public:
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;}
333 protected:
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 
346 protected:
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 
355 inline 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 
375 class BoostingFaceTemplate:public FaceTemplate
376 {
377 public:
378     inline BoostingFaceTemplate(long lNumber,CvRect rect);
379     ~BoostingFaceTemplate() {};
380 };//class RFaceTemplate:public FaceTemplate
381 
382 
383 inline 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