Skip to content

Instantly share code, notes, and snippets.

@lilith
Created March 12, 2012 09:39
Show Gist options
  • Save lilith/2020938 to your computer and use it in GitHub Desktop.
Save lilith/2020938 to your computer and use it in GitHub Desktop.
Eye detection code
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