//本文使用到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 caseif (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();}}
}
文章源地址: http://www.cnblogs.com/zengqs/archive/2009/02/01/1382024.html