//return "0" for single face and "c"(cache) for multiple face //for multiple face, the face rectangles are stored in CCommon.cacheRects //CComon.cacheBm store the 24bit Bitmap for source image public static string FindFaceAndEyes(BitmapSource srcimage, out System.Drawing.Rectangle facerect, out System.Drawing.Rectangle[] eyesrect) { String faceFileName = AppDomain.CurrentDomain.BaseDirectory + "haarcascade_frontalface_alt2.xml"; String eyeFileName = AppDomain.CurrentDomain.BaseDirectory + "haarcascade_eye.xml"; //working with gdi to get 24bit rgb image System.Drawing.Bitmap bmtest = CCommon.BitmapImage2Bitmap(srcimage); System.Drawing.Bitmap bmsrc24 = new System.Drawing.Bitmap(bmtest.Width, bmtest.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); System.Drawing.Graphics gbmsrc24 = System.Drawing.Graphics.FromImage(bmsrc24); gbmsrc24.DrawImageUnscaled(bmtest, 0, 0); gbmsrc24.Dispose(); bmtest.Dispose(); bmtest = null; if (cacheBm != null) { cacheBm.Dispose(); } cacheBm = (System.Drawing.Bitmap)bmsrc24.Clone(); //we do scaling if the source is too large double scale = 1.0; if (bmsrc24.Height > 500) { scale = (double)500 / bmsrc24.Height; } System.Drawing.Bitmap bm = new System.Drawing.Bitmap((int)(bmsrc24.Width * scale), (int)(bmsrc24.Height * scale), System.Drawing.Imaging.PixelFormat.Format24bppRgb); System.Drawing.Graphics gbm = System.Drawing.Graphics.FromImage(bm); //scale down the source image for face dection gbm.DrawImage(bmsrc24, new System.Drawing.Rectangle(0, 0, bm.Width, bm.Height), new System.Drawing.Rectangle(0, 0, bmsrc24.Width, bmsrc24.Height), System.Drawing.GraphicsUnit.Pixel); gbm.Dispose(); // bm.Save(AppDomain.CurrentDomain.BaseDirectory +"temp\\~bm.jpg",System.Drawing.Imaging.ImageFormat.Jpeg); ////////////////////////////////////////// IntelImage _img = CDetectFace.CreateIntelImageFromBitmap(bm); //IntPtr p_face = CDetectFace.HistEqualize(_img); bm.Dispose(); bm = null; string strindex = ""; using (HaarClassifier haarface = new HaarClassifier(faceFileName)) using (HaarClassifier haareye = new HaarClassifier(eyeFileName)) { var faces = haarface.DetectObjects(_img.IplImage()); // var faces = haarface.DetectObjects(p_face ); if (faces.Count > 0) { List <System.Drawing.Rectangle> facerects = new List <System.Drawing.Rectangle>(); for (int i = 0; i < faces.Count; i++) { var face = faces.ElementAt(i); System.Drawing.Rectangle rt = new System.Drawing.Rectangle((int)(face.x / scale), (int)(face.y / scale), (int)(face.width / scale), (int)(face.height / scale)); facerects.Add(rt); } cacheRects = facerects; if (faces.Count > 1) { //clean up and return eyesrect = null; facerect = facerect = System.Drawing.Rectangle.Empty; _img.Dispose(); bmsrc24.Dispose(); bmsrc24 = null; return("c"); //cached } } else { cacheRects.Clear(); } //only handle 1 face if (faces.Count == 1) { var face = faces.ElementAt(0); facerect = new System.Drawing.Rectangle((int)(face.x / scale), (int)(face.y / scale), (int)(face.width / scale), (int)(face.height / scale)); int x = facerect.X, y = facerect.Y, h0 = facerect.Height, w0 = facerect.Width; //to handle oversize face area double rescale = 1.0; if (h0 > 300) { rescale = 300.0 / h0; } System.Drawing.Rectangle temprect = new System.Drawing.Rectangle(x, y, w0, 10 * h0 / 16); System.Drawing.Bitmap bm_eyes = bmsrc24.cropAtRect(temprect); bm_eyes.Save(AppDomain.CurrentDomain.BaseDirectory + "temp\\~eye.bmp", System.Drawing.Imaging.ImageFormat.Bmp); IntelImage image_eyes = CDetectFace.CreateIntelImageFromBitmap(bm_eyes); //resize eyes area for better detection IntelImage image_eyes2X = new IntelImage((int)(image_eyes.IplImageStruc().width *2 * rescale), (int)(image_eyes.IplImageStruc().height *2 * rescale)); NativeMethods.CvResize(image_eyes.IplImage(), image_eyes2X.IplImage(), NativeMethods.CV_INTER_CUBIC); IntPtr p_eq_img_eyes = CDetectFace.HistEqualize(image_eyes2X); var eyes = haareye.DetectObjects(p_eq_img_eyes); ////clean up NativeMethods.cvReleaseImage(ref p_eq_img_eyes); image_eyes.Dispose(); image_eyes = null; bm_eyes.Dispose(); image_eyes2X.Dispose(); image_eyes2X = null; if (eyes.Count > 0) { eyesrect = new System.Drawing.Rectangle[eyes.Count]; for (int i = 0; i < eyesrect.Length; i++) { var eye = eyes.ElementAt(i); //note that we had scale the eyes area by 2, so we scale back eyesrect[i] = new System.Drawing.Rectangle((int)(eye.x / (2 * rescale)), (int)(eye.y / (2 * rescale)), (int)(eye.width / (2 * rescale)), (int)(eye.height / (2 * rescale))); } int mineyesize = (h0 / 12); int maxeyesize = (h0 / 3); //sorting var tempeyeslist = eyesrect.ToList(); //dist to center of face // <-1/2 w --> // | | | // |<-x ->o<d>| | // | | | // | | | // | | | // o=center of eye // x= x dist to center of eye // d= difference of 1/2 w and x // = distance of eye center to center of face // the further this distance, the more likely it is an eye int half_facewidth = facerect.Width / 2; tempeyeslist = tempeyeslist.OrderByDescending(eye => Math.Abs(eye.X + eye.Width / 2 - (half_facewidth))).ToList(); //size: should be within min and max eye size tempeyeslist = tempeyeslist.OrderByDescending(eye => (eye.Width > mineyesize)).ToList(); tempeyeslist = tempeyeslist.OrderByDescending(eye => (eye.Width < maxeyesize)).ToList(); eyesrect = tempeyeslist.ToArray(); } else { eyesrect = null; } } else { facerect = System.Drawing.Rectangle.Empty; eyesrect = null; } } //NativeMethods.cvReleaseImage(ref p_face ); _img.Dispose(); bmsrc24.Dispose(); bmsrc24 = null; return(strindex); }
//Load from cache CCommon cacheBm and cacheRects public static void FindEyesFromCache(int faceindex, out System.Drawing.Rectangle[] eyesrect) { String eyeFileName = AppDomain.CurrentDomain.BaseDirectory + "haarcascade_eye.xml"; using (HaarClassifier haareye = new HaarClassifier(eyeFileName)) { var face = cacheRects.ElementAt(faceindex); var facerect = new System.Drawing.Rectangle((int)(face.X), (int)(face.Y), (int)(face.Width), (int)(face.Height)); int x = facerect.X, y = facerect.Y, h0 = facerect.Height, w0 = facerect.Width; //to handle oversize face area double rescale = 1.0; if (h0 > 300) { rescale = 300.0 / h0; } System.Drawing.Rectangle temprect = new System.Drawing.Rectangle(x, y, w0, 10 * h0 / 16); System.Drawing.Bitmap bm_eyes = cacheBm.cropAtRect(temprect); bm_eyes.Save(AppDomain.CurrentDomain.BaseDirectory + "temp\\~eye.bmp", System.Drawing.Imaging.ImageFormat.Bmp); IntelImage image_eyes = CDetectFace.CreateIntelImageFromBitmap(bm_eyes); //resize eyes area for better detection IntelImage image_eyes2X = new IntelImage((int)(image_eyes.IplImageStruc().width * 2 * rescale), (int)(image_eyes.IplImageStruc().height * 2 * rescale)); NativeMethods.CvResize(image_eyes.IplImage(), image_eyes2X.IplImage(), NativeMethods.CV_INTER_CUBIC); IntPtr p_eq_img_eyes = CDetectFace.HistEqualize(image_eyes2X); var eyes = haareye.DetectObjects(p_eq_img_eyes); ////clean up NativeMethods.cvReleaseImage(ref p_eq_img_eyes); image_eyes.Dispose(); image_eyes = null; bm_eyes.Dispose(); image_eyes2X.Dispose(); image_eyes2X = null; if (eyes.Count > 0) { eyesrect = new System.Drawing.Rectangle[eyes.Count]; for (int i = 0; i < eyesrect.Length; i++) { var eye = eyes.ElementAt(i); //note that we had scale the eyes area by 2, so we scale back eyesrect[i] = new System.Drawing.Rectangle((int)(eye.x / (2 * rescale)), (int)(eye.y / (2 * rescale)), (int)(eye.width / (2 * rescale)), (int)(eye.height / (2 * rescale))); } int mineyesize = (h0 / 12); int maxeyesize = (h0 / 3); //sorting var tempeyeslist = eyesrect.ToList(); //dist to center of face // <-1/2 w --> // | | | // |<-x ->o<d>| | // | | | // | | | // | | | // o=center of eye // x= x dist to center of eye // d= difference of 1/2 w and x // = distance of eye center to center of face // the further this distance, the more likely it is an eye int half_facewidth = facerect.Width / 2; tempeyeslist = tempeyeslist.OrderByDescending(eye => Math.Abs(eye.X + eye.Width / 2 - (half_facewidth))).ToList(); //size: should be within min and max eye size tempeyeslist = tempeyeslist.OrderByDescending(eye => (eye.Width > mineyesize)).ToList(); tempeyeslist = tempeyeslist.OrderByDescending(eye => (eye.Width < maxeyesize)).ToList(); eyesrect = tempeyeslist.ToArray(); } else { eyesrect = null; } } }