source: level2/competencies/FacET/src/facet.cpp @ 234

Revision 74, 44.0 KB checked in by nik, 11 years ago (diff)

FacET import

Line 
1/* $Id: facet.cpp 5 2009-03-12 22:30:56Z mw $
2 * +-------------------------------------------------------------------+
3 * | This file contains parts of code from the application created for |
4 * | the Master thesis supervised by Marek Wnuk (Wroclaw University of |
5 * | Technology):  "Wykorzystanie systemu wizyjnego do rozpoznawania   |
6 * | emocji czlowieka" ("Vision system in human emotions recognition") |
7 * | by Marcin Namysl in June 2008.                                    |
8 * +-------------------------------------------------------------------+
9 *
10 * \author Marek Wnuk
11 * \date 2009.03.03
12 * \version 1.00.00
13 */
14
15/*
16    FacET is a library for detecting and parameterising face components.
17    Copyright (C) 2009  Marek Wnuk <marek.wnuk@pwr.wroc.pl>
18
19    This program is free software: you can redistribute it and/or modify
20    it under the terms of the GNU General Public License as published by
21    the Free Software Foundation, either version 3 of the License, or
22    (at your option) any later version.
23
24    This program is distributed in the hope that it will be useful,
25    but WITHOUT ANY WARRANTY; without even the implied warranty of
26    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27    GNU General Public License for more details.
28
29    You should have received a copy of the GNU General Public License
30    along with this program.  If not, see <http://www.gnu.org/licenses/>.
31*/
32
33/*! \file facet.cpp
34 *
35 * File defines the class for face features detection, parameterisation
36 * and displaying them in the image.
37 *
38*/
39
40#include "facet.h"
41
42facepar_t *Facet::currfacptr = NULL;
43
44CvMemStorage *HaarParameters::face_storage = cvCreateMemStorage(0);
45CvMemStorage *ImgProcMethods::contours_storage = cvCreateMemStorage(0);
46CvMemStorage *ImgProcMethods::storage = cvCreateMemStorage(0);
47
48/***************************** EMOTIONS ******************************/
49
50Facet::Facet() {
51
52  if (!readSettings())
53    std::cerr << "ERROR: reading the default parameters (default.cfg)\n";
54
55  mouthHaar = true;
56  noseHaar = false;
57  eyeballsHaar = true;
58}
59
60Facet::~Facet() {
61  cvDestroyAllWindows();
62  cvReleaseHaarClassifierCascade( &cascade_face );
63  cvReleaseHaarClassifierCascade( &cascade_leftEye );
64  cvReleaseHaarClassifierCascade( &cascade_rightEye );
65  cvReleaseHaarClassifierCascade( &cascade_mouth );
66  cvReleaseHaarClassifierCascade( &cascade_nose );
67  cvReleaseMemStorage( &face_storage );
68  cvReleaseMemStorage( &contours_storage );
69  cvReleaseMemStorage( &storage );
70}
71
72
73bool Facet::readSettings(string file_name)
74{
75  std::ifstream IStrm(file_name.c_str());
76 
77  string parameter = "";
78  string valu = "";
79  double value = 0;
80  char bufc[200];
81  bool ok;
82
83  void (FaceParameters::*wfun_face)(int) = 0;
84  void (HaarParameters::*wfun_haar)(double) = 0;
85  void (HaarParameters::*wfun_haar_s)(string) = 0;
86
87  cerr << "----------------------------------\n"
88       << "FacET parameters from config file:\n"
89       << "- File name: [" << file_name << "]:\n"
90       << "- Settings:\n";
91
92  while ( !IStrm.eof() && !IStrm.bad() ) {
93    if (( IStrm >> parameter).good() ) { 
94
95      if (parameter.at(0) == '#') {
96        IStrm.getline(bufc, 199);
97        IStrm.unget();
98      }
99     
100      else { // FacET parameters
101        ok = true;
102        if (!parameter.compare("EYEBROWS_RATIO"))
103          wfun_face = &FaceParameters::setEyebrowsRatio;
104        else if (!parameter.compare("LIPS_RATIO"))
105          wfun_face = &FaceParameters::setLipsRatio;
106        else if (!parameter.compare("FACE_SCALING"))
107          wfun_haar = &HaarParameters::setFaceScale;
108        else if (!parameter.compare("FACE_PATH"))
109          wfun_haar_s = &HaarParameters::readFaceCascade;
110        else if (!parameter.compare("R_EYE_PATH"))
111          wfun_haar_s = &HaarParameters::readRightEyeCascade;
112        else if (!parameter.compare("L_EYE_PATH"))
113          wfun_haar_s = &HaarParameters::readLeftEyeCascade;
114        else if (!parameter.compare("MOUTH_PATH"))
115          wfun_haar_s = &HaarParameters::readMouthCascade;
116        else if (!parameter.compare("NOSE_PATH"))
117          wfun_haar_s = &HaarParameters::readNoseCascade;
118
119        else { cerr << ""; ok = false; }
120       
121        if( ok ) {
122          if ( (IStrm >> value).good() ){
123            if (wfun_haar) (this->*wfun_haar)(static_cast<double>(value));
124            else if (wfun_face) (this->*wfun_face)(static_cast<int>(value));
125            cerr << "  " << parameter << " " << value << endl;
126            wfun_haar = NULL; wfun_face = NULL;
127          }
128          else {
129            IStrm.clear(); IStrm.ignore(); IStrm.unget();
130            if ( (IStrm >> valu).good() ){
131              if (wfun_haar_s) (this->*wfun_haar_s)(valu);
132           
133              cerr << "  " << parameter << " " << valu << endl;
134              wfun_haar_s = NULL;
135            }
136            else {IStrm.clear(); IStrm.ignore(); IStrm.unget();}
137          }
138        }
139        else { wfun_haar = NULL; wfun_face = NULL; wfun_haar_s = NULL; }
140      }
141    }
142    else IStrm.clear(); IStrm.ignore(); IStrm.unget();
143  }
144  cerr << "----------------------------------\n" ;
145  return true;
146}
147
148/*! Returns the sequence with the detected faces */
149CvSeq *Facet::faceDetectHaar(IplImage *src)
150{
151  if( !cascade_face ) {
152    cerr << "ERROR: Loading the face cascade file failed\n";
153    return NULL;
154  }
155 
156  IplImage* gray = cvCreateImage(cvSize(src->width,src->height), 8, 1 );
157  IplImage* small_img =
158    cvCreateImage(cvSize(cvRound (src->width/face_detection_scale),
159                         cvRound (src->height/face_detection_scale)), 8, 1);
160 
161  cvCvtColor( src, gray, CV_BGR2GRAY );
162  cvResize( gray, small_img, CV_INTER_LINEAR );
163  cvEqualizeHist( small_img, small_img );
164 
165  cvClearMemStorage( face_storage );
166 
167  CvSeq *faces;
168 
169  if( cascade_face ) {
170    faces = cvHaarDetectObjects(small_img, cascade_face, face_storage, 1.1,
171                                3, CV_HAAR_DO_CANNY_PRUNING, cvSize(30, 30));
172    cvReleaseImage( &gray );
173    cvReleaseImage( &small_img );
174   
175    return faces;
176  }
177  else {
178    cvReleaseImage( &gray );
179    cvReleaseImage( &small_img );
180   
181    return NULL;
182  }
183}
184
185void Facet::detectFeat(IplImage *src, IplImage *dst)
186{
187  CvSeq *faces = faceDetectHaar(src);
188  /*
189    faceDetectHue(src,true,true);
190  */
191  if ( !faces ) return;
192  if ( !faces->total) return;
193 
194 
195 
196  for(int i = 0; i < (faces ? faces->total : 0); i++ )
197    {
198     
199      currfacptr = new facepar_t;
200     
201      CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
202     
203      // face rectangle scaling (for Haar-based method)
204      face.p1.x = cvRound(r->x*(face_detection_scale));
205      face.p2.x = cvRound((r->x+r->width)*(face_detection_scale));
206      face.p1.y = cvRound(r->y*(face_detection_scale));
207      face.p2.y = cvRound((r->y+r->height)*(face_detection_scale));
208     
209     
210      CvRect faceRectangle = cvRect(face.p1.x,face.p1.y,face.p2.x-face.p1.x,
211                                    face.p2.y-face.p1.y);
212     
213      cvSetImageROI(src, faceRectangle);
214      findFaceRegions(src, face, !mouthHaar, !eyeballsHaar);
215      cvResetImageROI(src);
216     
217      checkEyesSize();
218     
219      cvSetImageROI(src, cvRect(face.p1.x + face.left_eye.p1.x,
220                                face.p1.y + face.left_eye.p1.y,
221                                face.left_eye.p2.x - face.left_eye.p1.x,
222                                face.left_eye.p2.y - face.left_eye.p1.y));
223      if (eyeballsHaar) detectLeftEyeballHaar(src);
224      cvResetImageROI(src);
225      cvSetImageROI(src, cvRect(face.p1.x + face.right_eye.p1.x,
226                                face.p1.y + face.right_eye.p1.y,
227                                face.right_eye.p2.x - face.right_eye.p1.x,
228                                face.right_eye.p2.y - face.right_eye.p1.y));
229      if (eyeballsHaar) detectRightEyeballHaar(src);
230      cvResetImageROI(src);
231//      cvResetImageROI(src);
232     
233      if (mouthHaar) {
234        cvSetImageROI(src, cvRect(face.p1.x, face.p1.y +
235                                  cvRound(2*faceRectangle.height/3), //2,3
236                                  faceRectangle.width,
237                                  3*faceRectangle.height/7)); // 3,7
238        detectMouthHaar(src);
239        cvResetImageROI(src);
240      }
241     
242      if (noseHaar) {
243        cvSetImageROI(src, cvRect(face.p1.x, face.p1.y +
244                                  faceRectangle.height/2,
245                                  faceRectangle.width,
246                                  1*faceRectangle.height/2));
247        detectNoseHaar(src);
248        cvResetImageROI(src);
249      }
250     
251      checkMouthSize();
252      checkNoseSize();
253      checkEyeballsSize();
254     
255      calcFaceDeclination();
256     
257     
258      // left eyebrow transform
259      bitset<4> flaga = 8;
260      cvSetImageROI(src, cvRect(face.p1.x + face.left_eye.p1.x,
261                                face.p1.y + face.left_eye.p1.y,
262                                face.left_eye.p2.x - face.left_eye.p1.x,
263                                face.left_eye.p2.y - face.left_eye.p1.y));
264      detectEyebrow(src, face.left_eye, face.left_iris, face.left_brow,flaga);
265      cvResetImageROI(src);
266     
267      cvSetImageROI(src,cvRect(face.p1.x + face.left_iris.p1.x,
268                               face.p1.y + face.left_iris.p1.y -
269                               cvRound((face.left_iris.p2.y -
270                                        face.left_iris.p1.y)/3),
271                               face.left_iris.p2.x-face.left_iris.p1.x,
272                               face.left_iris.p2.y-face.left_iris.p1.y+
273                               cvRound(2*(face.left_iris.p2.y -
274                                          face.left_iris.p1.y)/3)));
275     
276     
277      currfacptr->LEyOpn = detectEyelids(src, face.left_iris, face.left_lid);   
278      cvResetImageROI(src);
279     
280      currfacptr->LEbHgt = calcLeftEyebrowHeight();
281     
282      // right eyebrow transform
283      flaga = 4;
284      cvSetImageROI(src, cvRect(face.p1.x + face.right_eye.p1.x,
285                                face.p1.y + face.right_eye.p1.y,
286                                face.right_eye.p2.x-face.right_eye.p1.x,
287                                face.right_eye.p2.y-face.right_eye.p1.y));
288     
289     
290      detectEyebrow(src,face.right_eye,face.right_iris,face.right_brow,flaga);
291      cvResetImageROI(src);
292
293      cvSetImageROI(src,cvRect(face.p1.x + face.right_iris.p1.x,
294                               face.p1.y + face.right_iris.p1.y -
295                               cvRound((face.right_iris.p2.y -
296                                        face.right_iris.p1.y)/3),
297                               face.right_iris.p2.x-face.right_iris.p1.x,
298                               face.right_iris.p2.y-face.right_iris.p1.y+
299                               cvRound(2*(face.right_iris.p2.y -
300                                          face.right_iris.p1.y)/3)));
301     
302      currfacptr->REyOpn = detectEyelids(src, face.right_iris, face.right_lid);
303      cvResetImageROI(src);
304//      cvResetImageROI(src);
305      currfacptr->REbHgt = calcRightEyebrowHeight();
306
307      cvSetImageROI(src, cvRect(face.p1.x + face.mouth.p1.x,
308                                face.p1.y + face.mouth.p1.y,
309                                face.mouth.p2.x - face.mouth.p1.x,
310                                face.mouth.p2.y - face.mouth.p1.y));
311
312   
313      CvSeq *lips = 0;
314      detectLips(src, face.lip, lips);
315      cvResetImageROI(src);
316     
317      list<CvPoint> wrinklesList;
318      int forehead_y = min(face.left_brow.p2.y, face.right_brow.p2.y)/3;
319      if (forehead_y <= 0) forehead_y = cvRound((face.p2.y-face.p1.y)/3);
320      face.forehead.p1 = cvPoint((face.p2.x-face.p1.x)/4, forehead_y);
321      face.forehead.p2 = cvPoint(face.forehead.p1.x +
322                                 (face.p2.x-face.p1.x)/2,
323                                 face.forehead.p1.y + 2*forehead_y);
324     
325      checkForeheadSize();
326     
327      cvSetImageROI(src, cvRect(face.p1.x + face.forehead.p1.x,
328                                face.p1.y + face.forehead.p1.y,
329                                (face.p2.x-face.p1.x)/2, 2*forehead_y));
330     
331      detectForehead(src, wrinklesList);
332      cvResetImageROI(src);
333     
334      if (!noseHaar) {
335        face.nose.p1 = cvPoint(face.mouth.p1.x, face.left_eye.p2.y);
336        face.nose.p2 = cvPoint(face.mouth.p2.x, face.mouth.p1.y);
337        checkNoseSize();
338      }
339     
340      cvSetImageROI(src, cvRect(face.p1.x + face.nose.p1.x,
341                                face.p1.y + face.nose.p1.y,
342                                face.nose.p2.x - face.nose.p1.x,
343                                face.nose.p2.y - face.nose.p1.y));
344
345      detectNose(src, face.nose);
346      cvResetImageROI(src);
347
348      cvSetImageROI(src, cvRect(face.lip.p1.x, face.lip.p1.y,
349                                face.lip.p2.x - face.lip.p1.x,
350                                face.lip.p2.y - face.lip.p1.y));
351
352      checkLipsSize();
353
354      detectTeeth(src);
355      cvResetImageROI(src);
356         
357      drawFeatures(dst, wrinklesList, lips);
358     
359      facesList.push_back(*currfacptr);
360      delete currfacptr;
361    }
362}
363
364double Facet::calcFaceDeclination()
365{
366  CvPoint p1 = cvPoint(cvRound((face.left_iris.p2.x - face.left_iris.p1.x)*0.5)
367                       + face.left_iris.p1.x,
368                       cvRound((face.left_iris.p2.y - face.left_iris.p1.y)*0.5)
369                       + face.left_iris.p1.y);
370 
371  CvPoint p2 = cvPoint(cvRound((face.right_iris.p2.x-face.right_iris.p1.x)*0.5)
372                       + face.right_iris.p1.x,
373                       cvRound((face.right_iris.p2.y-face.right_iris.p1.y)*0.5)
374                       + face.right_iris.p1.y);
375 
376  double A, B, C;
377
378  drawStrLine(p1, p2, A, B, C);
379 
380  double param = rad2deg(calcAngleOX(-A, B));
381       
382  currfacptr->roix = face.p1.x;
383  currfacptr->roiy = face.p1.y;
384  currfacptr->angle = param;
385  return param;
386}
387
388
389void Facet::checkSize(CvPoint &p1, CvPoint &p2)
390{
391  if (p1.x > p2.x) {
392    int tmp = 0;
393    tmp = p1.x;
394    p1.x = p2.x;
395    p2.x = tmp;
396  }
397  else if (p1.x == p2.x)
398    p2.x += 1;
399 
400  if (p1.y > p2.y) {
401    int tmp = 0;
402    tmp = p1.y;
403    p1.y = p2.y;
404    p2.y = tmp;
405  }
406  else if (p1.y == p2.y)
407    p2.y += 1;
408}
409
410
411void Facet::checkEyesSize()
412{
413  checkSize(face.left_eye.p1, face.left_eye.p2);
414  checkSize(face.right_eye.p1, face.right_eye.p2);
415}
416
417void Facet::checkEyeballsSize()
418{
419  checkSize(face.left_iris.p1, face.left_iris.p2);
420  checkSize(face.right_iris.p1, face.right_iris.p2);
421}
422
423void Facet::checkMouthSize()
424{
425  checkSize(face.mouth.p1, face.mouth.p2);
426}
427
428void Facet::checkLipsSize()
429{
430  checkSize(face.lip.p1, face.lip.p2);
431}
432
433void Facet::checkNoseSize()
434{
435  checkSize(face.nose.p1, face.nose.p2);
436}
437
438void Facet::checkForeheadSize()
439{
440  checkSize(face.forehead.p1, face.forehead.p2);
441}
442
443int Facet::calcRightEyebrowHeight()
444{
445  return (face.right_iris.p1.y+(face.right_iris.p2.y-face.right_iris.p1.y)/2 -
446          face.right_brow.p2.y)*100/(face.right_eye.p2.y-face.right_eye.p1.y);
447}     
448
449int Facet::calcLeftEyebrowHeight()
450{
451  return (face.left_iris.p1.y + (face.left_iris.p2.y - face.left_iris.p1.y)/2 -
452          face.left_brow.p2.y) * 100/(face.left_eye.p2.y-face.left_eye.p1.y);
453}
454
455void Facet::detectLeftEyeballHaar(IplImage *src){
456
457  detectObjectHaar(src, cascade_leftEye, face.left_iris,.6,1.2,5);
458  face.left_iris.p1.x += face.left_eye.p1.x;
459  face.left_iris.p1.y += face.left_eye.p1.y;
460  face.left_iris.p2.x += face.left_eye.p1.x;
461  face.left_iris.p2.y += face.left_eye.p1.y;
462}
463
464void Facet::detectRightEyeballHaar(IplImage *src){
465  detectObjectHaar(src, cascade_rightEye, face.right_iris,.6,1.2,5);
466  face.right_iris.p1.x += face.right_eye.p1.x;
467  face.right_iris.p1.y += face.right_eye.p1.y;
468  face.right_iris.p2.x += face.right_eye.p1.x;
469  face.right_iris.p2.y += face.right_eye.p1.y;
470}
471
472void Facet::detectNoseHaar(IplImage *src)
473{     
474  detectObjectHaar(src, cascade_nose, face.nose, .9, 1.1, 2);
475     
476  face.nose.p1.y += cvRound((face.p2.y-face.p1.y)/3);
477  face.nose.p2.y += cvRound((face.p2.y-face.p1.y)/3);
478}
479
480void Facet::detectMouthHaar(IplImage *src)
481{
482  detectObjectHaar(src, cascade_mouth, face.mouth, 1.2, 1.1, 5);
483       
484  face.mouth.p1.y += cvRound(2*(face.p2.y-face.p1.y)/3);
485  face.mouth.p2.y += cvRound(2*(face.p2.y-face.p1.y)/3);
486}
487
488
489CvRect Facet::findMouthRectangle(CvSeq *contour)
490{
491  CvRect b_rect = cvRect(0,0,1,1);
492  CvRect b_rect_small = cvRect(0,0,1,1);
493  CvRect b_rect_max = cvRect(0,0,1,1);
494 
495  double outer_area = 0;
496  double small_area = 0;
497  double max_area = 0;
498 
499  for( ; contour != 0; contour = contour->h_next ){
500    CvSeqReader reader;
501    cvStartReadSeq( contour, &reader, 0 );
502   
503    outer_area =  fabs(cvContourArea(contour, CV_WHOLE_SEQ ));
504   
505    if (outer_area > max_area){
506      if (small_area > outer_area/6){
507        b_rect_small = b_rect;
508        small_area = max_area;
509      }
510      max_area = outer_area;
511      b_rect = cvContourBoundingRect(contour, 0);                 
512    }
513    else if ( (max_area>0) & (max_area/6 < outer_area) &
514              (outer_area < max_area) ) {
515      b_rect_small = cvContourBoundingRect(contour, 0);
516      small_area = outer_area;
517    }
518  }
519  if ( (b_rect_small.x > 0) && (b_rect_small.y > 0) ) {
520    b_rect_max = cvMaxRect( &b_rect, &b_rect_small );
521    return b_rect_max;
522  }
523  else return b_rect;
524}
525
526
527void Facet::drawFeatures(IplImage *dst, list<CvPoint> listOfLines,
528                            CvSeq *lips)
529{
530  CvPoint pt1 = face.p1;
531  CvPoint pt2 = face.p2;
532 
533  int pt_size = 2; // size of points
534 
535  CvScalar inner_rect_color = CV_RGB(255,0,0);
536  CvScalar outer_rect_color = CV_RGB(255,255,0);
537  CvScalar second_lip_color = CV_RGB(255,0,255);
538  CvScalar b_rect_max_color = CV_RGB(255,255,0);
539 
540  // face region rectangle
541  cvRectangle(dst, pt1, pt2, CV_RGB(255,0,0),pt_size+1,8);
542 
543  // wrinkles
544  for (list<CvPoint>::iterator iter=listOfLines.begin();
545       iter != listOfLines.end(); ++iter){
546    CvPoint p1 = *iter;
547    CvPoint p2 = *(++iter);
548    p1.x += face.p1.x + face.forehead.p1.x;
549    p1.y += face.p1.y + face.forehead.p1.y;
550    p2.x += face.p1.x + face.forehead.p1.x;
551    p2.y += face.p1.y + face.forehead.p1.y;
552
553    cvLine(dst,p1,p2,CV_RGB(255,0,0),1,8);
554  }
555 
556  for( ; lips != 0; lips = lips->h_next ){
557    CvPoint pt_old = cvPoint(0,0);
558    CvPoint pt = cvPoint(0,0);
559    CvSeqReader reader;
560    cvStartReadSeq( lips, &reader, 0 );
561   
562    for( int i = 0; i < lips->total; i++ ){
563      CV_READ_SEQ_ELEM( pt, reader );
564     
565      CvPoint p1 = cvPoint(pt1.x + face.mouth.p1.x + pt.x,
566                           pt1.y + face.mouth.p1.y + pt.y);
567      CvPoint p2 = cvPoint(pt1.x + face.mouth.p1.x + pt_old.x,
568                           pt1.y + face.mouth.p1.y + pt_old.y);
569     
570      if (i>0) cvLine(dst, p1, p2, CV_RGB(0,255,0), pt_size-1, 8);
571      cvLine(dst, p1, p1, CV_RGB(0,0,255), pt_size-1, 8);
572     
573      pt_old = pt;
574    }
575  }
576 
577  // eyelids boundary drawing
578  cvLine(dst,
579         cvPoint(pt1.x+face.left_lid.p1.x, pt1.y+face.left_lid.p1.y),
580         cvPoint(pt1.x+face.left_lid.p2.x, pt1.y+face.left_lid.p2.y),
581         CV_RGB(255,0,0), pt_size, 4);
582 
583  cvLine(dst,
584         cvPoint(pt1.x+face.left_lid.p3.x, pt1.y+face.left_lid.p3.y),
585         cvPoint(pt1.x+face.left_lid.p4.x, pt1.y+face.left_lid.p4.y),
586         CV_RGB(255,0,0), pt_size, 4);
587 
588  cvLine(dst,
589         cvPoint(pt1.x+face.right_lid.p1.x, pt1.y+face.right_lid.p1.y),
590         cvPoint(pt1.x+face.right_lid.p2.x, pt1.y+face.right_lid.p2.y),
591         CV_RGB(255,0,0), pt_size, 4);
592
593  cvLine(dst,
594         cvPoint(pt1.x+face.right_lid.p3.x, pt1.y+face.right_lid.p3.y),
595         cvPoint(pt1.x+face.right_lid.p4.x, pt1.y+face.right_lid.p4.y),
596         CV_RGB(255,0,0), pt_size, 4);
597
598  // nostrils points
599  cvLine(dst,cvPoint(face.nose.p3.x+pt1.x, face.nose.p3.y+pt1.y),
600         cvPoint(face.nose.p3.x+pt1.x, face.nose.p3.y+pt1.y),
601         CV_RGB(0,0,255),pt_size+1,8);
602 
603  cvLine(dst,cvPoint(face.nose.p4.x+pt1.x, face.nose.p4.y+pt1.y),
604         cvPoint(face.nose.p4.x+pt1.x, face.nose.p4.y+pt1.y),
605         CV_RGB(0,0,255),pt_size+1,8);
606 
607  cvLine(dst,cvPoint(face.nose.p3.x+pt1.x, face.nose.p3.y+pt1.y),
608         cvPoint(face.nose.p4.x+pt1.x, face.nose.p4.y+pt1.y),
609         CV_RGB(0,255,0),pt_size,8);
610 
611  // mouth region rectangle
612  cvRectangle(dst,cvPoint(face.lip.p1.x, face.lip.p1.y),
613              cvPoint(face.lip.p2.x, face.lip.p2.y),
614              outer_rect_color,pt_size-1,8);     
615 
616  // lips corners
617  cvLine(dst, face.lip.p3, face.lip.p3, CV_RGB(255,0,0), pt_size+5, 8);
618  cvLine(dst, face.lip.p4, face.lip.p4, CV_RGB(255,0,0), pt_size+5, 8);
619 
620  // eyes rectangles
621  cvRectangle(dst,
622              cvPoint(face.left_eye.p1.x+pt1.x,
623                      face.left_eye.p1.y+pt1.y),
624              cvPoint(face.left_eye.p2.x+pt1.x,
625                      face.left_eye.p2.y+pt1.y),
626              CV_RGB(0,255,0),pt_size,8);
627 
628  cvRectangle(dst,
629              cvPoint(face.right_eye.p1.x+pt1.x,
630                      face.right_eye.p1.y+pt1.y),
631              cvPoint(face.right_eye.p2.x+pt1.x,
632                      face.right_eye.p2.y+pt1.y),
633              CV_RGB(0,255,0),pt_size,8);
634 
635  // mouth rectangle
636  cvRectangle(dst,cvPoint(face.mouth.p1.x+pt1.x,face.mouth.p1.y+pt1.y),
637              cvPoint(face.mouth.p2.x+pt1.x,face.mouth.p2.y+pt1.y),
638              CV_RGB(0,0,255),pt_size,8);
639 
640 
641  // nose rectangle
642  cvRectangle(dst,
643              cvPoint(face.nose.p1.x+pt1.x, face.nose.p1.y+pt1.y),
644              cvPoint(face.nose.p2.x+pt1.x, face.nose.p2.y+pt1.y),
645              CV_RGB(255,0,0),pt_size,8);
646 
647  // forehead rectangle
648  cvRectangle(dst,
649              cvPoint(face.forehead.p1.x+pt1.x,
650                      face.forehead.p1.y+pt1.y),
651              cvPoint(face.forehead.p2.x+pt1.x,
652                      face.forehead.p2.y+pt1.y),
653              CV_RGB(255,255,0),pt_size,8);
654 
655  // left eyebrow lines
656 
657  cvLine(dst,
658         cvPoint(pt1.x+face.left_brow.p1.x,
659                 pt1.y+face.left_brow.p1.y),
660         cvPoint(pt1.x+face.left_brow.p2.x,
661                 pt1.y+face.left_brow.p2.y),
662         CV_RGB(0,200,255),pt_size+1,8);
663 
664  cvLine(dst,
665         cvPoint(pt1.x+face.left_brow.p2.x,
666                 pt1.y+face.left_brow.p2.y),
667         cvPoint(pt1.x+face.left_brow.p3.x,
668                 pt1.y+face.left_brow.p3.y),
669         CV_RGB(0,200,255),pt_size+1,8);
670 
671  cvLine(dst,
672         cvPoint(pt1.x+face.left_brow.p3.x,
673                 pt1.y+face.left_brow.p3.y),
674         cvPoint(pt1.x+face.left_brow.p3.x,
675                 pt1.y+face.left_brow.p3.y),
676         CV_RGB(255,255,0),pt_size+1,8);
677  cvLine(dst,
678         cvPoint(pt1.x+face.left_brow.p2.x,
679                 pt1.y+face.left_brow.p2.y),
680         cvPoint(pt1.x+face.left_brow.p2.x,
681                 pt1.y+face.left_brow.p2.y),
682         CV_RGB(255,255,0),pt_size+1,8);
683 
684  cvLine(dst,
685         cvPoint(pt1.x+face.left_brow.p1.x,
686                 pt1.y+face.left_brow.p1.y),
687         cvPoint(pt1.x+face.left_brow.p1.x,
688                 pt1.y+face.left_brow.p1.y),
689         CV_RGB(255,255,0),pt_size+1,8);
690 
691  // right eyebrow lines
692 
693  cvLine(dst,
694         cvPoint(pt1.x+face.right_brow.p1.x,
695                 pt1.y+face.right_brow.p1.y),
696         cvPoint(pt1.x+face.right_brow.p2.x,
697                 pt1.y+face.right_brow.p2.y),
698         CV_RGB(0,200,255),pt_size+1,8);
699 
700  cvLine(dst,
701         cvPoint(pt1.x+face.right_brow.p2.x,
702                 pt1.y+face.right_brow.p2.y),
703         cvPoint(pt1.x+face.right_brow.p3.x,
704                 pt1.y+face.right_brow.p3.y),
705         CV_RGB(0,200,255),pt_size+1,8);
706 
707  cvLine(dst,
708         cvPoint(pt1.x+face.right_brow.p3.x,
709                 pt1.y+face.right_brow.p3.y),
710         cvPoint(pt1.x+face.right_brow.p3.x,
711                 pt1.y+face.right_brow.p3.y),
712         CV_RGB(255,255,0),pt_size+1,8);
713  cvLine(dst,
714         cvPoint(pt1.x+face.right_brow.p2.x,
715                 pt1.y+face.right_brow.p2.y),
716         cvPoint(pt1.x+face.right_brow.p2.x,
717                 pt1.y+face.right_brow.p2.y),
718         CV_RGB(255,255,0),pt_size+1,8);
719 
720  cvLine(dst,
721         cvPoint(pt1.x+face.right_brow.p1.x,
722                 pt1.y+face.right_brow.p1.y),
723         cvPoint(pt1.x+face.right_brow.p1.x,
724                 pt1.y+face.right_brow.p1.y),
725         CV_RGB(255,255,0),pt_size+1,8);
726         
727  // eye pupil rectangles
728  cvRectangle(dst,
729              cvPoint(pt1.x+face.left_iris.p1.x,
730                      pt1.y+face.left_iris.p1.y),
731              cvPoint(pt1.x+face.left_iris.p2.x,
732                      pt1.y+face.left_iris.p2.y),
733              CV_RGB(255,255,0),pt_size-1,8);
734  cvRectangle(dst,
735              cvPoint(pt1.x+face.right_iris.p1.x,
736                      pt1.y+face.right_iris.p1.y),
737              cvPoint(pt1.x+face.right_iris.p2.x,
738                      pt1.y+face.right_iris.p2.y),
739              CV_RGB(255,255,0),pt_size-1,8);
740 
741}
742
743
744/*! Function for nose detection
745 *
746 *
747 * - maybe gradient projection will work fine?
748 */
749void Facet::detectNose(IplImage *src, FaceComponent &nose)
750{
751  IplImage *nose_img = cvCreateImage(cvGetSize(src), 8, src->nChannels);
752  cvCopy(src, nose_img);
753
754  IplImage *gray = cvCreateImage(cvGetSize(nose_img),8,1);
755  IplImage *grad = cvCreateImage(cvGetSize(nose_img),8,1);
756  IplImage *tmp = cvCreateImage(cvGetSize(nose_img),8,1);
757
758  for (int i = 0; i < 1; i++) cvSmooth(nose_img, nose_img, CV_MEDIAN, 3, 3);
759  cvCvtColor(nose_img, gray,CV_RGB2GRAY);
760
761  IplConvKernel* element =
762    cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_ELLIPSE);
763 
764  cvMorphologyEx(gray, grad, tmp, element, CV_MOP_GRADIENT, 1);
765
766  cvReleaseStructuringElement( &element );
767
768  stretchHistogram(grad, grad);
769 
770  int* ver_val = new int[grad->width];  //CHANGE GC
771  int* hor_val = new int[grad->height];
772  // int ver_val[grad->width];   
773  // int hor_val[grad->height];
774 
775  //CvMat *mat_grad = cvCreateMat(grad->height, grad->width, CV_8UC1);
776  CvMat mat_grad;
777 
778  cvGetMat(grad, &mat_grad);
779 
780  counting(&mat_grad,ver_val,PROJ_VERTICAL,CNT_MODE_NORMAL,0,gray->height);
781  counting(&mat_grad,hor_val,PROJ_HORIZONTAL,CNT_MODE_NORMAL,0,gray->width);
782 
783  int sum = 0;
784  for (int i=0; i<gray->width; i++){
785    sum += ver_val[i];
786  }
787  int average = cvRound(sum/(gray->width));
788  average = cvRound(average*1.2);
789 
790  bool startup = true;
791 
792  int max_h = 0;
793  int hor_pos =0 , ver_pos_l = 0, ver_pos_r = 0;
794 
795  int range = 0;
796 
797  for (int i=0; i<gray->width; i++){
798    if (startup & (range >= 2)){
799      startup = false;
800      ver_pos_l = i - range;
801    }
802    else if (!startup && (range >= 2)) {
803      ver_pos_r = i;
804    }
805    if (ver_val[i]>average){
806      ++range;
807    }
808    else range = 0;
809  }
810 
811  for (int i=0; i<gray->height; i++){
812    if (hor_val[i]>max_h){
813      max_h=hor_val[i];
814      hor_pos=i;
815    }
816  }
817 
818  nose.p3 = cvPoint(face.nose.p1.x + ver_pos_l, face.nose.p1.y + hor_pos);
819  nose.p4 = cvPoint(face.nose.p1.x + ver_pos_r, face.nose.p1.y + hor_pos);
820 
821  float roz_noz = (ver_pos_r-ver_pos_l)*100.0/face.width;
822
823  currfacptr->Nstrls = roz_noz;
824  cvReleaseImage( &nose_img );
825  cvReleaseImage( &gray );
826  cvReleaseImage( &grad );
827  cvReleaseImage( &tmp );
828  //  cvReleaseMat( &mat_grad );
829
830  delete [] ver_val;    //CHANGE delete memory GC
831  delete [] hor_val;
832
833}
834
835
836/*! Function for the forehead detection with wrinkles in its central part
837 *
838 * it's better to resize the forehead to learn the wrinkles size
839 *
840 * check how the wrinkles appear in different colour spaces
841 *
842 * test the adaptive threshold
843 *
844 * Multiple sobel - acceptable results up to the 2nd derivative
845 * Adaptive threshold - poor results
846 *
847 */
848
849void Facet::detectForehead(IplImage *src, list<CvPoint> &linesList)
850{
851  IplImage *gray = cvCreateImage(cvGetSize(src),8,1);
852  IplImage *sobel = cvCreateImage(cvGetSize(src),8,1);
853 
854  cvCvtColor(src, gray, CV_RGB2GRAY);
855  for (int i = 0; i < 5; i++)  cvSmooth(gray, gray,CV_MEDIAN,3,3);
856
857  cvSobel(gray, sobel,0,1,3);
858  cvSobel(sobel, sobel,0,1,3);
859
860  int wrinkles_counter = doHoughTransform(sobel, linesList);
861
862  currfacptr->Wrnkls = wrinkles_counter;
863
864  cvReleaseImage( &gray );
865  cvReleaseImage( &sobel );
866}
867
868
869/*! Function for teeth detection in the mouth area
870 *
871 */
872void Facet::detectTeeth(IplImage *src)
873{
874  IplImage *scale = cvCreateImage(cvSize(150,100), 8, 3);
875  IplImage *gray = cvCreateImage(cvGetSize(scale), 8, 1);
876  IplImage *binary = cvCreateImage(cvGetSize(scale), 8, 1);
877  cvResize(src,scale);
878  cvCvtColor(scale, gray, CV_RGB2GRAY);
879 
880  for (int i = 0; i < 1; i++) cvSmooth(gray,gray,CV_MEDIAN ,3,1,1); 
881  cvNot(gray,gray);
882 
883  int average = cvRound(cvAvg(gray).val[0]);
884   
885  hysteresisThresholding(gray, binary, cvRound(0.9*average),
886                     cvRound(average*1.4));
887 
888  bitset<4> flag = 15;
889  removeBoundaryBlobs(binary, gray, flag);
890
891  int white_cnt = cvCountNonZero(gray);
892  int total_cnt = binary->width * binary->height;
893
894  double param = white_cnt*100/total_cnt;
895  currfacptr->TeethA = param;
896
897  cvReleaseImage( &scale );
898  cvReleaseImage( &gray );
899  cvReleaseImage( &binary );
900}
901
902
903/*! Function for mouth transforms (lips detection)
904 *
905 *  An example of HSV transform saved in file: ->
906 *                                      backup/program_mouth_hsv.cpp
907 */
908void Facet::detectLips(IplImage *src, FaceComponent &lip,
909                            CvSeq *&lips_outline)
910
911  IplImage *mouth = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
912  cvCopy(src, mouth);
913
914  IplImage *L  = cvCreateImage(cvGetSize(mouth), 8, 1);
915  IplImage *r  = cvCreateImage(cvGetSize(mouth), 8, 1);
916  IplImage *g  = cvCreateImage(cvGetSize(mouth), 8, 1);
917  IplImage *b  = cvCreateImage(cvGetSize(mouth), 8, 1);
918  IplImage *luv  = cvCreateImage(cvGetSize(mouth), 8, 3);
919  IplImage *plane  = cvCreateImage(cvGetSize(mouth), 8, 1);
920
921  for (int i = 0; i < 10; i++)  cvSmooth(mouth, mouth,CV_BLUR,3,3);
922
923  cvCvtColor(mouth, luv, CV_BGR2Luv);
924  cvSplit(luv, L, plane, plane, 0 );
925  cvSplit(mouth, r, g, b, 0 );
926
927  CvMat mat_R; // = cvCreateMat(mouth->height, mouth->width,CV_8UC1);
928  CvMat mat_G; // = cvCreateMat(mouth->height, mouth->width,CV_8UC1);
929  CvMat mat_B; //= cvCreateMat(mouth->height, mouth->width,CV_8UC1);
930
931  cvGetMat(r,&mat_R,0);
932  cvGetMat(g,&mat_G,0);
933  cvGetMat(b,&mat_B,0);
934
935  double max_h=0.0, min_h=255.0;
936
937  double** H_values = new double*[mouth->width]; // GC
938  for(int j=0; j< mouth->width; j++) {
939    double* vals = new double[mouth->height];
940    H_values[j] = vals;
941  }
942  // double H_values [mouth->width][mouth->height];
943 
944  for(int i=0; i< mouth->height; i++) {
945    for(int j=0; j< mouth->width; j++) {
946     
947      double R = cvGetAt(&mat_R,i,j).val[0];
948      double G = cvGetAt(&mat_G,i,j).val[0];
949      if (G==0) G+=0.0000000001;
950      double H = R / ( R + G );
951      H_values[j][i] = H;   
952      if (H>max_h) max_h=H;
953      if (H<min_h) min_h=H;
954    }
955  }
956
957  IplImage *Rcor  = cvCreateImage(cvGetSize(mouth), 8, 1);
958  IplImage *Gcor  = cvCreateImage(cvGetSize(mouth), 8, 1);
959  IplImage *Bcor  = cvCreateImage(cvGetSize(mouth), 8, 1);
960  IplImage *result = cvCreateImage(cvGetSize(mouth), 8, 1);
961  IplImage *result_c = cvCreateImage(cvGetSize(mouth), 8, 1);
962
963  CvMat mat_Rcor;// = cvCreateMat(result->height, result->width,CV_8UC1);
964  CvMat mat_Gcor;// = cvCreateMat(result->height, result->width,CV_8UC1);
965  CvMat mat_Bcor;// = cvCreateMat(result->height, result->width,CV_8UC1);
966  CvMat mat_L;// = cvCreateMat(result->height, result->width,CV_8UC1);
967  CvMat mat_Res;// = cvCreateMat(result->height, result->width,CV_8UC1);
968 
969  cvGetMat(Rcor,&mat_Rcor,0);
970  cvGetMat(Gcor,&mat_Gcor,0);
971  cvGetMat(Bcor,&mat_Bcor,0);
972  cvGetMat(L,&mat_L,0);
973  cvGetMat(result,&mat_Res,0);
974
975  for(int i=0; i< result->height; i++) {
976    for(int j=0; j< result->width; j++) {
977     
978      double R = cvGetAt(&mat_R,i,j).val[0];
979      double Lxy = cvGetAt(&mat_L,i,j).val[0];
980      double r_cor = R / ( R + 0.4 * Lxy + 0.4 );
981      cvSetAt(&mat_Rcor,cvScalar(cvRound(r_cor*255)),i,j); 
982     
983      double G = cvGetAt(&mat_G,i,j).val[0];
984      double g_cor = G / ( G + 0.4 * Lxy + 0.4 );
985      cvSetAt(&mat_Gcor,cvScalar(cvRound(g_cor*255)),i,j);       
986
987      double B = cvGetAt(&mat_B,i,j).val[0];
988      double b_cor = B / ( B + 0.4 * Lxy + 0.4 );
989      cvSetAt(&mat_Bcor,cvScalar(cvRound(b_cor*255)),i,j); 
990
991    }
992  }
993 
994  cvGetImage(&mat_Res,result);
995  //stretchHistogram(result, result); cvNot(result,result);
996 
997  cvSub(Bcor, Gcor, result); 
998  stretchHistogram(result, result); 
999  cvNot(result,result);     
1000
1001  int mouth_thresh = findThresholdByHist( result, lips_proportions );
1002  hysteresisThresholding(result,result_c,cvRound(mouth_thresh*.8),
1003                     cvRound(mouth_thresh*1.2));
1004  cvCopy(result_c, result);
1005 
1006  bitset<4> flag = 14;
1007 
1008  if ((result->width>5) && (result->height>5))
1009    removeBoundaryBlobs(result,result_c,flag);
1010  else cvCopy(result,result_c);
1011 
1012 
1013  int iter = 1;
1014  while (  findConnectedRegions(result_c) > 2 ){
1015    removeSmallBlobs(result_c, result, iter++);
1016    cvCopy(result,result_c);
1017  }
1018 
1019  IplConvKernel* element =
1020    cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_ELLIPSE);
1021  cvMorphologyEx(result, result, result_c, element, CV_MOP_CLOSE, 1);
1022 
1023  cvReleaseStructuringElement( &element );
1024
1025  createOutline(result,result_c);
1026  findContours(result_c, lips_outline);
1027 
1028  parameteriseLips(result_c, lip, lips_outline);
1029 
1030  int H_width = mouth->width; //CHANGE2 GC
1031 
1032  cvReleaseImage( &mouth );
1033  cvReleaseImage( &L );
1034  cvReleaseImage( &r );
1035  cvReleaseImage( &g );
1036  cvReleaseImage( &b );
1037  cvReleaseImage( &luv );
1038  cvReleaseImage( &plane );
1039  cvReleaseImage( &Rcor );
1040  cvReleaseImage( &Gcor );
1041  cvReleaseImage( &Bcor );
1042  cvReleaseImage( &result );
1043  cvReleaseImage( &result_c );
1044  /*
1045  cvReleaseMat( &mat_R );
1046  cvReleaseMat( &mat_G );
1047  cvReleaseMat( &mat_B );
1048  cvReleaseMat( &mat_Rcor );
1049  cvReleaseMat( &mat_Gcor );
1050  cvReleaseMat( &mat_Bcor );
1051  cvReleaseMat( &mat_L );
1052  cvReleaseMat( &mat_Res );
1053  */
1054
1055  for(int j=0; j< H_width; j++) { //CHANGE2 GC
1056    delete [] H_values[j];
1057  }
1058  delete [] H_values;
1059}
1060
1061
1062void Facet::parameteriseLips(IplImage *result_c, FaceComponent &lip,
1063                                CvSeq *lips_outline){
1064  // aspect
1065  CvRect lips_rect = findMouthRectangle(lips_outline);
1066  double aspect_ratio;
1067  (lips_rect.height != 0) ?
1068    aspect_ratio = lips_rect.width*100/lips_rect.height :
1069    aspect_ratio=-1;
1070 
1071  currfacptr->LiAspt = aspect_ratio;
1072  lip.p1 = cvPoint(lips_rect.x, lips_rect.y);
1073  lip.p2 = cvPoint(lips_rect.x+lips_rect.width, lips_rect.y+lips_rect.height);
1074 
1075  // corners location
1076 
1077  CvMat mat;// = cvCreateMat(result_c->height, result_c->width, CV_8UC1);
1078  cvGetMat(result_c, &mat);
1079 
1080  int maxi=-1, mini=-1;
1081  for (int i=0; i< result_c->width; i++){
1082    for (int j=0; j< result_c->height; j++){
1083      double akt=cvGetAt(&mat, j, i).val[0];
1084     
1085      if ((i>=lip.p1.x) && (i<=lip.p2.x) && (j>=lip.p1.y) && (j<=lip.p2.y))
1086        {
1087          if ((akt>100)&&(mini<0)){
1088            mini=j;
1089          }
1090          else if ((akt>100)&&(mini>=0))
1091            maxi=j;
1092        }
1093    }
1094  }
1095  lip.p3 = cvPoint(lip.p1.x, mini); // left corner
1096  lip.p4 = cvPoint(lip.p2.x, maxi); // right corner
1097
1098  double l_corner, r_corner;
1099  l_corner = ((lips_rect.y+lips_rect.height) - lip.p3.y)*100/lips_rect.height;
1100  r_corner = ((lips_rect.y+lips_rect.height) - lip.p4.y)*100/lips_rect.height;
1101 
1102  currfacptr->LLiCnr = l_corner;
1103  currfacptr->RLiCnr = r_corner;
1104
1105  // mouth rectangle and lips corners in the face region coordinates
1106  lip += (FaceComponent(face.p1,face.p2) + face.mouth) ;
1107  //  cvReleaseMat( &mat );
1108}
1109
1110
1111// An attempt to detect the face by the skin hue
1112// -> based on : jap.pdf
1113// The same filter for lips detection
1114//
1115void Facet::faceDetectHue(IplImage *src, bool lips, bool eyes)
1116{
1117  IplImage *dst = cvCreateImage(cvGetSize(src), 8, 3);
1118  cvCopy(src, dst);
1119
1120  IplImage *R = cvCreateImage(cvGetSize(dst), 8, 1);
1121  IplImage *G = cvCreateImage(cvGetSize(dst), 8, 1);
1122  IplImage *B = cvCreateImage(cvGetSize(dst), 8, 1);
1123  IplImage *r = cvCreateImage(cvGetSize(dst), 8, 1);
1124  IplImage *g = cvCreateImage(cvGetSize(dst), 8, 1);
1125  IplImage *lip = cvCreateImage(cvGetSize(dst), 8, 3);
1126 
1127  cvCvtColor(dst,dst,CV_RGB2BGR);
1128  cvSmooth(dst,dst,CV_MEDIAN ,3,1,1);
1129
1130  // transformation into (r,g) colour space
1131  cvSplit(dst,R,G,B,0);
1132  cvZero(r);
1133  cvZero(g);
1134  cvZero(dst);
1135  if (lips) cvZero(lip);
1136
1137  CvMat mat_R;// = cvCreateMat(dst->height, dst->width, CV_8UC1);
1138  CvMat mat_G;// = cvCreateMat(dst->height, dst->width, CV_8UC1);
1139  CvMat mat_B;// = cvCreateMat(dst->height, dst->width, CV_8UC1);
1140  CvMat mat_r;// = cvCreateMat(dst->height, dst->width, CV_8UC1);
1141  CvMat mat_g;// = cvCreateMat(dst->height, dst->width, CV_8UC1);
1142  CvMat mat_dst;// = cvCreateMat(dst->height, dst->width, CV_8UC3);
1143  CvMat mat_src;// = cvCreateMat(dst->height, dst->width, CV_8UC3);
1144  CvMat mat_lip;// = cvCreateMat(dst->height, dst->width, CV_8UC3);
1145  cvGetMat(R,&mat_R,0);
1146  cvGetMat(G,&mat_G,0);
1147  cvGetMat(B,&mat_B,0);
1148  cvGetMat(r,&mat_r,0);
1149  cvGetMat(g,&mat_g,0);
1150  cvGetMat(dst,&mat_dst,0);
1151  cvGetMat(src,&mat_src,0);
1152  if (lips)  cvGetMat(&lip,&mat_lip,0);
1153
1154  for (int i=0; i < (&mat_R)->rows; i++)
1155    for (int j=0; j < (&mat_R)->cols; j++)
1156      {
1157        double red = cvGetAt(&mat_R,i,j).val[0];
1158        double green = cvGetAt(&mat_G,i,j).val[0];
1159        double blue = cvGetAt(&mat_B,i,j).val[0];
1160        double rr = red/(red+green+blue);
1161        double gg = green/(red+green+blue);
1162       
1163        // skin detection
1164        double f_upper = -1.3767*rr*rr + 1.0743*rr + 0.1452;
1165        double f_lower = -0.7760*rr*rr + 0.5601*rr + 0.1766;
1166        double W = (rr - 0.33)*(rr - 0.33) + (gg - 0.33)*(gg - 0.33);
1167       
1168        if ( ((gg < f_upper) && (gg > f_lower)) && (W > 0.0004) &&
1169             (red > blue) && (red > green) &&
1170             ((red-green) >= 25))
1171          //cvSetAt(mat_dst, cvScalar(blue, green, red), i, j);
1172          cvSetAt(&mat_dst, cvScalar( 255, 255, 255 ), i, j);
1173        else
1174          cvSetAt(&mat_dst, cvScalar ( 0,0,0 ), i, j);   
1175       
1176        if (lips) {
1177          double Lr = -0.776*rr*rr + 0.5661*rr + 0.165;
1178
1179          if ((gg < Lr) && (red >= 20) && (green >= 20) && (blue >= 20))
1180            cvSetAt(&mat_lip, cvGetAt(&mat_src,i,j), i, j);
1181        }
1182       
1183      }
1184
1185  cvGetImage(&mat_dst, dst); 
1186  if (lips) cvGetImage(&mat_lip, lip);
1187 
1188  IplImage *dst_copy = cvCreateImage(cvGetSize(dst),8,1);
1189  cvCvtColor(dst,dst_copy, CV_RGB2GRAY);
1190 
1191  IplImage *src_copy = cvCreateImage(cvGetSize(src),8,3);
1192  cvCopy(src,src_copy);
1193 
1194  CvSeq *contour = 0;
1195  CvPoint pkt = cvPoint(0,0);
1196 
1197  findContours(dst_copy, contour);
1198 
1199  if (contour != 0) {
1200   
1201    for( ; contour != 0; contour = contour->h_next ){
1202     
1203      double area =  fabs(cvContourArea(contour, CV_WHOLE_SEQ ));
1204      if (area >= (src->width*src->height)/100) {
1205       
1206        CvRect b_rect = cvContourBoundingRect(contour, 0);
1207       
1208        cvRectangle(src_copy, cvPoint(b_rect.x, b_rect.y),
1209                    cvPoint(b_rect.x+b_rect.width,b_rect.y+b_rect.height),
1210                    CV_RGB(0,255,0),8,8);
1211      }
1212    }
1213  }
1214 
1215  if (eyes) {
1216    IplImage *eye = cvCreateImage(cvGetSize(src),8,1);
1217    IplImage *eye2 = cvCreateImage(cvGetSize(src),8,1);
1218    cvCvtColor(src_copy,eye,CV_RGB2GRAY);
1219    cvZero(eye2);
1220   
1221    int thr = 40;
1222    hysteresisThresholding(eye, eye2, thr, cvRound(thr*1.4));
1223   
1224    cvReleaseImage( &eye );
1225    cvReleaseImage( &eye2 );
1226  }
1227 
1228  cvReleaseImage( &dst );
1229  cvReleaseImage( &dst_copy );
1230  cvReleaseImage( &src_copy );
1231  cvReleaseImage( &R );
1232  cvReleaseImage( &G );
1233  cvReleaseImage( &B );
1234  cvReleaseImage( &r );
1235  cvReleaseImage( &g );
1236  cvReleaseImage( &lip );
1237  /*
1238  cvReleaseMat( &mat_R );
1239  cvReleaseMat( &mat_G );
1240  cvReleaseMat( &mat_B );
1241  cvReleaseMat( &mat_r );
1242  cvReleaseMat( &mat_g );
1243  cvReleaseMat( &mat_dst );
1244  cvReleaseMat( &mat_src );
1245  cvReleaseMat( &mat_lip );
1246  */
1247}
1248
1249
1250// Eyelids detection
1251//
1252double Facet::detectEyelids(IplImage *src, FaceComponent iris,
1253                             FaceComponent &lid) {
1254
1255  IplImage *temp = cvCreateImage(cvGetSize(src), 8, 1);
1256  IplImage *val  = cvCreateImage(cvGetSize(src), 8, 1);
1257  IplImage *hsv  = cvCreateImage(cvGetSize(src), 8, 3);
1258  cvCvtColor(src, hsv, CV_BGR2HSV);
1259  cvSplit(hsv, temp, temp, val, 0 );
1260 
1261  IplImage *eye = cvCreateImage(cvSize(150,100), 8, 1);
1262  IplImage *eye_c = cvCreateImage(cvGetSize(eye), 8, 3);
1263  IplImage *eye_thresh = cvCreateImage(cvGetSize(eye), 8, 1);
1264  IplImage *tmpx = cvCreateImage(cvGetSize(eye), 8, 1);
1265 
1266  IplImage *eye_c1 = cvCreateImage(cvGetSize(src), 8, 1);
1267  cvCopy(val, eye_c1);
1268  IplImage *eye_c3 = cvCreateImage(cvGetSize(src), 8, 3);
1269  cvCopy(src, eye_c3);
1270 
1271  cvResize(eye_c1, eye);
1272  cvResize(eye_c3, eye_c);
1273 
1274  cvZero(tmpx);
1275  cvEqualizeHist(eye, eye);
1276 
1277  int thresh = findThresholdByHist(eye, 20); // 1/4
1278  hysteresisThresholding(eye, eye_thresh, cvRound(0.9*thresh),
1279                         cvRound(thresh*1.2));
1280 
1281  bitset<4> flag = 3;
1282  cvCopy(eye_thresh, tmpx);
1283  removeBoundaryBlobs( tmpx, eye_thresh, flag);
1284 
1285  CvMat mat; // = cvCreateMat(eye->height, eye->width, CV_8UC1);
1286  cvGetMat(eye_thresh, &mat);
1287 
1288  int* ver = new int[eye->width];       //CHANGE GC
1289  int* hor = new int[eye->height];
1290  // int ver[eye->width], hor[eye->height];
1291 
1292  counting(&mat,ver,PROJ_VERTICAL,CNT_MODE_NORMAL,0,eye->height);
1293  counting(&mat,hor,PROJ_HORIZONTAL,CNT_MODE_NORMAL,0,eye->width);
1294 
1295  int sum=0;
1296  for (int i=0; i< eye->height; ++i) {
1297    sum+=hor[i];
1298  }
1299 
1300  int average = cvRound(sum/eye->height/3);
1301 
1302  int v_i_p=0, v_i_k=0;
1303  for (int i=0; i< eye->height; ++i) {
1304    if ((hor[i]>average)&&(v_i_p==0)) {
1305      v_i_p = i;
1306    }
1307    else if (hor[i]>average) v_i_k = i;
1308  }
1309 
1310  //cvGetImage(&mat, eye_thresh);
1311 
1312  double param = (v_i_k - v_i_p)*100/eye->height;
1313
1314  double scale;
1315  scale = eye_c1->height*100/eye->height;
1316
1317  lid.p1 = cvPoint(iris.p1.x - 2, iris.p1.y -
1318                   cvRound((iris.p2.y -iris.p1.y)/3)+cvRound(scale*v_i_p/100));
1319
1320  lid.p2 = cvPoint(iris.p2.x + 2, iris.p1.y -
1321                   cvRound((iris.p2.y -iris.p1.y)/3)+cvRound(scale*v_i_p/100));
1322 
1323  lid.p3 = cvPoint(iris.p1.x -2, iris.p1.y -
1324                   cvRound((iris.p2.y -iris.p1.y)/3)+cvRound(scale*v_i_k/100));
1325
1326  lid.p4 = cvPoint(iris.p2.x + 2, iris.p1.y -
1327                   cvRound((iris.p2.y -iris.p1.y)/3)+cvRound(scale*v_i_k/100));
1328 
1329  cvReleaseImage( &temp );
1330  cvReleaseImage( &val );
1331  cvReleaseImage( &hsv );
1332 
1333  cvReleaseImage( &eye );
1334  cvReleaseImage( &eye_c );
1335  cvReleaseImage( &eye_c1 );
1336  cvReleaseImage( &eye_c3 );
1337  cvReleaseImage( &eye_thresh );
1338  cvReleaseImage( &tmpx );
1339 
1340  //cvReleaseMat( &mat );
1341 
1342  delete [] ver;        //CHANGE delete memory GC
1343  delete [] hor;
1344
1345  return param;
1346}
1347
1348
1349// Eyebrow transform
1350//
1351// Operates on HSV rather than on Grayscale image
1352//
1353void Facet::detectEyebrow(IplImage *src, FaceComponent eye_region,
1354                             FaceComponent iris, FaceComponent &brow,
1355                             bitset<4> flaga)
1356{
1357  IplImage *hsv  = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
1358  IplImage *hsv_plane  = cvCreateImage(cvGetSize(src), src->depth, 1);
1359  IplImage *hsv_value  = cvCreateImage(cvGetSize(src), src->depth, 1);
1360  IplImage *eyebrows = cvCreateImage(cvGetSize(src), src->depth, 1);
1361 
1362  cvCvtColor(src, hsv, CV_BGR2HSV);
1363  cvSplit(hsv, hsv_plane, hsv_plane, hsv_value, 0 );
1364 
1365  for (int i = 0; i < 1; i++)
1366    cvSmooth(hsv_value, hsv_value, CV_MEDIAN , 3, 1, 1);
1367 
1368  // *** ROI SETTING ***
1369 
1370  cvCopy(hsv_value, eyebrows);
1371  cvSetImageROI(eyebrows, cvRect(0, 0, src->width,
1372                                 ((iris-eye_region).p1.y) == 0 ? 1 :
1373                                 (iris-eye_region).p1.y));
1374 
1375  // *** SCALING ***
1376 
1377  IplImage *scale = cvCreateImage( cvSize(150,100),8,1 );      // scaling
1378  IplImage *scale_prim = cvCreateImage(cvGetSize(eyebrows),8,1 ); // primary scale
1379 
1380  cvResize(eyebrows, scale);
1381  //cvSaveImage("scaling.png", scale);
1382 
1383  // **** THRESHOLDING ****
1384 
1385  int brow_thresh = findThresholdByHist(scale, eyebrow_proportions);
1386  hysteresisThresholding(scale, scale, cvRound(0.9*brow_thresh),
1387                         cvRound(brow_thresh*1.4));//60 200
1388 
1389  for (int i=0; i<3; i++) cvSmooth(scale, scale, CV_MEDIAN, 3, 3);
1390 
1391  //cvSaveImage("thresholding.png", scale); 
1392 
1393  // **** FILTERING ****
1394 
1395  bitset<4> flag1 = 12;
1396 
1397  removeBoundaryBlobs(scale, scale, flag1);
1398 
1399  //cvSaveImage("rm_bound_blobs.png", scale); 
1400 
1401  int iter = 1; 
1402  // remove small blobs if total number of them is greater than 1
1403  while ( findConnectedRegions(scale) > 1 ) {
1404    removeSmallBlobs(scale, scale, iter++);
1405  }
1406 
1407  //cvSaveImage("rm_small_blobs.png", scale); 
1408 
1409  // **** SILHOUETTE OUTLINE ****
1410
1411  createOutline(scale, scale);
1412 
1413  //cvSaveImage("outline.png", scale); 
1414 
1415  // *** SCALING (return to the original size) ***
1416 
1417  cvResize(scale, eyebrows);
1418  //eyebrows = cvCloneImage(scale);
1419 
1420  // **** FINDING THE CHARACTERISTIC POINTS ****
1421 
1422  CvMat matc1;// = cvCreateMat(eyebrows->height, eyebrows->width,CV_8UC1);
1423  cvGetMat(eyebrows, &matc1);
1424  bool end = false;
1425  int min_h=eyebrows->height;
1426 
1427  for (int j=0; j< matc1.width; j++){
1428    for (int i=0; i< matc1.height; i++){
1429      int value = (int)cvGetAt(&matc1,i,j).val[0];
1430      if (value>0) {
1431        if (!end){
1432          brow.p1=cvPoint(eye_region.p1.x+j,
1433                          eye_region.p1.y+i);
1434          end=true;
1435        }
1436        else {
1437          brow.p3=cvPoint(eye_region.p1.x+j,
1438                          eye_region.p1.y+i);
1439          if (min_h>i){
1440            min_h = i;
1441            brow.p2=cvPoint(eye_region.p1.x+j,
1442                            eye_region.p1.y+i);
1443          }
1444        }
1445      }
1446    }
1447  }
1448 
1449  parameteriseEyebrow(brow, flaga);
1450 
1451  //drawEyebrows(src, eye_region, brow);
1452  //drawEyebrows(eyebrows, eye_region, brow);
1453 
1454  cvResetImageROI(eyebrows);
1455 
1456  cvReleaseImage(&eyebrows);
1457  // cvReleaseImage(&temp);
1458  cvReleaseImage(&hsv);
1459  cvReleaseImage(&hsv_plane);
1460  cvReleaseImage(&hsv_value);
1461  cvReleaseImage(&scale);
1462  cvReleaseImage(&scale_prim);
1463 
1464  //cvReleaseMat( &matc1 );
1465}
1466
1467
1468void Facet::parameteriseEyebrow(FaceComponent brow, bitset<4> flaga) {
1469 
1470  // calculate the angle between two lines
1471  double A1,A2,B1,B2,C1,C2;
1472 
1473  drawStrLine(brow.p1, brow.p2, A1, B1, C1);
1474  drawStrLine(brow.p3, brow.p2, A2, B2, C2);
1475 
1476  double param;
1477  param = abs(cvRound(rad2deg(calcTwoLinesAngle(A1,B1,A2,B2))));
1478 
1479  if(flaga[2]) currfacptr->REbBnd = param;
1480  if(flaga[3]) currfacptr->LEbBnd = param;
1481 
1482  double Kat1 = abs(cvRound(rad2deg(calcAngleOX(A1,B1))));
1483  double Kat2 = 180 - abs(cvRound(rad2deg(calcAngleOX(A2,B2))));
1484 
1485  param = (Kat1>Kat2 ? Kat1 : Kat2);
1486  if(flaga[2]) currfacptr->REbDcl = param;
1487  if(flaga[3]) currfacptr->LEbDcl = param;
1488
1489}
1490
1491
1492void Facet::drawEyebrows(const IplImage *src, FaceComponent eye_region,
1493                            FaceComponent brow){
1494 
1495  IplImage *display = cvCreateImage(cvGetSize(src), 8, 3);
1496 
1497  if (src->nChannels == 3) cvCopy(src, display);
1498  else cvCvtColor(src, display, CV_GRAY2RGB);
1499 
1500  brow = (brow - eye_region);
1501 
1502  cvLine(display,cvPoint(brow.p2.x,brow.p2.y), cvPoint(brow.p3.x, brow.p3.y),
1503         CV_RGB(255,255,0),3,8);
1504 
1505  cvLine(display,cvPoint(brow.p1.x,brow.p1.y), cvPoint(brow.p2.x,brow.p2.y),
1506         CV_RGB(255,255,0),3,8);
1507 
1508  cvLine(display,cvPoint(brow.p1.x,brow.p1.y), cvPoint(brow.p1.x,brow.p1.y),
1509         CV_RGB(0,0,0),8,8);
1510 
1511  cvLine(display,cvPoint(brow.p2.x,brow.p2.y), cvPoint(brow.p2.x,brow.p2.y),
1512         CV_RGB(0,0,0),8,8);
1513 
1514  cvLine(display,cvPoint(brow.p3.x,brow.p3.y), cvPoint(brow.p3.x,brow.p3.y),
1515         CV_RGB(0,0,0),8,8);
1516 
1517  cvLine(display,cvPoint(brow.p1.x,brow.p1.y), cvPoint(brow.p1.x,brow.p1.y),
1518         CV_RGB(255,255,255),6,8);
1519
1520  cvLine(display,cvPoint(brow.p2.x,brow.p2.y), cvPoint(brow.p2.x,brow.p2.y),
1521         CV_RGB(255,255,255),6,8);
1522 
1523  cvLine(display,cvPoint(brow.p3.x,brow.p3.y), cvPoint(brow.p3.x,brow.p3.y),
1524         CV_RGB(255,255,255),6,8);
1525 
1526  cvLine(display,cvPoint(brow.p1.x,brow.p1.y), cvPoint(brow.p1.x,brow.p1.y),
1527         CV_RGB(0,0,0),4,8);
1528 
1529  cvLine(display,cvPoint(brow.p2.x,brow.p2.y), cvPoint(brow.p2.x,brow.p2.y),
1530         CV_RGB(0,0,0),4,8);
1531 
1532  cvLine(display,cvPoint(brow.p3.x,brow.p3.y), cvPoint(brow.p3.x,brow.p3.y),
1533         CV_RGB(0,0,0),4,8);
1534 
1535  cvSaveImage("aproksymacja.png", display); 
1536  cvReleaseImage( &display );
1537}
1538
1539void Facet::cleanFacesList()
1540{
1541  if(facesList.size()){
1542   
1543    int tmp = facesList.size();
1544    for (int i = 0; i< tmp; ++i){
1545      facesList.pop_front();
1546    }
1547  }
1548}
1549
Note: See TracBrowser for help on using the repository browser.