double EyeMouthDist( // eye-mouth distance of a face shape, return 1 if not a face const Shape& shape) // in { static const int eyes[] = // surrogates for pupil midpoint { L17_LPupil, L17_RPupil, L17_LEyeOuter, L17_REyeOuter, L17_LEyeInner, L17_REyeInner, L17_LEyebrowInner, L17_REyebrowInner, L17_LEyebrowOuter, L17_REyebrowOuter }; static const int mouths[] = // surrogates for bot of bot lip { L17_CBotOfBotLip, L17_CTopOfTopLip, L17_LMouthCorner, L17_RMouthCorner }; const Shape shape17(Shape17OrEmpty(shape)); if (shape17.rows == 0) // could not convert the shape to a Shape17? return ShapeWidth(shape) / 2; // fallback, note return double eyemouth = CanonicalEyeMouthDist(shape17); if (eyemouth == 0) // pupils and mouth not available? { const int eye = TabPoint(eyes, NELEMS(eyes), shape17); const int mouth = TabPoint(mouths, NELEMS(mouths), shape17); if (eye >= 0 && mouth >= 0) // actual or surrogate points available? { eyemouth = PointDist(shape17, eye, mouth) * CanonicalEyeMouthDist(MEANSHAPE17) / PointDist(MEANSHAPE17, eye, mouth); } } if (eyemouth == 0) { // last resort, estimate eyemouth dist from shape extent eyemouth = MAX(ShapeWidth(shape17), ShapeHeight(shape17)) * PointDist(MEANSHAPE17, L17_LPupil, L17_CBotOfBotLip) / MAX(ShapeWidth(MEANSHAPE17), ShapeHeight(MEANSHAPE17)); } CV_Assert(eyemouth > 1 && eyemouth < 1e5); // sanity check return eyemouth; }
static int MouthVerticalShift( const int ileft_best, // in const int iright_best, // in const int imouth_best, // in const vec_Rect& leyes, // in const vec_Rect& reyes, // in const vec_Rect& mouths) // in { double shift = 0; // assume no shift if (ileft_best != -1 && iright_best != -1) // got both eyes? { CV_Assert(imouth_best != -1); // get eye mouth distance: first get center of both eyes const double xleft = leyes[ileft_best].x + leyes[ileft_best].width / 2; const double yleft = leyes[ileft_best].y + leyes[ileft_best].height / 2; const double xright = reyes[iright_best].x + reyes[iright_best].width / 2; const double yright = reyes[iright_best].y + reyes[iright_best].height / 2; const double eyemouth = PointDist((xleft + xright) / 2,(yleft + yright) / 2, mouths[imouth_best].x, mouths[imouth_best].y); static const double MOUTH_VERT_ADJUST = -0.050; // neg to shift up shift = MOUTH_VERT_ADJUST * eyemouth; } return cvRound(shift); }
double InterEyeDist( // inter-pupil distance of a face shape const Shape& shape) // in { static const int leyes[] = // surrogates for left pupil { L17_LPupil, L17_LEyeOuter, L17_LEyeInner, L17_LEyebrowInner, L17_LEyebrowOuter }; static const int reyes[] = // surrogates for right pupil { L17_RPupil, L17_REyeOuter, L17_REyeInner, L17_REyebrowInner, L17_REyebrowOuter }; const Shape shape17(Shape17OrEmpty(shape)); if (shape17.rows == 0) // could not convert the shape to a Shape17? return ShapeWidth(shape) / 2; // fallback, note return double eyedist = 0; const int leye = TabPoint(leyes, NELEMS(leyes), shape17); const int reye = TabPoint(reyes, NELEMS(reyes), shape17); if (leye >= 0 && reye >= 0 && // actual or surrogate points available? PointDist(shape17, leye, reye) > 1) // surrogates aren't co-located? { eyedist = PointDist(shape17, leye, reye) * PointDist(MEANSHAPE17, L17_LPupil, L17_RPupil) / PointDist(MEANSHAPE17, leye, reye); } else // last resort, estimate inter-pupil distance from shape extent { eyedist = MAX(ShapeWidth(shape17), ShapeHeight(shape17)) * PointDist(MEANSHAPE17, L17_LPupil, L17_RPupil) / MAX(ShapeWidth(MEANSHAPE17), ShapeHeight(MEANSHAPE17)); } CV_Assert(eyedist > 1 && eyedist < 1e5); // sanity check return eyedist; }
void test_point() { int ndim = 5; int i; double diff; int retval = 0; printf("\nTesting points\n"); struct Point* p1 = PointAlloc(ndim); struct Point* p2 = PointAlloc(ndim); struct Point* p3; for (i=0; i<p1->x->size; i++) { p1->x->data[i] = (double) i; p2->x->data[i] = (double) 2*i; printf("p1->x->data[%d]: %lf\n", i, p1->x->data[i]); printf("p2->x->data[%d]: %lf\n", i, p2->x->data[i]); } if (PointEqual(p1,p2)) { printf("Points are equal\n"); } else { printf("Points differ\n"); } diff = PointDist(p1,p2); if (diff < 0.0) { retval = 1; } else { printf("diff: %lf\n", diff); } printf("copying Points\n"); PointCopy(p2,p1); if (PointEqual(p1,p2)) { printf("Points are equal\n"); } else { printf("Points differ\n"); } // this would fail //PointEqual(p1,p3); PointFree(p1); PointFree(p2); }
static double CanonicalEyeMouthDist( // return 0 if pupils and mouth not avail const Shape& shape17) // in { if (!PointUsed(shape17, L17_LPupil) || !PointUsed(shape17, L17_RPupil) || !PointUsed(shape17, L17_CBotOfBotLip)) { return 0; // note return } return PointDist( MeanPoint(shape17, L17_LPupil, L17_RPupil, IX), // eye mid point MeanPoint(shape17, L17_LPupil, L17_RPupil, IY), shape17(L17_CBotOfBotLip, IX), // bot of bot lip shape17(L17_CBotOfBotLip, IY)); }
static DetPar PseudoDetParFromStartShape( const Shape& startshape, double rot, double yaw, int nmods) { const double lex = startshape(L_LPupil, IX); // left eye const double ley = startshape(L_LPupil, IY); const double rex = startshape(L_RPupil, IX); // right eye const double rey = startshape(L_RPupil, IY); const double mouthx = startshape(L_CBotOfBotLip, IX); // mouth const double mouthy = startshape(L_CBotOfBotLip, IY); CV_Assert(PointUsed(lex, ley)); CV_Assert(PointUsed(rex, rey)); CV_Assert(PointUsed(mouthx, mouthy)); const double xeye = (lex + rex) / 2; // midpoint of eyes const double yeye = (ley + rey) / 2; const double eyemouth = PointDist(xeye, yeye, mouthx, mouthy); DetPar detpar; detpar.x = .7 * xeye + .3 * mouthx; detpar.y = .7 * yeye + .3 * mouthy; detpar.width = 2.0 * eyemouth; detpar.height = 2.0 * eyemouth; detpar.lex = lex; detpar.ley = ley; detpar.rex = rex; detpar.rey = rey; detpar.mouthx = mouthx; detpar.mouthy = mouthy; detpar.rot = rot; detpar.eyaw = DegreesAsEyaw(yaw, nmods); // determines what ASM model to use detpar.yaw = yaw; return detpar; }