1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
41 ///////////////////////////////////////////////
42 //// Created by Khudyakov V.A. bober@gorodok.net
43 //////////////////////////////////////////////
44 // FaceDetection.cpp: implementation of the FaceDetection class.
46 //////////////////////////////////////////////////////////////////////
48 #include "precomp.hpp"
49 #include "_facedetection.h"
52 int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* userdata);
54 //////////////////////////////////////////////////////////////////////
55 // Construction/Destruction
56 //////////////////////////////////////////////////////////////////////
58 FaceDetection::FaceDetection()
63 m_mstgContours = NULL;
64 memset(m_seqContours, 0, sizeof(CvSeq*) * MAX_LAYERS);
68 assert(m_iNumLayers <= MAX_LAYERS);
69 m_pFaceList = new FaceDetectionList();
77 FaceDetection::~FaceDetection()
80 cvReleaseImage(&m_imgGray);
83 cvReleaseImage(&m_imgThresh);
86 cvReleaseMemStorage(&m_mstgContours);
89 cvReleaseMemStorage(&m_mstgRects);
94 void FaceDetection::FindContours(IplImage* imgGray)
96 ReallocImage(&m_imgThresh, cvGetSize(imgGray), 1);
97 if (NULL == m_imgThresh)
100 int iNumLayers = m_iNumLayers;
101 int iMinLevel = 0, iMaxLevel = 255, iStep = 255 / iNumLayers;
102 ThresholdingParam(imgGray, iNumLayers, iMinLevel, iMaxLevel, iStep);
104 cvReleaseMemStorage(&m_mstgContours);
105 m_mstgContours = cvCreateMemStorage();
106 if (NULL == m_mstgContours)
108 memset(m_seqContours, 0, sizeof(CvSeq*) * MAX_LAYERS);
110 cvReleaseMemStorage(&m_mstgRects);
111 m_mstgRects = cvCreateMemStorage();
112 if (NULL == m_mstgRects)
114 m_seqRects = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvContourRect), m_mstgRects);
115 if (NULL == m_seqRects)
118 for (int l = iMinLevel, i = 0; l < iMaxLevel; l += iStep, i++)
120 cvThreshold(imgGray, m_imgThresh, (double)l, (double)255, CV_THRESH_BINARY);
121 if (cvFindContours(m_imgThresh, m_mstgContours, &m_seqContours[i], sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE))
122 AddContours2Rect(m_seqContours[i], l, i);
125 cvSeqSort(m_seqRects, CompareContourRect, NULL);
126 }// void FaceDetection::FindContours(IplImage* imgGray)
129 #define GIST_NUM (256 / GIST_STEP)
132 void FaceDetection::ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
134 assert(imgGray != NULL);
135 assert(imgGray->nChannels == 1);
138 uchar* buffImg = (uchar*)imgGray->imageData;
139 int gistImg[GIST_NUM + 1] = {0};
141 for (j = 0; j < imgGray->height; j ++)
143 for (i = 0; i < imgGray->width; i ++)
145 int ind = buffImg[i] / GIST_STEP;
148 buffImg += imgGray->widthStep;
152 for (i = 0; i <= GIST_NUM; i ++)
154 if (gistImg[i] >= GIST_MIN)
158 iMinLevel = i * GIST_STEP;
160 for (i = GIST_NUM; i >= 0; i --)
162 if (gistImg[i] >= GIST_MIN)
166 iMaxLevel = i * GIST_STEP;
168 int dLevels = iMaxLevel - iMinLevel;
174 else if (dLevels <= iNumLayers)
176 iMinLevel = iMaxLevel - iNumLayers;
180 iMaxLevel = iNumLayers;
183 iStep = (iMaxLevel - iMinLevel) / iNumLayers;
185 }// void FaceDetection::ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
188 #define MAX_ERROR 0xFFFFFFFF
192 void FaceDetection::CreateResults(CvSeq * lpSeq)
203 tmp = m_pFaceList->GetData();
204 tmp->CreateFace(&tmpData);
207 tmpFace.MouthRect = tmpData.MouthRect;
208 tmpFace.LeftEyeRect = tmpData.LeftEyeRect;
209 tmpFace.RightEyeRect = tmpData.RightEyeRect;
211 cvSeqPush(lpSeq,&tmpFace);
215 while ( (tmp = m_pFaceList->GetData()) != 0 )
217 CurStat = tmp->GetWeight();
222 while ( (tmp = m_pFaceList->GetData()) != 0 )
224 tmp->CreateFace(&tmpData);
225 CurStat = tmp->GetWeight();
230 tmpFace.MouthRect = tmpData.MouthRect;
231 tmpFace.LeftEyeRect = tmpData.LeftEyeRect;
232 tmpFace.RightEyeRect = tmpData.RightEyeRect;
233 cvSeqPush(lpSeq,&tmpFace);
239 }// void FaceDetection::DrawResult(IplImage* img)
241 void FaceDetection::ResetImage()
244 m_pFaceList = new FaceDetectionList();
246 }//FaceDetection::ResetImage
248 void FaceDetection::AddContours2Rect(CvSeq *seq, int color, int iLayer)
250 assert(m_mstgRects != NULL);
251 assert(m_seqRects != NULL);
254 for (CvSeq* external = seq; external; external = external->h_next)
256 cr.r = cvContourBoundingRect(external, 1 );
257 cr.pCenter.x = cr.r.x + cr.r.width / 2;
258 cr.pCenter.y = cr.r.y + cr.r.height / 2;
262 cr.seqContour = external;
263 cr.iContourLength = external->total;
265 cvSeqPush(m_seqRects, &cr);
266 for (CvSeq* internal = external->v_next; internal; internal = internal->h_next)
268 cr.r = cvContourBoundingRect(internal, 0);
269 cr.pCenter.x = cr.r.x + cr.r.width / 2;
270 cr.pCenter.y = cr.r.y + cr.r.height / 2;
274 cr.seqContour = internal;
275 cr.iContourLength = internal->total;
277 cvSeqPush(m_seqRects, &cr);
280 }// void FaceDetection::AddContours2Rect(CvSeq *seq, int color, int iLayer)
282 int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* /*userdata*/)
284 return (((CvContourRect*)el1)->pCenter.y - ((CvContourRect*)el2)->pCenter.y);
285 }// int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* userdata)
287 void FaceDetection::FindFace(IplImage *img)
295 PostBoostingFindCandidats(img);
299 }// void FaceDetection::FindFace(IplImage *img)
302 void FaceDetection::FindCandidats()
304 bool bFound1 = false;
305 MouthFaceTemplate * lpFaceTemplate1 = 0;
307 bool bInvalidRect1 = false;
308 CvRect * lpRect1 = NULL;
312 for (int i = 0; i < m_seqRects->total; i++)
314 CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, i);
315 CvRect rect = pRect->r;
316 if (rect.width >= 2*rect.height)
319 lpFaceTemplate1 = new MouthFaceTemplate(3,rect,3*(double)rect.width/(double)4,
320 3*(double)rect.width/(double)4,
321 (double)rect.width/(double)2,
322 (double)rect.width/(double)2);
325 lpFace1 = new RFace(lpFaceTemplate1);
327 for (int j = 0; j < m_seqRects->total; j++)
329 CvContourRect* prect = (CvContourRect*)cvGetSeqElem(m_seqRects, j);
331 if ( !bInvalidRect1 )
334 lpRect1 = new CvRect();
339 lpRect1 = new CvRect();
344 if ( lpFace1->isFeature(lpRect1) )
347 bInvalidRect1 = false;
349 bInvalidRect1 = true;
357 m_pFaceList->AddElem(lpFace1);
367 delete lpFaceTemplate1;
374 delete lpFaceTemplate1;
381 void FaceDetection::PostBoostingFindCandidats(IplImage * FaceImage)
383 BoostingFaceTemplate * lpFaceTemplate1 = 0;
385 bool bInvalidRect1 = false;
386 CvRect * lpRect1 = NULL;
390 if ( ( !FaceImage->roi ) )
391 lpFaceTemplate1 = new BoostingFaceTemplate(3,cvRect(0,0,FaceImage->width,FaceImage->height));
393 lpFaceTemplate1 = new BoostingFaceTemplate(3,cvRect(FaceImage->roi->xOffset,FaceImage->roi->yOffset,
394 FaceImage->roi->width,FaceImage->roi->height));
396 lpFace1 = new RFace(lpFaceTemplate1);
398 for (int i = 0; i < m_seqRects->total; i++)
400 CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, i);
402 if ( !bInvalidRect1 )
405 lpRect1 = new CvRect();
410 lpRect1 = new CvRect();
415 if ( lpFace1->isFeature(lpRect1) )
418 bInvalidRect1 = false;
420 bInvalidRect1 = true;
425 m_pFaceList->AddElem(lpFace1);
428 delete lpFaceTemplate1;
433 delete lpFaceTemplate1;
436 }//void FaceDetection::PostBoostingFindCandidats(IplImage * FaceImage)
438 /////////////////////////
444 //FaceDetectionList Class
446 FaceDetectionListElem::FaceDetectionListElem()
451 }///FaceDetectionListElem::FaceDetectionListElem()
453 FaceDetectionListElem::FaceDetectionListElem(Face * pFace,FaceDetectionListElem * pHead)
456 m_pPrev = pHead->m_pPrev;
457 pHead->m_pPrev->m_pNext = this;
458 pHead->m_pPrev = this;
461 }//FaceDetectionListElem::FaceDetectionListElem(Face * pFace)
465 FaceDetectionListElem::~FaceDetectionListElem()
468 m_pNext->m_pPrev = m_pPrev;
469 m_pPrev->m_pNext = m_pNext;
471 }//FaceDetectionListElem::~FaceDetectionListElem()
473 FaceDetectionList::FaceDetectionList()
475 m_pHead = new FaceDetectionListElem();
477 m_pCurElem = m_pHead;
478 }//FaceDetectionList::FaceDetectionList()
480 FaceDetectionList::~FaceDetectionList()
483 while((tmp = m_pHead->m_pNext->m_pFace) != 0)
484 delete m_pHead->m_pNext;
488 }//FaceDetectionList::~FaceDetectionList()
491 int FaceDetectionList::AddElem(Face * pFace)
493 new FaceDetectionListElem(pFace,m_pHead);
494 return m_FacesCount++;
495 }//FaceDetectionList::AddElem(Face * pFace)
497 Face * FaceDetectionList::GetData()
499 m_pCurElem = m_pCurElem->m_pNext;
500 return m_pCurElem->m_pFace;
501 }//Face * FaceDetectionList::GetData()