一个人脸检测器

本文使用到Emgu.CV库,该库是C#语言对OpenCV的封装,以下是一个列子程序的改正版本。

using System;
using System.Collections.Generic;
using System.Text;
using Emgu.CV.Structure;
using Emgu.CV;

namespace VSL.Plugin.TrackingSystem.SimpleTrackingSystemExample
{

    public class FaceDetector
    {
        //private HaarCascade _faceCascade;
        Emgu.CV.HaarCascade face;// = new HaarCascade(".\\haarcascades\\haarcascade_frontalface_alt_tree.xml");
        Emgu.CV.HaarCascade eye;// = new HaarCascade(".\\haarcascades\\haarcascade_frontaleye.xml");

        public FaceDetector()
        {
            //  _faceCascade = new HaarCascade(".\\haarcascades\\haarcascade_frontalface_alt_tree.xml");
            face = new Emgu.CV.HaarCascade(".\\haarcascades\\haarcascade_frontalface_alt_tree.xml");
            eye = new Emgu.CV.HaarCascade(".\\haarcascades\\haarcascade_frontaleye.xml");
        }

        public List<Face<D>> Detect<D>(Emgu.CV.Image<Emgu.CV.Bgr, D> img)
        {
            using (Emgu.CV.Image<Emgu.CV.Gray, D> gray = img.Convert<Emgu.CV.Gray, D>())
            {
                MCvAvgComp[][] objects = gray.DetectHaarCascade(face);
                List<Face<D>> res = new List<Face<D>>();

                System.Drawing.Rectangle rect = img.ROI; //保存操作区域

                //通过判断脸部是否含有眼睛来进一步检测是否是正确的人脸
                foreach (MCvAvgComp f in objects[0])
                {
                    //检测眼睛
                    gray.ROI = f.rect;
                    MCvAvgComp[][] eyesDetected = gray.DetectHaarCascade(eye, 1.1, 1,
                                                                         Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.
                                                                             DO_CANNY_PRUNING,
                                                                         new System.Drawing.Size(20, 20));
                    gray.ROI = System.Drawing.Rectangle.Empty;

                    //if there is no eye in the specific region, the region shouldn't contains a face
                    //note that we might not be able to recoginize a person who ware glass in this case
                    if (eyesDetected[0].Length == 0) continue;

                    img.ROI = f.rect; //设定操作区域
                    res.Add(new Face<D>(img.Copy(), f.rect));
                }
                img.ROI = rect; //恢复操作区域
                return res;
            }
        }

        public void Dispose()
        {
            face.Dispose();
        }
    }

    public class Eye<D>
    {
        private Emgu.CV.Image<Emgu.CV.Bgr, D> _image;
        public Eye(Emgu.CV.Image<Emgu.CV.Bgr, D> img, System.Drawing.Rectangle rect)
        {
            _image = img;
        }

        public Emgu.CV.Image<Emgu.CV.Bgr, D> RGB
        {
            get
            {
                return _image;
            }
        }
    }

    public class Face<D>
    {
        private Emgu.CV.Image<Emgu.CV.Bgr, D> _image;
        private Emgu.CV.Image<Emgu.CV.Gray, D> _imageGray;
        private Emgu.CV.Image<Emgu.CV.Hsv, D> _imageHSV;
        private Emgu.CV.Image<Emgu.CV.Gray, D> _h;
        private Emgu.CV.Image<Emgu.CV.Gray, D> _s;
        private Emgu.CV.Image<Emgu.CV.Gray, D> _v;
        private Emgu.CV.Histogram _hueHtg;
        //private Seq<MCvContour> _skinContour;
        private System.Drawing.Rectangle _rect;
        private Emgu.CV.HaarCascade _eyeCascade;

        public Face(Emgu.CV.Image<Emgu.CV.Bgr, D> img, System.Drawing.Rectangle rect)
        {
            _image = img;
            _rect = rect;
            _eyeCascade = new Emgu.CV.HaarCascade(".\\haarcascades\\eye_12.xml");
        }

