Files
ErhaCam/src/main/java/id/co/gtc/erhacam/Detectors.java
2025-04-14 18:16:42 +07:00

219 lines
7.8 KiB
Java

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<DetectorResult> HaveFrontalFace(UMat graymat){
List<DetectorResult> 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<DetectorResult> HaveLeft45Face(UMat graymat){
List<DetectorResult> 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;
}
}