Esempio n. 1
0
static void DrawEyes(
    CImage&         img,         // io
    const vec_Rect& leyes,       // in
    const vec_Rect& reyes,       // in
    int             ileft_best,  // in
    int             iright_best, // in
    const Rect&     facerect,    // in
    EYAW            eyaw)        // in
{
    // rectangles showing search regions
    const int linewidth = facerect.width > 700? 3: facerect.width > 300? 2: 1;
    const Rect left_rect(EyeSearchRect(eyaw, facerect, false));
    const Rect right_rect(EyeSearchRect(eyaw, facerect, true));
    const Rect eye_inner_rect(EyeInnerRect(eyaw, facerect));
    DrawRect(img, facerect,       Dark(C_YELLOW),    linewidth);
    DrawRect(img, left_rect,      VeryDark(C_RED),   linewidth);
    DrawRect(img, right_rect,     VeryDark(C_GREEN), linewidth);
    DrawRect(img, eye_inner_rect, Dark(C_YELLOW),    linewidth);
    int i;
    for (i = 0; i < NSIZE(leyes); i++)
        DrawFeat(img,
                 i, leyes, C_RED, linewidth, i==ileft_best);
    for (i = 0; i < NSIZE(reyes); i++)
        DrawFeat(img,
                 i, reyes, C_RED /*C_GREEN*/, linewidth, i==iright_best);
}
Esempio n. 2
0
	// Show a complex array ---------------------------------------------------
	std::ostream& operator<<(std::ostream& ostrm,
		const MultidimArray< Complex >& v)
	{
		if (v.xdim == 0)
			ostrm << "NULL MultidimArray\n";
		else
			ostrm << std::endl;

		for (int l = 0; l < NSIZE(v); l++)
		{
			if (NSIZE(v)>1) ostrm << "Image No. " << l << std::endl;
			for (int k = STARTINGZ(v); k <= FINISHINGZ(v); k++)
			{
				if (ZSIZE(v) > 1) ostrm << "Slice No. " << k << std::endl;
				for (int i = STARTINGY(v); i <= FINISHINGY(v); i++)
				{
					for (int j = STARTINGX(v); j <= FINISHINGX(v); j++)
						ostrm << "(" << A3D_ELEM(v, k, i, j).real << "," << A3D_ELEM(v, k, i, j).imag << ")" << ' ';
					ostrm << std::endl;
				}
			}
		}

		return ostrm;
	}
