/external/opencv/cvaux/src/cvfacedetection.cpp
C++ | 486 lines | 325 code | 98 blank | 63 comment | 50 complexity | 5fe17c6b520cd7bbd3b6e6937f578a8c MD5 | raw file
- /*M///////////////////////////////////////////////////////////////////////////////////////
- //
- // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
- //
- // By downloading, copying, installing or using the software you agree to this license.
- // If you do not agree to this license, do not download, install,
- // copy or use the software.
- //
- //
- // Intel License Agreement
- // For Open Source Computer Vision Library
- //
- // Copyright (C) 2000, Intel Corporation, all rights reserved.
- // Third party copyrights are property of their respective owners.
- //
- // Redistribution and use in source and binary forms, with or without modification,
- // are permitted provided that the following conditions are met:
- //
- // * Redistribution's of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- //
- // * Redistribution's in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- //
- // * The name of Intel Corporation may not be used to endorse or promote products
- // derived from this software without specific prior written permission.
- //
- // This software is provided by the copyright holders and contributors "as is" and
- // any express or implied warranties, including, but not limited to, the implied
- // warranties of merchantability and fitness for a particular purpose are disclaimed.
- // In no event shall the Intel Corporation or contributors be liable for any direct,
- // indirect, incidental, special, exemplary, or consequential damages
- // (including, but not limited to, procurement of substitute goods or services;
- // loss of use, data, or profits; or business interruption) however caused
- // and on any theory of liability, whether in contract, strict liability,
- // or tort (including negligence or otherwise) arising in any way out of
- // the use of this software, even if advised of the possibility of such damage.
- //
- //M*/
- ///////////////////////////////////////////////
- //// Created by Khudyakov V.A. bober@gorodok.net
- //////////////////////////////////////////////
- // FaceDetection.cpp: implementation of the FaceDetection class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "_cvaux.h"
- #include "_cvfacedetection.h"
- int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* userdata);
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- FaceDetection::FaceDetection()
- {
- m_imgGray = NULL;
- m_imgThresh = NULL;
- m_mstgContours = NULL;
- memset(m_seqContours, 0, sizeof(CvSeq*) * MAX_LAYERS);
- m_mstgRects = NULL;
- m_seqRects = NULL;
- m_iNumLayers = 16;
- assert(m_iNumLayers <= MAX_LAYERS);
- m_pFaceList = new List();
-
- m_bBoosting = false;
- }// FaceDetection()
- FaceDetection::~FaceDetection()
- {
- if (m_imgGray)
- cvReleaseImage(&m_imgGray);
- if (m_imgThresh)
- cvReleaseImage(&m_imgThresh);
- if (m_mstgContours)
- cvReleaseMemStorage(&m_mstgContours);
- if (m_mstgRects)
- cvReleaseMemStorage(&m_mstgRects);
-
- }// ~FaceDetection()
- void FaceDetection::FindContours(IplImage* imgGray)
- {
- ReallocImage(&m_imgThresh, cvGetSize(imgGray), 1);
- if (NULL == m_imgThresh)
- return;
- //
- int iNumLayers = m_iNumLayers;
- int iMinLevel = 0, iMaxLevel = 255, iStep = 255 / iNumLayers;
- ThresholdingParam(imgGray, iNumLayers, iMinLevel, iMaxLevel, iStep);
- // init
- cvReleaseMemStorage(&m_mstgContours);
- m_mstgContours = cvCreateMemStorage();
- if (NULL == m_mstgContours)
- return;
- memset(m_seqContours, 0, sizeof(CvSeq*) * MAX_LAYERS);
- cvReleaseMemStorage(&m_mstgRects);
- m_mstgRects = cvCreateMemStorage();
- if (NULL == m_mstgRects)
- return;
- m_seqRects = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvContourRect), m_mstgRects);
- if (NULL == m_seqRects)
- return;
- // find contours
- for (int l = iMinLevel, i = 0; l < iMaxLevel; l += iStep, i++)
- {
- cvThreshold(imgGray, m_imgThresh, (double)l, (double)255, CV_THRESH_BINARY);
- if (cvFindContours(m_imgThresh, m_mstgContours, &m_seqContours[i], sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE))
- AddContours2Rect(m_seqContours[i], l, i);
- }
- // sort rects
- cvSeqSort(m_seqRects, CompareContourRect, NULL);
- }// void FaceDetection::FindContours(IplImage* imgGray)
- #define GIST_STEP 10
- #define GIST_NUM (256 / GIST_STEP)
- #define GIST_MIN 32
- void FaceDetection::ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
- {
- assert(imgGray != NULL);
- assert(imgGray->nChannels == 1);
- int i, j;
- // create gistogramm
- uchar* buffImg = (uchar*)imgGray->imageData;
- int gistImg[GIST_NUM + 1] = {0};
- for (j = 0; j < imgGray->height; j ++)
- {
- for (i = 0; i < imgGray->width; i ++)
- {
- int ind = buffImg[i] / GIST_STEP;
- gistImg[ind] ++;
- }
- buffImg += imgGray->widthStep;
- }
- // params
-
- for (i = 0; i <= GIST_NUM; i ++)
- {
- if (gistImg[i] >= GIST_MIN)
- break;
- }
-
- iMinLevel = i * GIST_STEP;
-
- for (i = GIST_NUM; i >= 0; i --)
- {
- if (gistImg[i] >= GIST_MIN)
- break;
- }
-
- iMaxLevel = i * GIST_STEP;
-
- int dLevels = iMaxLevel - iMinLevel;
- if (dLevels <= 0)
- {
- iMinLevel = 0;
- iMaxLevel = 255;
- }
- else if (dLevels <= iNumLayers)
- {
- iMinLevel = iMaxLevel - iNumLayers;
- if (iMinLevel < 0)
- {
- iMinLevel = 0;
- iMaxLevel = iNumLayers;
- }
- }
- iStep = (iMaxLevel - iMinLevel) / iNumLayers;
- }// void FaceDetection::ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
- #ifndef MAX_ERROR
- #define MAX_ERROR 0xFFFFFFFF
- #endif //MAX_ERROR
- void FaceDetection::CreateResults(CvSeq * lpSeq)
- {
-
- Face * tmp;
-
- double Max = 0;
- double CurStat = 0;
-
- FaceData tmpData;
- if (m_bBoosting)
- {
- tmp = m_pFaceList->GetData();
- tmp->CreateFace(&tmpData);
- CvFace tmpFace;
- tmpFace.MouthRect = tmpData.MouthRect;
- tmpFace.LeftEyeRect = tmpData.LeftEyeRect;
- tmpFace.RightEyeRect = tmpData.RightEyeRect;
- cvSeqPush(lpSeq,&tmpFace);
- }else
- {
- while ( (tmp = m_pFaceList->GetData()) != 0 )
- {
- CurStat = tmp->GetWeight();
- if (CurStat > Max)
- Max = CurStat;
- }
-
- while ( (tmp = m_pFaceList->GetData()) != 0 )
- {
- tmp->CreateFace(&tmpData);
- CurStat = tmp->GetWeight();
-
- if (CurStat == Max)
- {
- CvFace tmpFace;
- tmpFace.MouthRect = tmpData.MouthRect;
- tmpFace.LeftEyeRect = tmpData.LeftEyeRect;
- tmpFace.RightEyeRect = tmpData.RightEyeRect;
- cvSeqPush(lpSeq,&tmpFace);
-
- }
- }
- }
- }// void FaceDetection::DrawResult(IplImage* img)
- void FaceDetection::ResetImage()
- {
- delete m_pFaceList;
- m_pFaceList = new List();
- }//FaceDetection::ResetImage
- void FaceDetection::AddContours2Rect(CvSeq *seq, int color, int iLayer)
- {
- assert(m_mstgRects != NULL);
- assert(m_seqRects != NULL);
- CvContourRect cr;
- for (CvSeq* external = seq; external; external = external->h_next)
- {
- cr.r = cvContourBoundingRect(external, 1 );
- cr.pCenter.x = cr.r.x + cr.r.width / 2;
- cr.pCenter.y = cr.r.y + cr.r.height / 2;
- cr.iNumber = iLayer;
- cr.iType = 6;
- cr.iFlags = 0;
- cr.seqContour = external;
- cr.iContourLength = external->total;
- cr.iColor = color;
- cvSeqPush(m_seqRects, &cr);
- for (CvSeq* internal = external->v_next; internal; internal = internal->h_next)
- {
- cr.r = cvContourBoundingRect(internal, 0);
- cr.pCenter.x = cr.r.x + cr.r.width / 2;
- cr.pCenter.y = cr.r.y + cr.r.height / 2;
- cr.iNumber = iLayer;
- cr.iType = 12;
- cr.iFlags = 0;
- cr.seqContour = internal;
- cr.iContourLength = internal->total;
- cr.iColor = color;
- cvSeqPush(m_seqRects, &cr);
- }
- }
- }// void FaceDetection::AddContours2Rect(CvSeq *seq, int color, int iLayer)
- int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* /*userdata*/)
- {
- return (((CvContourRect*)el1)->pCenter.y - ((CvContourRect*)el2)->pCenter.y);
- }// int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* userdata)
- void FaceDetection::FindFace(IplImage *img)
- {
- // find all contours
- FindContours(img);
- //
- ResetImage();
- if (m_bBoosting)
- PostBoostingFindCandidats(img);
- else
- FindCandidats();
-
- }// void FaceDetection::FindFace(IplImage *img)
- void FaceDetection::FindCandidats()
- {
- bool bFound1 = false;
- MouthFaceTemplate * lpFaceTemplate1;
- RFace * lpFace1;
- bool bInvalidRect1 = false;
- CvRect * lpRect1 = NULL;
-
- for (int i = 0; i < m_seqRects->total; i++)
- {
- CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, i);
- CvRect rect = pRect->r;
- if (rect.width >= 2*rect.height)
- {
- lpFaceTemplate1 = new MouthFaceTemplate(3,rect,3*(double)rect.width/(double)4,
- 3*(double)rect.width/(double)4,
- (double)rect.width/(double)2,
- (double)rect.width/(double)2);
-
- lpFace1 = new RFace(lpFaceTemplate1);
-
- for (int j = 0; j < m_seqRects->total; j++)
- {
- CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, j);
-
- if ( !bInvalidRect1 )
- {
- lpRect1 = NULL;
- lpRect1 = new CvRect();
- *lpRect1 = pRect->r;
- }else
- {
- delete lpRect1;
- lpRect1 = new CvRect();
- *lpRect1 = pRect->r;
- }
-
-
- if ( lpFace1->isFeature(lpRect1) )
- {
- bFound1 = true;
- bInvalidRect1 = false;
- }else
- bInvalidRect1 = true;
-
- }
-
- if (bFound1)
- {
- m_pFaceList->AddElem(lpFace1);
- bFound1 = false;
- lpFace1 = NULL;
- }else
- {
- delete lpFace1;
- lpFace1 = NULL;
- }
-
- delete lpFaceTemplate1;
- }
-
- }
- }
- void FaceDetection::PostBoostingFindCandidats(IplImage * FaceImage)
- {
- BoostingFaceTemplate * lpFaceTemplate1;
- RFace * lpFace1;
- bool bInvalidRect1 = false;
- CvRect * lpRect1 = NULL;
-
- if ( ( !FaceImage->roi ) )
- lpFaceTemplate1 = new BoostingFaceTemplate(3,cvRect(0,0,FaceImage->width,FaceImage->height));
- else
- lpFaceTemplate1 = new BoostingFaceTemplate(3,cvRect(FaceImage->roi->xOffset,FaceImage->roi->yOffset,
- FaceImage->roi->width,FaceImage->roi->height));
-
- lpFace1 = new RFace(lpFaceTemplate1);
- for (int i = 0; i < m_seqRects->total; i++)
- {
- CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, i);
-
- if ( !bInvalidRect1 )
- {
- lpRect1 = NULL;
- lpRect1 = new CvRect();
- *lpRect1 = pRect->r;
- }else
- {
- delete lpRect1;
- lpRect1 = new CvRect();
- *lpRect1 = pRect->r;
- }
-
-
- if ( lpFace1->isFeature(lpRect1) )
- {
- //bFound1 = true;
- bInvalidRect1 = false;
- }else
- bInvalidRect1 = true;
-
- }
-
- m_pFaceList->AddElem(lpFace1);
-
- delete lpFaceTemplate1;
- }//void FaceDetection::PostBoostingFindCandidats(IplImage * FaceImage)
- /////////////////////////
- //class Face
- //////
- //List Class
- /////
- ListElem::ListElem()
- {
- m_pNext = this;
- m_pPrev = this;
- m_pFace = NULL;
- }///ListElem::ListElem()
- ListElem::ListElem(Face * pFace,ListElem * pHead)
- {
- m_pNext = pHead;
- m_pPrev = pHead->m_pPrev;
- pHead->m_pPrev->m_pNext = this;
- pHead->m_pPrev = this;
- m_pFace = pFace;
- }//ListElem::ListElem(Face * pFace)
- ListElem::~ListElem()
- {
- delete m_pFace;
- m_pNext->m_pPrev = m_pPrev;
- m_pPrev->m_pNext = m_pNext;
- }//ListElem::~ListElem()
- List::List()
- {
- m_pHead = new ListElem();
- m_FacesCount = 0;
- m_pCurElem = m_pHead;
- }//List::List()
- List::~List()
- {
- void * tmp;
- while((tmp = m_pHead->m_pNext->m_pFace) != 0)
- delete m_pHead->m_pNext;
- delete m_pHead;
- }//List::~List()
- int List::AddElem(Face * pFace)
- {
- new ListElem(pFace,m_pHead);
- return m_FacesCount++;
- }//List::AddElem(Face * pFace)
- Face * List::GetData()
- {
- m_pCurElem = m_pCurElem->m_pNext;
- return m_pCurElem->m_pFace;
- }//Face * List::GetData()