package id.co.gtc.erhacam; import Config.SomeCodes; import lombok.NonNull; import org.bytedeco.opencv.opencv_core.*; import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier; import org.tinylog.Logger; import java.util.ArrayList; import java.util.List; public class Detectors { public static CascadeClassifier frontalfaceDetector; private static CascadeClassifier eyeDetector; private static CascadeClassifier profilefaceDetector; private static double scaleFactor = 1.1; private final static int minNeighbors = 3; private final static int flags = 0; private static Size FaceminSize; private static Size FacemaxSize; public static void LoadAllDetectors(){ LoadFrontalFaceDetector(); LoadEyeDetector(); LoadProfileFaceDetector(); } private static void LoadFrontalFaceDetector(){ String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml"); if (filename!=null) { Logger.info("Face Detector file : " + filename); if (frontalfaceDetector==null) { try{ frontalfaceDetector = new CascadeClassifier(filename); Logger.info("FaceDetector loaded"); } catch (Exception e){ Logger.error("Exception on loading FaceDetector : " + e.getMessage()); } } else Logger.info("FaceDetector already loaded"); } else Logger.error("Unable to extract face detector file"); } private static void LoadProfileFaceDetector(){ String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml"); if (filename!=null) { Logger.info("Profile Face Detector file : " + filename); if (profilefaceDetector==null) { try{ profilefaceDetector = new CascadeClassifier(filename); Logger.info("ProfileFaceDetector loaded"); } catch (Exception e){ Logger.error("Exception on loading ProfileFaceDetector : " + e.getMessage()); } } else Logger.info("ProfileFaceDetector already loaded"); } else Logger.error("Unable to extract profile face detector file"); } private static void LoadEyeDetector(){ String filename = SomeCodes.ExtractResource("/haarcascade_eye.xml"); if (filename!=null) { Logger.info("Eye Detector file : " + filename); if (eyeDetector==null) { try{ eyeDetector = new CascadeClassifier(filename); Logger.info("EyeDetector loaded"); } catch (Exception e){ Logger.error("Exception on loading EyeDetector : " + e.getMessage()); } } else Logger.info("EyeDetector already loaded"); } else Logger.error("Unable to extract eye detector file"); } /** * Detect if there is a frontal face, containing 2 eyes * @param graymat Mat in Gray Scale * @return List of Rect if face detected, otherwise empty list */ public static @NonNull List HaveFrontalFace(UMat graymat){ List result = new ArrayList<>(); RectVector faces = DetectFrontalFace(graymat); if (faces!=null && faces.size()>0){ for(Rect face : faces.get()){ RectVector eyes = DetectEye(graymat, face.width()); DetectorResult dr = new DetectorResult(); dr.setFace(face); if (eyes!=null && eyes.size()>=2){ for(Rect eye : eyes.get()){ if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye); } } result.add(dr); } } return result; } public static @NonNull List HaveLeft45Face(UMat graymat){ List result = new ArrayList<>(); RectVector faces = DetectProfileFace(graymat); if (faces!=null && faces.size()>0){ for(Rect face : faces.get()){ RectVector eyes = DetectEye(graymat, face.width()); DetectorResult dr = new DetectorResult(); dr.setFace(face); if (eyes!=null && eyes.size()>0){ for(Rect eye : eyes.get()){ if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye); } } result.add(dr); } } return result; } public static void setScaleFactor(double value){ if (scaleFactor!=value) scaleFactor = value; } public static void setFaceMinSize(int value){ if (FaceminSize!=null){ if (FaceminSize.width()!=value || FaceminSize.height()!=value) { FaceminSize = new Size(value, value); //Logger.info("FaceMinSize changed to : " + FaceminSize.width()); } } else { FaceminSize = new Size(value, value); //Logger.info("FaceMinSize created with value : " + FaceminSize.width()); } System.out.println("Face Min Size : " + FaceminSize.width()); } public static void setFaceMaxSize(int value){ if (FacemaxSize!=null){ if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) { FacemaxSize = new Size(value, value); //Logger.info("FaceMaxSize changed to : " + FacemaxSize.width()); } } else { FacemaxSize = new Size(value, value); //Logger.info("FaceMaxSize created with value : " + FacemaxSize.width()); } System.out.println("Face Max Size : " + FacemaxSize.width()); } public static RectVector DetectProfileFace(UMat graymat){ return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize); } /** * Detect Face from Mat * @param graymat Mat in Gray Scale * @return RectVector if face detected, otherwise null */ public static RectVector DetectFrontalFace(UMat graymat){ return Detect(graymat, frontalfaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize); } /** * Detect Eye from Mat * If Eye detected, it will return RectVector with size is number of eyes detected * @param graymat Mat in Gray Scale * @return RectVector if eye detected, otherwise null */ public static RectVector DetectEye(UMat graymat, int facewidth){ //return Detect(graymat, eyeDetector); int minwidth = Math.max((int)(facewidth*0.25), 24); int maxwidth = (int)(facewidth*0.4); Size minsize = new Size(minwidth, minwidth); Size maxsize = new Size(maxwidth, maxwidth); return Detect(graymat, eyeDetector, scaleFactor, minNeighbors, flags, minsize, maxsize); } @SuppressWarnings("SameParameterValue") private static RectVector Detect(UMat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){ if (detector!=null){ if (graymat!=null && graymat.channels()==1){ if (!graymat.empty()){ if (minSize!=null){ if (maxSize!=null){ try{ RectVector detected = new RectVector(); detector.detectMultiScale(graymat, detected, scaleFactor, minNeighbors, flags, minSize, maxSize); return detected; } catch (Exception e){ System.out.println("Detectors Detect Error, Message : "+e.getMessage()); } } } } } } return null; } }