Esempio n. 3
0
static void
ioctl_simplestruct_init_from_bin(ioctl_tree * node, const void *data)
{
    DBG(DBG_IOCTL_TREE, "ioctl_simplestruct_init_from_bin: %s(%lX): size is %lu bytes\n", node->type->name, node->id, NSIZE(node));
    node->data = malloc(NSIZE(node));
    memcpy(node->data, data, NSIZE(node));
}
Esempio n. 4
0
static void DiscardMissizedFaces(
    vec_DetPar& detpars) // io
{
    // constants (TODO These have not yet been rigorously empirically adjusted.)
    static const double MIN_WIDTH = 1.33; // as fraction of median width
    static const double MAX_WIDTH = 1.33; // as fraction of median width

    if (NSIZE(detpars) >= 3) // need at least 3 faces
    {
        // sort the faces on their width (smallest first) so can get median width
        sort(detpars.begin(), detpars.end(), DecreasingWidth);
        const int median     = cvRound(detpars[NSIZE(detpars) / 2].width);
        const int minallowed = cvRound(median / MIN_WIDTH);
        const int maxallowed = cvRound(MAX_WIDTH * median);
        // keep only faces that are not too big or small
        vec_DetPar all_detpars(detpars);
        detpars.resize(0);
        for (int iface = 0; iface < NSIZE(all_detpars); iface++)
        {
            DetPar* face = &all_detpars[iface];
            if (face->width >= minallowed && face->width <= maxallowed)
                detpars.push_back(*face);
            else if (trace_g || TRACE_IMAGES)
                lprintf("[discard face%d of %d]", iface, NSIZE(all_detpars));
        }
    }
}
Esempio n. 5
0
void ShapeFile::Subset_( // select a subset of the shapes
    int         nshapes, // in: number of shapes to select
    int         seed,    // in: if 0 use first nshapes,
                         //     else rand subset of nshapes
    const char* sregex)  // in: regex string, NULL or "" to match any
{
    SubsetRegex_(sregex);                // select shapes matching the regex

    if (nshapes)
        SubsetN_(nshapes, seed, sregex); // select nshapes

    nchar_ = 0; // nbr of chars in longest string in bases_
    for (int i = 0; i < NSIZE(bases_); i++)
        if (int(bases_[i].length()) > nchar_)
            nchar_ = int(bases_[i].length());

    if (nshapes == 1 || nshapes_ == 1)
        lprintf("Using 1 shape");
    else if (nshapes == 0)
        lprintf("Using all %d shapes", nshapes_);
    else if (seed == 0)
        lprintf("Using the first %d shape%s", nshapes, plural(nshapes));
    else
        lprintf("Using a random subset of %d shape%s", nshapes, plural(nshapes));
    if (sregex && sregex[0])
        lprintf(" matching %s", sregex);
    if (NSIZE(bases_) > 1)
        lprintf(" (%s ... %s)",
                bases_[0].c_str(), bases_[NSIZE(bases_)-1].c_str());
    lprintf("\n");
}
Esempio n. 6
0
static void NbrUsedPointsVec(   // nbr of used points in each shape
    vec_int&         nused_vec, // out: vec [nshapes] of int
    const vec_Shape& shapes)    // in
{
    nused_vec.resize(NSIZE(shapes));
    for (int ishape = 0; ishape < NSIZE(shapes); ishape++)
        nused_vec[ishape] = NbrUsedPoints(shapes[ishape]);
}
Esempio n. 7
0
void CopyShapeVec(
    vec_Shape&       newshapes, // out
    const vec_Shape& oldshapes) // in
{
    newshapes.resize(NSIZE(oldshapes));
    for (int i = 0; i < NSIZE(oldshapes); i++)
        oldshapes[i].copyTo(newshapes[i]);
}
Esempio n. 8
0
static void SelectMouth(
    int&            imouth_best,      // out: index into mouths, -1 if none
    int             ileft_best,       // in: index of best left eye, -1 if none
    int             iright_best,      // in: index of best right eye, -1 if none
    const vec_Rect& leyes,            // in: left eyes found by eye detector
    const vec_Rect& reyes,            // in: right eyes found by eye detector
    const vec_Rect& mouths,           // in: left eyes found by eye detector
    const Rect&     mouth_inner_rect) // in: center of mouth must be in this region
{
    CV_Assert(!mouths.empty());
    imouth_best = -1;

    // if only one mouth, use it
    if (NSIZE(mouths) == 1 && InRect(mouths[0], mouth_inner_rect))
        imouth_best = 0;
    else
    {
        // More than one mouth: selected the lowest mouth to avoid
        // "nostril mouths".  But to avoid "chin mouths", the mouth
        // must also meet the following criteria:
        //   i)  it must be wider than the .7 * smallest eye width
        //   ii) it must be not much narrower than widest mouth.

        int minwidth = 0;
        if (ileft_best != -1)
            minwidth = leyes[ileft_best].width;
        if (iright_best != -1)
            minwidth = MIN(minwidth, reyes[iright_best].width);
        minwidth = cvRound(.7 * minwidth);

        // find widest mouth
        int maxwidth = minwidth;
        for (int imouth = 0; imouth < NSIZE(mouths); imouth++)
        {
            const Rect mouth = mouths[imouth];
            if (InRect(mouth, mouth_inner_rect) && mouth.width > maxwidth)
            {
                maxwidth = mouth.width;
                imouth_best = imouth;
            }
        }
        // choose lowest mouth that is at least .84 the width of widest
        minwidth = MAX(minwidth, cvRound(.84 * maxwidth));
        int ymin = int(-1e5);
        for (int imouth = 0; imouth < NSIZE(mouths); imouth++)
        {
            const Rect mouth = mouths[imouth];
            if (InRect(mouth, mouth_inner_rect) &&
                mouth.y + mouth.height / 2 > ymin &&
                mouth.width > minwidth)
            {
                ymin = mouth.y + mouth.height / 2;
                imouth_best = imouth;
            }
        }
    }
}
Esempio n. 9
0
void DetectFaces(          // all face rects into detpars
    vec_DetPar&  detpars,  // out
    const Image& img,      // in
    int          minwidth) // in: as percent of img width
{
    CV_Assert(!facedet_g.empty()); // check that OpenFaceDetector_ was called

    int leftborder = 0, topborder = 0; // border size in pixels
    Image bordered_img(BORDER_FRAC == 0?
                       img: EnborderImg(leftborder, topborder, img));

    // Detection results are very slightly better with equalization
    // (tested on the MUCT images, which are not pre-equalized), and
    // it's quick enough to equalize (roughly 10ms on a 1.6 GHz laptop).

    Image equalized_img;
    cv::equalizeHist(bordered_img, equalized_img);

    CV_Assert(minwidth >= 1 && minwidth <= 100);

    // TODO smallest bioid faces are about 80 pixels width, hence 70 below
    const int minpix =
        MAX(minwidth <= 5? 70: 100, cvRound(img.cols * minwidth / 100.));

    // the params below are accurate but slow
    static const double SCALE_FACTOR   = 1.1;
    static const int    MIN_NEIGHBORS  = 3;
    static const int    DETECTOR_FLAGS = 0;

    vec_Rect facerects = // all face rects in image
        Detect(equalized_img, facedet_g, NULL,
               SCALE_FACTOR, MIN_NEIGHBORS, DETECTOR_FLAGS, minpix);

    // copy face rects into the detpars vector

    detpars.resize(NSIZE(facerects));
    for (int i = 0; i < NSIZE(facerects); i++)
    {
        Rect* facerect = &facerects[i];
        DetPar detpar; // detpar constructor sets all fields INVALID
        // detpar.x and detpar.y is the center of the face rectangle
        detpar.x = facerect->x + facerect->width / 2.;
        detpar.y = facerect->y + facerect->height / 2.;
        detpar.x -= leftborder; // discount the border we added earlier
        detpar.y -= topborder;
        detpar.width  = double(facerect->width);
        detpar.height = double(facerect->height);
        detpar.yaw = 0; // assume face has no yaw in this version of Stasm
        detpar.eyaw = EYAW00;
        detpars[i] = detpar;
    }
}
Esempio n. 10
0
static void NormalizeDesc( // take sqrt of elems and divide by L2 norm
    VEC& desc)             // io
{
    double* const data = Buf(desc);
    for (int i = 0; i < NSIZE(desc); i++)
        data[i] = sqrt(data[i]); // sqrt reduces effect of outliers
    const double norm = cv::norm(desc); // L2 norm
    if (!IsZero(norm))
    {
        const double scale = FINAL_SCALE / norm;
        for (int i = 0; i < NSIZE(desc); i++)
            data[i] *= scale;
    }
}
Esempio n. 11
0
static void WriteTrainDescs(
    const TRAIN_DISTS& train_dists, // in: [ipoint] [idesc] distances from true landmark
    const TRAIN_DESCS& train_descs, // in: [ipoint] [idesc] training descriptors
    int                ilev,        // in:
    const char*        outdir)      // in: output directory (-d flag)
{
    clock_t start_time = clock();
    const int npoints = NSIZE(train_descs);
    Pacifier pacifier(npoints);
    for (int ipoint = 0; ipoint < npoints; ipoint++)
    {
        // filename
        const int ndigits = NumDigits(npoints);
        char format[SLEN]; // e.g. tasmout/log/lev1_p23_classic.desc
        sprintf(format, "%%s/log/lev%%d_p%%%d.%dd_%%s.desc", ndigits, ndigits);
        char path[SLEN];
        sprintf(path, format, outdir, ilev, ipoint,
                IsTasmHatDesc(ilev, ipoint)? "hat": "classic");
        static int printed;
        PrintOnce(printed, "    generating %s (tasm -w flag)...\n", path);
        FILE* file = fopen(path, "wb");
        if (!file)
            Err("Cannot open %s", path);
        // header
        const vec_VEC descs = train_descs[ipoint]; // descriptors for this point
        const vec_double dists = train_dists[ipoint];
        Fprintf(file, "ilev ipoint       dist ");
        for (int i = 0; i < NSIZE(descs[0]); i++)
        {
            char s[SLEN];  sprintf(s, "x%d ", i);
            Fprintf(file, " %10.10s", s);
        }
        Fprintf(file, "\n");
        // contents
        for (int idesc = 0; idesc < NSIZE(descs); idesc++)
        {
            Fprintf(file, "%4d %6d %10g", ilev, ipoint, dists[idesc]);
            for (int i = 0; i < NSIZE(descs[idesc]); i++)
                Fprintf(file, " %10g", descs[idesc](i));
            Fprintf(file, "\n");
        }
        fclose(file);
        if (print_g)
            pacifier.Print_(ipoint);
    }
    if (print_g)
        pacifier.End_();
    lprintf(" [%.1f secs]\n", double(clock() - start_time) / CLOCKS_PER_SEC);
}
Esempio n. 12
0
static VEC FullProf(          // return full profile
    const Image& img,         // in
    const MAT&   shape,       // in
    int          ipoint,      // in: index of the current point
    int          fullproflen) // in
{
    CV_Assert(fullproflen > 1 && fullproflen < 100); // 100 is arb
    CV_Assert(fullproflen % 2 == 1); // fullprof length must be odd

    VEC fullprof(1, fullproflen);

    double xstep; // x axis dist corresponding to one pixel along whisker
    double ystep;
    WhiskerStep(xstep, ystep, shape, ipoint);

    const double x = shape(ipoint, IX); // center point of the whisker
    const double y = shape(ipoint, IY);

    // number of pixs to sample in each direction along the whisker
    const int n = (NSIZE(fullprof) - 1) / 2;

    int prevpix = Pix(img,
                      Step(x, xstep, -n-1), Step(y, ystep, -n-1));

    for (int i = -n; i <= n; i++)
    {
        const int pix = Pix(img,
                            Step(x, xstep, i), Step(y, ystep, i));
        fullprof(i + n) = double(pix - prevpix); // signed gradient
        prevpix = pix;
    }
    return fullprof;
}
Esempio n. 13
0
static void RandInts(
    vec_int& ints,    // out: scrambled integers in range 0 ... NSIZE(ints)-1
    int      seed)    // in:  random seed
{
    const int n = NSIZE(ints);
    CV_Assert(n > 0);
    if (n > RAND_MAX)
        Err("vector size %d is too big (max allowed is %d)", n, RAND_MAX);
    CV_Assert(seed != 0);
    if (seed == 1)       // 1 has a special meaning which we don't want
        seed = int(1e6); // arb

    int i;
    for (i = 0; i < n; i++)
        ints[i] = i;

    srand(seed);

    // We use our own random shuffle here because different compilers
    // give different results which messes up regression testing.
    // (I think only Visual C 6.0 is incompatible with everyone else?)
    //
    // Following code is equivalent to
    //    random_shuffle(ints.begin(), ints.end(),
    //       pointer_to_unary_function<int,int>(RandInt));

    vec_int::iterator it = ints.begin();
    for (i = 2; ++it != ints.end(); i++)
        iter_swap(it, ints.begin() + rand() % n);
}
Esempio n. 14
0
static inline void GetMagsAndOrients_AllInImg(
    vec_double&       mags,                    // out
    vec_double&       orients,                 // out
    const int         ix,                      // in: x coord of center of patch
    const int         iy,                      // in: y coord of center of patch
    const int         patchwidth,              // in
    const MAT&        magmat,                  // in
    const MAT&        orientmat,               // in
    const vec_double& pixelweights)            // in
{
    const int halfpatchwidth = (patchwidth-1) / 2;
    int ipix = 0;
    for (int x = iy - halfpatchwidth; x <= iy + halfpatchwidth; x++)
    {
        const double* const magbuf    = Buf(magmat)    + x * magmat.cols;
        const double* const orientbuf = Buf(orientmat) + x * orientmat.cols;

        for (int y = ix - halfpatchwidth; y <= ix + halfpatchwidth; y++)
        {
            mags[ipix]    = pixelweights[ipix] * magbuf[y];
            orients[ipix] = orientbuf[y];
            ipix++;
        }
    }
    CV_DbgAssert(ipix == NSIZE(mags));
}
Esempio n. 15
0
void Mod::LevSearch_(         // do an ASM search at one level in the image pyr
    Shape&       shape,       // io: the face shape for this pyramid level
    int          ilev,        // in: pyramid level (0 is full size)
    const Image& img,         // in: image scaled to this pyramid level
    const Shape& pinnedshape) // in: if no rows then no pinned landmarks, else
                              //     points except those equal to 0,0 are pinned
