Created
March 12, 2012 09:39
-
-
Save lilith/2020938 to your computer and use it in GitHub Desktop.
Eye detection code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public string FaceCascade = @"haarcascade_frontalface_default.xml"; | |
public string LeftEyeCascade = @"haarcascade_lefteye_2splits.xml"; | |
public string RightEyeCascade = @"haarcascade_righteye_2splits.xml"; | |
public string EyePair45 = @"hhaarcascade_mcs_eyepair_big.xml"; | |
public string EyePair22 = @"haarcascade_mcs_eyepair_small.xml"; | |
public List<RectangleF> DetectEyes(Bitmap b) { | |
List<RectangleF> eyes = new List<RectangleF>(); | |
using (IplImage orig = OpenCvSharp.BitmapConverter.ToIplImage(b)) | |
using (IplImage gray = new IplImage(orig.Size, BitDepth.U8, 1)) { | |
//Make grayscale version | |
Cv.CvtColor(orig, gray, ColorConversion.BgrToGray); | |
int w = orig.Width; int h = orig.Height; | |
double ratio = (double)w / (double)h; | |
double scale = 1; | |
if (ratio > 1) scale = (double)w / 1000; | |
if (ratio <= 1) scale = (double)h / 1000; | |
scale = Math.Min(1, 1 / scale); | |
using (IplImage small = new IplImage(new CvSize(Cv.Round(w * scale), Cv.Round(h * scale)), BitDepth.U8, 1)) { | |
//Resize to smaller version | |
Cv.Resize(gray, small, Interpolation.Area); | |
//Equalize histogram | |
Cv.EqualizeHist(gray, gray); | |
using (CvHaarClassifierCascade cascade = CvHaarClassifierCascade.FromFile(xmlFolder + FaceCascade)) | |
using (CvMemStorage storage = new CvMemStorage()) { | |
storage.Clear(); | |
Stopwatch watch = Stopwatch.StartNew(); | |
//TODO: CvSeq must be disposed... | |
CvSeq<CvAvgComp> faces = Cv.HaarDetectObjects(small, cascade, storage, 1.1, 2, HaarDetectionType.DoCannyPruning); | |
watch.Stop(); | |
Console.WriteLine("face detection time = {0}ms\n", watch.ElapsedMilliseconds); | |
using (CvHaarClassifierCascade cPair = CvHaarClassifierCascade.FromFile(xmlFolder + EyePair45)) | |
using (CvHaarClassifierCascade cLeft = CvHaarClassifierCascade.FromFile(xmlFolder + LeftEyeCascade)) | |
using (CvHaarClassifierCascade cRight = CvHaarClassifierCascade.FromFile(xmlFolder + RightEyeCascade)) { | |
watch.Reset(); watch.Start(); | |
foreach (CvAvgComp face in faces) { | |
storage.Clear(); | |
//Take the top 4/8ths of the face as the region of interest | |
CvRect r = face.Rect; | |
r.Height = Cv.Round((double)r.Height * 4.0 / 8.0); | |
small.SetROI(r); | |
CvSeq<CvAvgComp> pairs = Cv.HaarDetectObjects(small, cPair, storage, 1.1, 3); | |
foreach (CvAvgComp pair in pairs) { | |
int liftedTop = Math.Max(0,pair.Rect.Y - (pair.Rect.Height /2)); | |
CvRect leftEye = pair.Rect; | |
leftEye.Width = leftEye.Width / 2; | |
leftEye.X -= leftEye.Width / 10; | |
leftEye.Height = leftEye.Bottom - liftedTop; | |
leftEye.Y = liftedTop; | |
CvRect rightEye = pair.Rect; | |
rightEye.Width = rightEye.Width / 2; | |
rightEye.X += rightEye.Width + rightEye.Width / 10; | |
rightEye.Height = rightEye.Bottom - liftedTop; | |
rightEye.Y = liftedTop; | |
storage.Clear(); | |
small.SetROI(leftEye); | |
CvAvgComp[] leyes = Cv.HaarDetectObjects(small, cLeft, storage, 1.1, 3).ToArrayAndDispose(); //TODO dispose seq. | |
storage.Clear(); | |
small.SetROI(rightEye); | |
CvAvgComp[] reyes = Cv.HaarDetectObjects(small, cRight, storage, 1.1, 3).ToArrayAndDispose();//TODO dispose seq. | |
if (leyes.Length > 0 && reyes.Length > 0) { | |
eyes.Add(leyes[0].Rect.ToRectangleF()); | |
eyes.Add(reyes[0].Rect.ToRectangleF()); | |
} | |
} | |
} | |
watch.Stop(); | |
Console.WriteLine("eye pair and individual eye detection time = {0}ms\n", watch.ElapsedMilliseconds); | |
} | |
} | |
} | |
//Scale all rectangles by factor to restore to original resolution | |
for (int i = 0; i < eyes.Count; i++) { | |
RectangleF e = eyes[i]; | |
e.Y = (float)Math.Min(h, e.Y / scale); | |
e.X = (float)Math.Min(w, e.X / scale); | |
e.Height = (float)Math.Min(h - e.Y, e.Height / scale); | |
e.Width = (float)Math.Min(w -e.X, e.Width / scale); | |
eyes[i] = e; | |
} | |
} | |
return eyes; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment