206 lines
7.9 KiB
Java
206 lines
7.9 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 CascadeClassifier frontalfaceDetector;
|
|
private CascadeClassifier eyeDetector;
|
|
private CascadeClassifier profilefaceDetector;
|
|
|
|
private double scaleFactor = 1.05; // revisi 09/05/2025, dari nilai 1.05
|
|
private final int minNeighbors = 3; // revisi 09/05/2025, dari nilai 3
|
|
private final int flags = 0;
|
|
private Size FaceminSize;
|
|
private Size FacemaxSize;
|
|
|
|
public Detectors(){
|
|
LoadFrontalFaceDetector();
|
|
LoadEyeDetector();
|
|
|
|
LoadProfileFaceDetector();
|
|
}
|
|
|
|
private void LoadFrontalFaceDetector(){
|
|
// revisi 09/05/2025, dari filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml");
|
|
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
|
|
if (filename!=null) {
|
|
try{
|
|
frontalfaceDetector = new CascadeClassifier(filename);
|
|
} catch (Exception e){
|
|
Logger.error("Exception on loading FaceDetector : " + e.getMessage());
|
|
}
|
|
} else Logger.error("Unable to extract face detector file");
|
|
}
|
|
|
|
private void LoadProfileFaceDetector(){
|
|
String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml");
|
|
if (filename!=null) {
|
|
try{
|
|
profilefaceDetector = new CascadeClassifier(filename);
|
|
} catch (Exception e){
|
|
Logger.error("Exception on loading ProfileFaceDetector : " + e.getMessage());
|
|
}
|
|
} else Logger.error("Unable to extract profile face detector file");
|
|
}
|
|
|
|
private void LoadEyeDetector(){
|
|
String filename = SomeCodes.ExtractResource("/haarcascade_eye.xml");
|
|
if (filename!=null) {
|
|
try{
|
|
|
|
eyeDetector = new CascadeClassifier(filename);
|
|
} catch (Exception e){
|
|
Logger.error("Exception on loading EyeDetector : " + e.getMessage());
|
|
}
|
|
} 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 @NonNull List<DetectorResult> HaveFrontalFace(Mat graymat){
|
|
List<DetectorResult> result = new ArrayList<>();
|
|
//System.out.println("Detecting frontal from "+ graymat.size().width() + "x" + graymat.size().height());
|
|
RectVector faces = DetectFrontalFace(graymat);
|
|
if (faces!=null && faces.size()>0){
|
|
//System.out.println("faces size = " + faces.size());
|
|
for(Rect face : faces.get()){
|
|
RectVector eyes = DetectEye(graymat, face.width());
|
|
DetectorResult dr = new DetectorResult();
|
|
dr.setFace(face);
|
|
//System.out.println("eyes size = " + eyes.size());
|
|
if (eyes.size()>=2){
|
|
for(Rect eye : eyes.get()){
|
|
if (SomeCodes.IsInsideRect(eye, face)) {
|
|
dr.AddEye(eye);
|
|
}
|
|
}
|
|
}
|
|
result.add(dr);
|
|
}
|
|
} //else System.out.println("faces size = 0");
|
|
return result;
|
|
}
|
|
|
|
public @NonNull List<DetectorResult> HaveLeft45Face(Mat 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.size()>0){
|
|
for(Rect eye : eyes.get()){
|
|
if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye);
|
|
}
|
|
}
|
|
result.add(dr);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setScaleFactor(double value){
|
|
if (scaleFactor!=value) scaleFactor = value;
|
|
}
|
|
|
|
public 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());
|
|
}
|
|
|
|
}
|
|
|
|
public 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());
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public RectVector DetectProfileFace(Mat 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 RectVector DetectFrontalFace(Mat 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 RectVector DetectEye(Mat graymat, int facewidth){
|
|
//return Detect(graymat, eyeDetector);
|
|
int minwidth = (int)(facewidth*0.2);
|
|
int maxwidth = (int)(facewidth*0.4);
|
|
Size minsize = new Size(minwidth, minwidth);
|
|
Size maxsize = new Size(maxwidth, maxwidth);
|
|
//System.out.println("Detecting Eye with minsize = " + minsize.width() + "x" + minsize.height() + ", maxsize = " + maxsize.width() + "x" + maxsize.height());
|
|
return Detect(graymat, eyeDetector, scaleFactor, minNeighbors, flags, minsize, maxsize);
|
|
}
|
|
|
|
@SuppressWarnings("SameParameterValue")
|
|
private RectVector Detect(Mat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){
|
|
if (detector!=null && !detector.empty()){
|
|
if (graymat!=null && graymat.channels()==1 && !graymat.empty()){
|
|
if (minSize!=null && maxSize!=null){
|
|
if (minSize.width()< maxSize.width() && minSize.height() < maxSize.height()){
|
|
if (graymat.cols()> minSize.width() && graymat.rows() > minSize.height()) {
|
|
try {
|
|
RectVector detected = new RectVector();
|
|
// try defaulting minSize and maxSize
|
|
detector.detectMultiScale(graymat, detected, scaleFactor, minNeighbors, flags, minSize, new Size());
|
|
|
|
return detected;
|
|
} catch (Exception e) {
|
|
System.out.println("Detectors Detect Error, Message : " + e.getMessage());
|
|
}
|
|
} else System.out.println("graymat is smaller than minSize");
|
|
|
|
} else System.out.println("minSize is larger than maxSize");
|
|
} else System.out.println("minSize or maxSize is null");
|
|
} else System.out.println("graymat is null, not 1 channel, or empty");
|
|
|
|
} else System.out.println("detector empty");
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
}
|