Home | History | Annotate | Download | only in src
      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 (at) gorodok.net
     43 //////////////////////////////////////////////
     44 
     45 #include "_cvaux.h"
     46 #include "_cvfacedetection.h"
     47 
     48 Face::Face(FaceTemplate * lpFaceTemplate)
     49 {
     50     //init number of face elements;
     51     m_lFaceFeaturesNumber = lpFaceTemplate->GetCount();
     52 
     53     //init array of numbers of foundet face elements of each type
     54     m_lplFaceFeaturesCount = new long[m_lFaceFeaturesNumber];
     55     memset(m_lplFaceFeaturesCount,0,m_lFaceFeaturesNumber*sizeof(long));
     56 
     57     //init array of ideal face features
     58     m_lpIdealFace = new FaceFeature[m_lFaceFeaturesNumber];
     59 
     60     //init array of founded features
     61     m_lppFoundedFaceFeatures = new FaceFeature*[m_lFaceFeaturesNumber];
     62 
     63     for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
     64     {
     65         m_lppFoundedFaceFeatures[i] = (new FaceFeature[3*MAX_LAYERS]);
     66     }
     67 
     68     //set start weight 0
     69     m_dWeight = 0;
     70 
     71 }//Face::Face(FaceTemplate * lpFaceTemplate)
     72 
     73 Face::~Face()
     74 {
     75     for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
     76     {
     77         delete [] (m_lppFoundedFaceFeatures[i]);
     78     }
     79     delete [] m_lppFoundedFaceFeatures;
     80 
     81 
     82     delete [] m_lplFaceFeaturesCount;
     83     delete [] m_lpIdealFace;
     84 
     85 }//Face::~Face()
     86 
     87 
     88 #define UP_SCALE    1
     89 #define DOWN_SCALE  2
     90 
     91 
     92 ////////////
     93 //class RFace(rect based face)
     94 ////////////
     95 RFace::RFace(FaceTemplate * lpFaceTemplate):Face(lpFaceTemplate)
     96 {
     97     //init ideal face
     98     FaceFeature * lpTmp = lpFaceTemplate->GetFeatures();
     99 
    100     for (int j = 0;j < m_lFaceFeaturesNumber;j ++)
    101     {
    102         CvRect * lpTmpRect = NULL;
    103         lpTmpRect = new CvRect;
    104         *lpTmpRect = *(CvRect*)lpTmp[j].GetContour();
    105 
    106         m_lpIdealFace[j].SetContour( lpTmpRect );
    107         m_lpIdealFace[j].SetWeight( lpTmp[j].GetWeight() );
    108         m_lpIdealFace[j].SetFeature( lpTmp[j].isFaceFeature() );
    109 
    110     }
    111 
    112     m_bIsGenerated = false;
    113 }//RFace::RFace(FaceTemplate * lpFaceTemplate)
    114 
    115 RFace::~RFace()
    116 {
    117 
    118 }//RFace::~RFace()
    119 
    120 inline bool RFace::isPointInRect(CvPoint p,CvRect rect)
    121 {
    122     if ( (p.x >= rect.x) && (p.y >= rect.y) && (p.x <= rect.x + rect.width) && (p.y <= rect.y + rect.height) )
    123         return true;
    124 
    125     return false;
    126 }//inline bool RFace::isPointInRect(CvPoint,CvRect rect)
    127 
    128 double RFace::GetWeight()
    129 {
    130     return m_dWeight;
    131 }//double RFace::GetWeight()
    132 
    133 
    134 bool RFace::CheckElem(void * lpCandidat,void * lpIdeal)
    135 {
    136 
    137     CvRect IdealRect = *(CvRect*)lpIdeal;
    138     CvRect Rect = *(CvRect*)lpCandidat;
    139 
    140     if (Rect.height > Rect.width)
    141         return false;
    142 
    143     long SizeIdeal = IdealRect.width*IdealRect.height;
    144     long Size = Rect.width*Rect.height;
    145 
    146     if ( (Size > SizeIdeal) || ( Size < (SizeIdeal/5) ) )
    147         return false;
    148 
    149 //  CvRect UpRect;
    150 //  CvRect DownRect;
    151 //  ResizeRect(IdealRect,&UpRect,UP_SCALE,7);
    152 //  ResizeRect(IdealRect,&DownRect,DOWN_SCALE,7);
    153 
    154     long x = Rect.x + cvRound(Rect.width/2);
    155     long y = Rect.y + cvRound(Rect.height/2);
    156 
    157     if ( isPointInRect(cvPoint(x,y),IdealRect) )
    158         return true;
    159 
    160 //  if ( isPointInRect(cvPoint(Rect.x,Rect.y),UpRect) &&
    161 //       isPointInRect(cvPoint(Rect.x + Rect.width,Rect.y + Rect.height),UpRect ) &&
    162 //       isPointInRect(cvPoint(DownRect.x,DownRect.y),Rect) &&
    163 //       isPointInRect(cvPoint(DownRect.x + DownRect.width,DownRect.y + DownRect.height),Rect) )
    164 //      return true;
    165 
    166 
    167 //  if ( isPointInRect(cvPoint(Rect.x,Rect.y),IdealRect) &&
    168 //       isPointInRect(cvPoint(Rect.x + Rect.width,Rect.y + Rect.height),IdealRect ) )
    169 //      return true;
    170 
    171     return false;
    172 }//inline bool RFace::CheckElem(CvRect rect)
    173 
    174 
    175 
    176 void RFace::CalculateError(FaceData * lpFaceData)
    177 {
    178     CvRect LeftEyeRect = lpFaceData->LeftEyeRect;
    179     CvRect RightEyeRect = lpFaceData->RightEyeRect;
    180     CvRect MouthRect = lpFaceData->MouthRect;
    181 
    182     long LeftSquare = LeftEyeRect.width*LeftEyeRect.height;
    183     long RightSquare = RightEyeRect.width*RightEyeRect.height;
    184 
    185     long dy = LeftEyeRect.y - RightEyeRect.y;
    186 
    187     long dx1 = LeftEyeRect.x + LeftEyeRect.width/2 - MouthRect.x;
    188     long dx2 = RightEyeRect.x + RightEyeRect.width/2 - MouthRect.x - MouthRect.width;
    189 
    190 
    191     lpFaceData->Error = (double)(LeftSquare - RightSquare)*(double)(LeftSquare - RightSquare)/((double)(LeftSquare + RightSquare)*(LeftSquare + RightSquare)) +
    192                         (double)(dy*dy)/((double)(LeftEyeRect.height + RightEyeRect.height)*(LeftEyeRect.height + RightEyeRect.height)) +
    193                         (double)(dx1*dx1)/((double)MouthRect.width*MouthRect.width) +
    194                         (double)(dx2*dx2)/((double)MouthRect.width*MouthRect.width);
    195 
    196 }//void RFace::CalculateError(FaceData * lpFaceData)
    197 
    198 #define MAX_ERROR 0xFFFFFFFF
    199 
    200 void  RFace::CreateFace(void * lpData)
    201 {
    202     FaceData Data;
    203 
    204     double Error = MAX_ERROR;
    205     double CurError = MAX_ERROR;
    206 
    207     FaceData * lpFaceData = (FaceData*)lpData;
    208 
    209     int im = 0;//mouth was find
    210     int jl = 0;//left eye was find
    211     int kr = 0;//right eye was find
    212 
    213     long MouthNumber = 0;
    214     long LeftEyeNumber = 0;
    215     long RightEyeNumber = 0;
    216 
    217     for (int i = 0;i < m_lplFaceFeaturesCount[0] + 1;i ++)
    218     {
    219 
    220         if ( !m_lplFaceFeaturesCount[0] )
    221             Data.MouthRect = *(CvRect*)m_lpIdealFace[0].GetContour();
    222         else
    223         {
    224             if ( i != m_lplFaceFeaturesCount[0] )
    225                 Data.MouthRect = *(CvRect*)m_lppFoundedFaceFeatures[0][i].GetContour();
    226             im = 1;
    227         }
    228 
    229 
    230         for (int j = 0;j < m_lplFaceFeaturesCount[1] + 1;j ++)
    231         {
    232 
    233             if ( !m_lplFaceFeaturesCount[1] )
    234                 Data.LeftEyeRect = *(CvRect*)m_lpIdealFace[1].GetContour();
    235             else
    236             {
    237                 if (j != m_lplFaceFeaturesCount[1] )
    238                     Data.LeftEyeRect = *(CvRect*)m_lppFoundedFaceFeatures[1][j].GetContour();
    239                 jl = 1;
    240             }
    241 
    242 
    243             for (int k = 0;k < m_lplFaceFeaturesCount[2] + 1;k ++)
    244             {
    245 
    246                 if ( !m_lplFaceFeaturesCount[2] )
    247                     Data.RightEyeRect = *(CvRect*)m_lpIdealFace[2].GetContour();
    248                 else
    249                 {
    250                     if (k != m_lplFaceFeaturesCount[2] )
    251                         Data.RightEyeRect = *(CvRect*)m_lppFoundedFaceFeatures[2][k].GetContour();
    252                     kr = 1;
    253                 }
    254 
    255                 CalculateError(&Data);
    256 
    257                 if ( (im + jl + kr) )
    258                 {
    259                     Error = Data.Error/(im + jl + kr);
    260                 }else
    261                     Error = MAX_ERROR;
    262 
    263                 if (CurError > Error)
    264                 {
    265                     CurError = Error;
    266                     MouthNumber = i;
    267                     LeftEyeNumber = j;
    268                     RightEyeNumber = k;
    269                 }
    270 
    271             }
    272 
    273 
    274         }
    275 
    276     }
    277 
    278     if ( m_lplFaceFeaturesCount[0] )
    279         lpFaceData->MouthRect = *(CvRect*)m_lppFoundedFaceFeatures[0][MouthNumber].GetContour();
    280     else
    281         lpFaceData->MouthRect = *(CvRect*)m_lpIdealFace[0].GetContour();
    282 
    283     if ( m_lplFaceFeaturesCount[1] )
    284         lpFaceData->LeftEyeRect = *(CvRect*)m_lppFoundedFaceFeatures[1][LeftEyeNumber].GetContour();
    285     else
    286         lpFaceData->LeftEyeRect = *(CvRect*)m_lpIdealFace[1].GetContour();
    287 
    288     if ( m_lplFaceFeaturesCount[2] )
    289         lpFaceData->RightEyeRect = *(CvRect*)m_lppFoundedFaceFeatures[2][RightEyeNumber].GetContour();
    290     else
    291         lpFaceData->RightEyeRect = *(CvRect*)m_lpIdealFace[2].GetContour();
    292 
    293     lpFaceData->Error = CurError;
    294 
    295 }//void * RFace::CreateFace()
    296 
    297 void RFace::Show(IplImage * Image)
    298 {
    299     for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
    300     {
    301         if (m_lplFaceFeaturesCount[i])
    302         {
    303             for (int j = 0;j < m_lplFaceFeaturesCount[i];j ++)
    304             {
    305                 CvRect rect = *(CvRect*)m_lppFoundedFaceFeatures[i][j].GetContour();
    306                 CvPoint p1 = cvPoint(rect.x,rect.y);
    307                 CvPoint p2 = cvPoint(rect.x + rect.width,rect.y + rect.height);
    308                 cvRectangle(Image,p1,p2,CV_RGB(255,0,0),1);
    309             }
    310         }
    311     }
    312 
    313 }//void RFace::Show(IplImage * Image)
    314 
    315 void RFace::ShowIdeal(IplImage* Image)
    316 {
    317     for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
    318     {
    319         CvRect Rect = *(CvRect*)m_lpIdealFace[i].GetContour();
    320         CvPoint p1 = cvPoint(Rect.x,Rect.y);
    321         CvPoint p2 = cvPoint(Rect.x + Rect.width,Rect.y + Rect.height);
    322         cvRectangle(Image,p1,p2,CV_RGB(0,0,255),1);
    323     }
    324 }//void RFace::ShowIdeal(IplImage* Image)
    325 
    326 
    327 inline void RFace::ResizeRect(CvRect Rect,CvRect * lpRect,long lDir,long lD)
    328 {
    329     if (lDir == UP_SCALE)
    330     {
    331         lpRect->x = Rect.x - lD;
    332         lpRect->y = Rect.y - lD;
    333         lpRect->width = Rect.width + 2*lD;
    334         lpRect->height = Rect.height + 2*lD;
    335     }
    336     if (lDir == DOWN_SCALE)
    337     {
    338         lpRect->x = Rect.x + lD;
    339         lpRect->y = Rect.y + lD;
    340         if (Rect.width - 2*lD >= 0)
    341         {
    342             lpRect->width = Rect.width - 2*lD;
    343         }else
    344             lpRect->width = 0;
    345 
    346         if (Rect.height - 2*lD >= 0)
    347         {
    348             lpRect->height = Rect.height - 2*lD;
    349         }else
    350             lpRect->height = 0;
    351     }
    352 
    353 }// inline void RFace::ResizeRect(CvRect * lpRect,long lDir,long lD)
    354 
    355