        public List<Eye<D>> DetectEye()
        {
            MCvAvgComp[][] objects = Gray.DetectHaarCascade(_eyeCascade);
            List<Eye<D>> res = new List<Eye<D>>();

            foreach (MCvAvgComp o in objects[0])
            {
                _image.ROI = o.rect;
                res.Add(new Eye<D>(_image.Copy(), o.rect));
            }
            _image.ROI = System.Drawing.Rectangle.Empty;
            return res;
        }

        public System.Drawing.Rectangle Rectangle
        {
            get { return _rect; }
        }
        public Emgu.CV.Image<Emgu.CV.Bgr, D> Bgr
        {
            get
            {
                return _image;
            }
        }

        public Emgu.CV.Image<Emgu.CV.Gray, D> Gray
        {
            get
            {
                if (_imageGray == null) _imageGray = _image.Convert<Emgu.CV.Gray, D>();
                return _imageGray;
            }
        }

        public Emgu.CV.Image<Emgu.CV.Hsv, D> Hsv
        {
            get
            {
                if (_imageHSV == null) _imageHSV = _image.Convert<Emgu.CV.Hsv, D>();
                return _imageHSV;
            }
        }

        public Emgu.CV.Image<Emgu.CV.Gray, D> H
        {
            get
            {
                if (_h == null)
                {
                    Emgu.CV.Image<Gray, D>[] imgs = Hsv.Split();
                    _h = imgs[0];
                    _s = imgs[1];
                    _v = imgs[2];
                }
                return _h;
            }
        }
        public Image<Gray, D> S
        {
            get
            {
                if (_s == null)
                {
                    Image<Gray, D>[] imgs = Hsv.Split();
                    _h = imgs[0];
                    _s = imgs[1];
                    _v = imgs[2];
                }
                return _s;
            }
        }
        public Image<Gray, D> V
        {
            get
            {
                if (_h == null)
                {
                    Image<Gray, D>[] imgs = Hsv.Split();
                    _h = imgs[0];
                    _s = imgs[1];
                    _v = imgs[2];
                }
                return _v;
            }
        }

        public Histogram HueHistogram
        {
            get
            {

                if (_hueHtg == null)
                {
                    int size = 60;
                    _hueHtg = new Histogram(new int[1] { size }, new float[1] { 0.0f }, new float[1] { 180.0f });
                }
                return _hueHtg;
            }
        }

        public Image<Gray, D> SkinMask
        {
            get
            {
                Image<Gray, D> skinMask = Gray.CopyBlank();

                //skinMask.Draw(SkinContour, new Gray(255.0), new Gray(120.0), -1);

                return skinMask;
            }
        }

        /*
        public Seq<MCvContour> SkinContour
        {
            get
            {
                if (_skinContour == null)
                {
                    Histogram htg = HueHistogram;

                    htg.Accumulate(new Image<Gray, D>[1] { H });

                    double[] arr = new double[htg.BinSize[0]];
                    for (int i = 0; i < htg.BinSize[0]; i++)
                        arr[i] = htg.Query(new int[1] { i });
                    System.Array.Sort<double>(arr);
                    System.Array.Reverse(arr);
                    htg.Threshold(arr[2]);

                    using (Image<Gray, D> bpj = htg.BackProject(new Image<Gray, D>[1] { H }))
                    {
                        Seq<MCvContour> cList = bpj.FindContours( CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, new MemStorage());
                        Seq<MCvContour> maxAreaContour = cList;
                        foreach (Seq<MCvContour> ct in cList)
                        {
                            if (ct.Area > maxAreaContour.Area)
                                maxAreaContour = ct;
                        }
                        _skinContour = GRAY.Snake(maxAreaContour, 1.0f, 1.0f, 1.0f, new Point2D<int>(5, 5), new Emgu.CV.MCvTermCriteria(20, 1.0), new MemStorage());

                    }
                }
                return _skinContour;
            }
        }*/

        public void Dispose()
        {
            _image.Dispose();
            if (_imageGray != null) _imageGray.Dispose();
            if (_imageHSV != null) _imageHSV.Dispose();
            if (_h != null) _h.Dispose();
            if (_s != null) _s.Dispose();
            if (_v != null) _v.Dispose();
            //if (_skinContour != null) _skinContour.Dispose();
        }
    }
}

你可能感兴趣的:(个人)