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