const
{
    TraceShape(shape, img, ilev, 0, "enterlevsearch");

    InitHatLevData(img, ilev); // init internal HAT mats for this lev

    VEC b(NSIZE(shapemod_.eigvals_), 1, 0.); // eigvec weights, init to 0

    for (int iter = 0; iter < SHAPEMODEL_ITERS; iter++)
    {
        // suggest shape by descriptor matching at each landmark

        SuggestShape_(shape,
                      ilev, img, pinnedshape);

        TraceShape(shape, img, ilev, iter, "suggested");

        // adjust suggested shape to conform to the shape model

        if (pinnedshape.rows)
            shape = shapemod_.ConformShapeToMod_Pinned_(b,
                                                        shape, ilev, pinnedshape);
        else
            shape = shapemod_.ConformShapeToMod_(b,
                                                 shape, ilev);

        TraceShape(shape, img, ilev, iter, "conformed");
    }
}
Esempio n. 16
0
void GenAndWriteDescMods( // generate the descriptor models and write them to .mh files
    const ShapeFile& sh,               // in: the shapefile contents
    const char*      outdir,           // in: output directory (-d flag)
    const char*      modname,          // in: e.g. "yaw00"
    const char*      cmdline,          // in: command line used to invoke tasm
    bool             write_traindescs) // in: tasm -w flag
{
    lprintf("--- Generating the descriptor models from %d shapes ---\n", NSIZE(sh.shapes_));

    srand((unsigned int)TASM_NEGTRAIN_SEED);

    // we work a level at a time to save memory (although it takes longer than
    // doing all levels simultaneously because we have to reread the images for
    // each level)

    for (int ilev = 0; ilev < N_PYR_LEVS; ilev++)
    {
        TRAIN_DISTS train_dists; // [ipoint] [idesc] distances from true landmark
        TRAIN_DESCS train_descs; // [ipoint] [idesc] training descriptors

        // get the training descriptors for all points and images for this pyr lev

        GetTrainingDescs(train_dists, train_descs, ilev, sh);

        if (write_traindescs)
            WriteTrainDescs(train_dists, train_descs, ilev, outdir);

        // generate the descriptor models from the training descriptors

        GenDescMods(train_dists, train_descs, ilev, sh, outdir, modname, cmdline);
    }
}
Esempio n. 17
0
static void GenDescMods( // generate descriptor models for all points and images for one pyr lev
    TRAIN_DISTS&     train_dists, // out: [ipoint] [idesc] distances from true landmark
    TRAIN_DESCS&     train_descs, // out: [ipoint] [idesc] training descriptors
    int              ilev,        // in: pyramid level (0 is full scale)
    const ShapeFile& sh,          // in
    const char*      outdir,      // in: output directory (-d flag)
    const char*      modname,     // in: e.g. "yaw00"
    const char*      cmdline)     // in: command line used to invoke tasm
{
    clock_t start_time = clock();
    lprintf("Generating pyramid level %d models ", ilev);
    const int npoints = sh.shapes_[0].rows;
    Pacifier pacifier(npoints);
    for (int ipoint = 0; ipoint < npoints; ipoint++)
    {
        const vec_VEC descs = train_descs[ipoint]; // descriptors for this point
        CV_Assert(NSIZE(descs));
        char msg[SLEN]; sprintf(msg, "(level %d point %d)", ilev, ipoint);
        if (IsTasmHatDesc(ilev, ipoint)) // HAT descriptor?
            GenHatMod(ilev, ipoint, npoints, train_dists[ipoint], descs,
                      msg, outdir, modname, cmdline);
        else // classical 1D profile
            GenClassicMod(ilev, ipoint, npoints, descs, msg, outdir, modname, cmdline);
        if (print_g)
            pacifier.Print_(ipoint);
    }
    if (print_g)
        pacifier.End_();
    lprintf(" [%.1f secs]\n", double(clock() - start_time) / CLOCKS_PER_SEC);
}
Esempio n. 18
0
void FaceDet::DetectFaces_(  // call once per image to find all the faces
    const Image& img,        // in: the image (grayscale)
    const char*,             // in: unused (match virt func signature)
    bool         multiface,  // in: if false, want only the best face
    int          minwidth,   // in: min face width as percentage of img width
    void*        user)       // in: unused (match virt func signature)
{
    CV_Assert(user == NULL);
    CV_Assert(!facedet_g.empty()); // check that OpenFaceDetector_ was called
    DetectFaces(detpars_, img, minwidth);
    TraceFaces(detpars_, img, "facedet_BeforeDiscardMissizedFaces.bmp");
    DiscardMissizedFaces(detpars_);
    TraceFaces(detpars_, img, "facedet_AfterDiscardMissizedFaces.bmp");
    if (multiface) // order faces on increasing distance from left margin
    {
        sort(detpars_.begin(), detpars_.end(), IncreasingLeftMargin);
        TraceFaces(detpars_, img, "facedet.bmp");
    }
    else
    {
        // order faces on decreasing width, keep only the first (the largest face)
        sort(detpars_.begin(), detpars_.end(), DecreasingWidth);
        TraceFaces(detpars_, img, "facedet.bmp");
        if (NSIZE(detpars_))
            detpars_.resize(1);
    }
    iface_ = 0; // next invocation of NextFace_ must get first face
}
Esempio n. 19
0
void FaceDet::DetectFaces_( // call once per image to find all the faces
    const Image& img,       // in: the image (grayscale)
    const char*  imgpath,   // in: used only for debugging
    bool         multiface, // in: if false, want only the best face
    int          minwidth,  // in: min face width as percentage of img width
    void*        user,      // in: unused (match virt func signature)
    cv::CascadeClassifier cascade)
{
    (void) imgpath;
    (void) user;
    DetectFaces(detpars_, img, minwidth, cascade);
    DiscardMissizedFaces(detpars_);

    if (multiface) // order faces on increasing distance from left margin
    {
        sort(detpars_.begin(), detpars_.end(), IncreasingLeftMargin);
    }
    else
    {
        // order faces on decreasing width, keep only the first (the largest face)
        sort(detpars_.begin(), detpars_.end(), DecreasingWidth);
        if (NSIZE(detpars_))
            detpars_.resize(1);
    }
    iface_ = 0; // next invocation of NextFace_ must get first face
}
Esempio n. 20
0
static void GetMagsAndOrients_GeneralCase(
    vec_double&       mags,         // out
    vec_double&       orients,      // out
    const int         ix,           // in: x coord of center of patch
    const int         iy,           // in: y coord of center of patch
    const int         patchwidth,   // in
    const MAT&        magmat,       // in
    const MAT&        orientmat,    // in
    const vec_double& pixelweights) // in
{
    const int halfpatchwidth = (patchwidth-1) / 2;
    int ipix = 0;
    for (int x = iy - halfpatchwidth; x <= iy + halfpatchwidth; x++)
    {
        const double* const magbuf    = Buf(magmat)    + x * magmat.cols;
        const double* const orientbuf = Buf(orientmat) + x * orientmat.cols;

        for (int y = ix - halfpatchwidth; y <= ix + halfpatchwidth; y++)
        {
            if (x < 0 || x >= magmat.rows || y < 0 || y >= magmat.cols)
            {
                mags[ipix] = 0;    // off image
                orients[ipix] = 0;
            }
            else                   // in image
            {
                mags[ipix]    = pixelweights[ipix] * magbuf[y];
                orients[ipix] = orientbuf[y];
            }
            ipix++;
        }
    }
    CV_DbgAssert(ipix == NSIZE(mags));
}
Esempio n. 21
0
void FaceDet::DetectFaces_( // call once per image to find all the faces
    const Image& img,       // in: the image (grayscale)
    const char*  imgpath,   // in: used only for debugging
    bool         multiface, // in: if false, want only the best face
    int          minwidth,  // in: min face width as percentage of img width
    void*        user)      // in: unused (match virt func signature)
{
    CV_Assert(user == NULL);
    DetectFaces(detpars_, img, minwidth);
    char tracepath[SLEN];
    sprintf(tracepath, "%s_00_unsortedfacedet.bmp", Base(imgpath));
    TraceFaces(detpars_, img, tracepath);
    DiscardMissizedFaces(detpars_);
    if (multiface) // order faces on increasing distance from left margin
    {
        sort(detpars_.begin(), detpars_.end(), IncreasingLeftMargin);
        sprintf(tracepath, "%s_05_facedet.bmp", Base(imgpath));
        TraceFaces(detpars_, img, tracepath);
    }
    else
    {
        // order faces on decreasing width, keep only the first (the largest face)
        sort(detpars_.begin(), detpars_.end(), DecreasingWidth);
        sprintf(tracepath, "%s_05_sortedfaces.bmp", Base(imgpath));
        TraceFaces(detpars_, img, tracepath);
        if (NSIZE(detpars_))
            detpars_.resize(1);
    }
    iface_ = 0; // next invocation of NextFace_ must get first face
}
Esempio n. 22
0
static Shape AlignMeanShapeToRightEyeAndMouth(
    const DetPar& detpar,                             // in
    const Shape&  meanshape)                          // in
{
    if (trace_g)
        lprintf("AlignToRightEyeAndMouth          ");

    CV_Assert(NSIZE(meanshape) > 0 && PointUsed(meanshape, 0));
    CV_Assert(!Valid(detpar.lex));   // left eye invalid? (else why are we here?)
    CV_Assert(Valid(detpar.rex));    // right eye valid?
    CV_Assert(Valid(detpar.mouthx)); // mouth valid?

    const double x_meanmouth =
       (meanshape(L_CTopOfTopLip, IX) + meanshape(L_CBotOfBotLip, IX)) / 2;

    const double y_meanmouth =
       (meanshape(L_CTopOfTopLip, IY) + meanshape(L_CBotOfBotLip, IY)) / 2;

    Shape meanline(2, 2), detline(2, 2);              // line from eye to mouth

    meanline(0, IX) = meanshape(L_RPupil, IX);        // right eye
    meanline(0, IY) = meanshape(L_RPupil, IY);
    meanline(1, IX) = x_meanmouth;                    // mouth
    meanline(1, IY) = y_meanmouth;

    detline(0, IX) = detpar.rex;                      // right eye
    detline(0, IY) = detpar.rey;
    detline(1, IX) = detpar.mouthx;                   // mouth
    detline(1, IY) = detpar.mouthy;

    return AlignShape(meanshape, AlignmentMat(meanline, detline));
}
Esempio n. 23
0
static Shape AlignMeanShapeToBothEyesNoMouth(
    const DetPar& detpar,                      // in
    const Shape&  meanshape)                   // in
{
    if (trace_g)
        lprintf("AlignToBothEyesNoMouth           ");

    CV_Assert(NSIZE(meanshape) > 0 && PointUsed(meanshape, 0));
    CV_Assert(Valid(detpar.lex));
    CV_Assert(Valid(detpar.rex));

    Shape meanline(2, 2), detline(2, 2);       // line from eye to eye

    meanline(0, IX) = meanshape(L_LPupil, IX); // left eye
    meanline(0, IY) = meanshape(L_LPupil, IY);
    meanline(1, IX) = meanshape(L_RPupil, IX); // right eye
    meanline(1, IY) = meanshape(L_RPupil, IY);

    detline(0, IX) = detpar.lex;               // left eye
    detline(0, IY) = detpar.ley;
    detline(1, IX) = detpar.rex;               // right eye
    detline(1, IY) = detpar.rey;

    return AlignShape(meanshape, AlignmentMat(meanline, detline));
}
Esempio n. 24
0
static void TraceFaces(        // write image showing detected face rects
    const vec_DetPar& detpars, // in
    const Image&      img,     // in
    const char*       path)    // in
{
#if TRACE_IMAGES // will be 0 unless debugging (defined in stasm.h)

    CImage cimg; cvtColor(img, cimg, CV_GRAY2BGR); // color image
    for (int iface = 0; iface < NSIZE(detpars); iface++)
    {
        const DetPar &detpar = detpars[iface];

        rectangle(cimg,
                  cv::Point(cvRound(detpar.x - detpar.width/2),
                            cvRound(detpar.y - detpar.height/2)),
                  cv::Point(cvRound(detpar.x + detpar.width/2),
                            cvRound(detpar.y + detpar.height/2)),
                  CV_RGB(255,255,0), 2);

        ImgPrintf(cimg, // 10 * iface to minimize overplotting
                  detpar.x + 10 * iface, detpar.y,
                  C_YELLOW, 1, ssprintf("%d", iface));
    }
    lprintf("%s\n", path);
    if (!cv::imwrite(path, cimg))
        Err("Cannot write %s", path);
#endif
}
Esempio n. 25
0
static Shape AlignMeanShapeToBothEyesEstMouth(
    const DetPar& detpar,                      // in
    const Shape&  meanshape)                   // in
{
    // .48 was tested to give slightly better worse case results than .50
    static double EYEMOUTH_TO_FACERECT_RATIO = .48;

    if (trace_g)
        lprintf("AlignToBothEyesNoMouth(EstMouth) ");

    CV_Assert(NSIZE(meanshape) > 0 && PointUsed(meanshape, 0));
    CV_Assert(Valid(detpar.lex));
    CV_Assert(Valid(detpar.rex));

    // estimate the mouth's position

    double x_eyemid = 0;
    switch (detpar.eyaw)
    {
        case EYAW00:                                 //  mid point
            x_eyemid = .50 * detpar.lex + .50 * detpar.rex;
            break;
        // TODO The constants below have not been empirically optimized.
        case EYAW_45:                                // closer to left eye
            x_eyemid = .30 * detpar.lex + .70 * detpar.rex;
            break;
        case EYAW_22:                                // closer to left eye
            x_eyemid = .30 * detpar.lex + .70 * detpar.rex;
            break;
        case EYAW22:                                 // closer to right eye
            x_eyemid = .30 * detpar.lex + .70 * detpar.rex;
            break;
        case EYAW45:                                 // closer to right eye
            x_eyemid = .30 * detpar.lex + .70 * detpar.rex;
            break;
        default:
            Err("AlignMeanShapeToBothEyesEstMouth: Invalid eyaw %d", detpar.eyaw);
            break;
    }
    const double y_eyemid = (detpar.ley + detpar.rey) / 2;

    Shape mean_tri(3, 2), det_tri(3, 2);             // triangle of eyes and mouth

    mean_tri(0, IX) = meanshape(L_LPupil, IX);       // left eye
    mean_tri(0, IY) = meanshape(L_LPupil, IY);
    mean_tri(1, IX) = meanshape(L_RPupil, IX);       // right eye
    mean_tri(1, IY) = meanshape(L_RPupil, IY);
    mean_tri(2, IX) = meanshape(L_CBotOfBotLip, IX); // mouth
    mean_tri(2, IY) = meanshape(L_CBotOfBotLip, IY);

    det_tri(0, IX) = detpar.lex;                     // left eye
    det_tri(0, IY) = detpar.ley;
    det_tri(1, IX) = detpar.rex;                     // right eye
    det_tri(1, IY) = detpar.rey;
    det_tri(2, IX) = x_eyemid;                       // mouth
    det_tri(2, IY) = y_eyemid + EYEMOUTH_TO_FACERECT_RATIO * detpar.width;

    return AlignShape(meanshape, AlignmentMat(mean_tri, det_tri));
}
Esempio n. 26
0
bool NeedMouth(
    const vec_Mod& mods) // in: the ASM model(s)
{
    for (int imod = 0; imod < NSIZE(mods); imod++)
        if (mods[imod]->Estart_() == ESTART_EYE_AND_MOUTH)
            return true;
    return false;
}
Esempio n. 27
0
void ShapeFile::Open_(     // read shape file from disk
    const char* shapepath) // in
{
    lprintf("Reading %s: ", shapepath);
    STRCPY(shapepath_, shapepath);
    FILE* file = fopen(shapepath, "rb");
    if (!file)
        Err("Cannot open %s", shapepath);
    bool oldformat = false;
    Header(oldformat, shapepath, file);
    ImgDirs(dirs_, shapepath, file);
    shapes_.clear();
    bases_.clear();
    bits_.clear();
    poses_.clear();
    char base[SLEN]; unsigned bits; Shape shape;
    nchar_ = 0;
    int nrows = -1;
    while (ReadMat(base, bits, shape, file, shapepath))
    {
        bool normalshape = true;
        if (oldformat)
        {
            if (bits & FA_Meta)  // metashape?
                normalshape = false;
        }
        else if (bits & AT_Meta) // metashape?
        {
            normalshape = false;
            if (bits == AT_Pose)
            {
                CV_Assert(shape.rows == 1 && shape.cols == 4);
                poses_[base] = shape.clone();
            }
        }
        if (normalshape)
        {
            // check that all shapes have same number of points
            if (nrows == -1) // first shape?
                nrows = shape.rows;
            else if (shape.rows != nrows)
                Err("%s has %d row%s but %s has %d row%s",
                    base, shape.rows, plural(shape.rows),
                    bases_[0].c_str(), nrows, plural(nrows));
            shapes_.push_back(shape.clone());
            bases_.push_back(base);
            bits_.push_back(bits);
            int len = STRNLEN(base, 100);
            if (len > nchar_)
                nchar_ = len;
        }
    }
    fclose(file);
    nshapes_ = NSIZE(shapes_);
    lprintf("%d shape%s\n", nshapes_, plural(nshapes_));
    if (nshapes_ == 0)
        Err("No shapes in %s", shapepath);
}
Esempio n. 28
0
const DetPar FaceDet::NextFace_(void)
{
    DetPar detpar; // detpar constructor sets all fields INVALID

    if (iface_ < NSIZE(detpars_))
        detpar = detpars_[iface_++];

    return detpar;
}
Esempio n. 29
0
static void CheckUnusedPoints(
    const TRAIN_DISTS& train_dists, // in: [ipoint] [idesc] distances from true landmark
    int                nshapes)     // in
{
    for (int ipoint = 0; ipoint < NSIZE(train_dists); ipoint++)
    {
        if (NSIZE(train_dists[ipoint]) == 0)
            Err("no descriptors were generated for point %d", ipoint);
        if (NSIZE(train_dists[ipoint]) < nshapes) // see PointUsableForTraining
        {
            static int printed;
            PrintOnce(printed,
                "\n    in point %d, only %d descriptors used from "
                "%d shapes because some points were skipped... ",
                ipoint, NSIZE(train_dists[ipoint]), nshapes);
        }
    }
}
Esempio n. 30
0
static MAT CalcShapeCov(
    const vec_Shape& shapes,    // in
    const Shape&     meanshape) // in
{
    int npoints = meanshape.rows;
    int i, j;

    MAT cov(2 * npoints, 2 * npoints, 0.); // covariance of every x and y coord
    MAT nused(npoints, npoints, 0.);

    // Because of possible unused points, we have to iterate by
    // hand (we can't use standard matrix multiplies).

    for (int ishape = 0; ishape < NSIZE(shapes); ishape++)
    {
        Shape shape(shapes[ishape]);
        for (i = 0; i < npoints; i++)
            if (PointUsed(shape, i))
                for (j = 0; j < npoints; j++)
                    if (PointUsed(shape, j))
                    {
                        cov(2*i,   2*j)   +=  // x * x
                            (shape(i, IX) - meanshape(i, IX)) *
                            (shape(j, IX) - meanshape(j, IX));

                        cov(2*i+1, 2*j)   +=  // y * x
                            (shape(i, IY) - meanshape(i, IY)) *
                            (shape(j, IX) - meanshape(j, IX));

                        cov(2*i,   2*j+1) +=  // x * y
                            (shape(i, IX) - meanshape(i, IX)) *
                            (shape(j, IY) - meanshape(j, IY));

                        cov(2*i+1, 2*j+1) +=  // y * y
                            (shape(i, IY) - meanshape(i, IY)) *
                            (shape(j, IY) - meanshape(j, IY));

                        nused(i, j)++;
                    }
       }

    for (i = 0; i < npoints; i++)
        for (j = 0; j < npoints; j++)
        {
            const double n = nused(i, j);
            if (n < 3) // 3 is somewhat arb
                Err("Cannot calculate covariance of %g shape%s (need more shapes)",
                    n, plural(int(n)));
            cov(2*i,   2*j)   /=  n;
            cov(2*i+1, 2*j)   /=  n;
            cov(2*i,   2*j+1) /=  n;
            cov(2*i+1, 2*j+1) /=  n;
        }

    return cov;
}