commit 22/07/2025

This commit is contained in:
2025-07-22 11:33:13 +07:00
parent 3539fb7d65
commit 49ac4353b3
11 changed files with 134 additions and 57 deletions

View File

@@ -1,6 +1,6 @@
package Config; package Config;
import id.co.gtc.erhacam.Detectors; import id.co.gtc.erhacam.MainApplication;
import lombok.Getter; import lombok.Getter;
import org.tinylog.Logger; import org.tinylog.Logger;
@@ -856,9 +856,20 @@ public class ConfigFile {
cascadeMinSize = toInt(prop.getProperty("cascadeMinSize")); cascadeMinSize = toInt(prop.getProperty("cascadeMinSize"));
cascadeMaxSize = toInt(prop.getProperty("cascadeMaxSize")); cascadeMaxSize = toInt(prop.getProperty("cascadeMaxSize"));
Detectors.setFaceMaxSize(cascadeMaxSize); if (MainApplication.detectorsList!=null){
Detectors.setFaceMinSize(cascadeMinSize); MainApplication.detectorsList.forEach((i, d) -> {
Detectors.setScaleFactor(cascadeScaleFactor); if (d != null) {
d.setFaceMaxSize(cascadeMaxSize);
d.setFaceMinSize(cascadeMinSize);
d.setScaleFactor(cascadeScaleFactor);
}
});
}
// Detectors.setFaceMaxSize(cascadeMaxSize);
// Detectors.setFaceMinSize(cascadeMinSize);
// Detectors.setScaleFactor(cascadeScaleFactor);
MirrorCamera = toBoolean(prop.getProperty("MirrorCamera")); MirrorCamera = toBoolean(prop.getProperty("MirrorCamera"));
FlipCamera = toBoolean(prop.getProperty("FlipCamera")); FlipCamera = toBoolean(prop.getProperty("FlipCamera"));
@@ -944,9 +955,16 @@ public class ConfigFile {
cascadeMinNeighbors = 3; cascadeMinNeighbors = 3;
cascadeMinSize = 250; cascadeMinSize = 250;
cascadeMaxSize = 360; cascadeMaxSize = 360;
Detectors.setFaceMaxSize(cascadeMaxSize); if (MainApplication.detectorsList!= null) MainApplication.detectorsList.forEach((i, d) -> {
Detectors.setFaceMinSize(cascadeMinSize); if (d != null) {
Detectors.setScaleFactor(cascadeScaleFactor); d.setFaceMaxSize(cascadeMaxSize);
d.setFaceMinSize(cascadeMinSize);
d.setScaleFactor(cascadeScaleFactor);
}
});
// Detectors.setFaceMaxSize(cascadeMaxSize);
// Detectors.setFaceMinSize(cascadeMinSize);
// Detectors.setScaleFactor(cascadeScaleFactor);
MirrorCamera = false; MirrorCamera = false;
FlipCamera = false; FlipCamera = false;
SharpnessThreshold = 300.0; SharpnessThreshold = 300.0;

View File

@@ -0,0 +1,10 @@
package ErhaAPI;
import lombok.Data;
@Data
public class BarcodeHttpResult {
private int statusCode;
private String body;
private BarcodeResult result;
}

View File

@@ -1,7 +1,7 @@
package ErhaAPI; package ErhaAPI;
public class BarcodeResullt { public class BarcodeResult {
public int currentPage; public int currentPage;
public int limit; public int limit;
public int totalPages; public int totalPages;

View File

@@ -3,6 +3,7 @@ package ErhaAPI;
import Config.SomeCodes; import Config.SomeCodes;
import com.google.gson.Gson; import com.google.gson.Gson;
import lombok.Getter; import lombok.Getter;
import lombok.NonNull;
import org.tinylog.Logger; import org.tinylog.Logger;
@@ -68,12 +69,14 @@ public class ErhaAPI {
} }
} }
/** /**
* Validate Barcode data * Validate Barcode data
* @param Barcode Barcode to verify * @param Barcode Barcode to verify
* @return BarcodeResullt object if success, or null if failed * @return BarcodeHttpResult object
*/ */
public BarcodeResullt Validate_Barcode(String Barcode, boolean printdebug){ public @NonNull BarcodeHttpResult Validate_Barcode(String Barcode, boolean printdebug){
BarcodeHttpResult bhr = new BarcodeHttpResult();
if (ValidBarCode(Barcode)){ if (ValidBarCode(Barcode)){
try (HttpClient client = HttpClient.newHttpClient()) { try (HttpClient client = HttpClient.newHttpClient()) {
@@ -84,6 +87,11 @@ public class ErhaAPI {
.GET() .GET()
.build(); .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
bhr.setStatusCode(response.statusCode());
bhr.setBody(response.body());
if (response.statusCode()==200){ if (response.statusCode()==200){
String body = response.body(); String body = response.body();
if (printdebug){ if (printdebug){
@@ -91,7 +99,8 @@ public class ErhaAPI {
System.out.println("Validate_Barcode HTTP body : "); System.out.println("Validate_Barcode HTTP body : ");
System.out.println(body); System.out.println(body);
} }
return gson.fromJson(body, BarcodeResullt.class); BarcodeResult brr = gson.fromJson(body, BarcodeResult.class);
bhr.setResult(brr);
} else { } else {
Logger.error("Validate_Barcode failed, status code : " , response.statusCode()); Logger.error("Validate_Barcode failed, status code : " , response.statusCode());
} }
@@ -103,7 +112,7 @@ public class ErhaAPI {
} }
} }
return null; return bhr;
} }
@@ -113,9 +122,10 @@ public class ErhaAPI {
* Upload File * Upload File
* @param patientID Patient ID * @param patientID Patient ID
* @param filename File to upload * @param filename File to upload
* @return null if failed, or response body if success * @return UploadHttpResult object
*/ */
public UploadResult Upload_File(String patientID, String filename, boolean printdebug) { public @NonNull UploadHttpResult Upload_File(String patientID, String filename, boolean printdebug) {
UploadHttpResult uhr = new UploadHttpResult();
if (ValidMedicalRecordId(patientID)){ if (ValidMedicalRecordId(patientID)){
int medical_record_detail_id = toInt(patientID); int medical_record_detail_id = toInt(patientID);
if (ValidFile(filename)){ if (ValidFile(filename)){
@@ -159,6 +169,8 @@ public class ErhaAPI {
// Send request // Send request
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
uhr.setStatusCode(response.statusCode());
uhr.setBody(response.body());
if (printdebug){ if (printdebug){
System.out.println("Upload_File status code : " + response.statusCode()); System.out.println("Upload_File status code : " + response.statusCode());
System.out.println("Upload_File HTTP body : "); System.out.println("Upload_File HTTP body : ");
@@ -167,7 +179,8 @@ public class ErhaAPI {
if (response.statusCode()==200){ if (response.statusCode()==200){
return gson.fromJson(response.body(), UploadResult.class); UploadResult ur = gson.fromJson(response.body(), UploadResult.class);
uhr.setResult(ur);
} else { } else {
Logger.error("Upload_File file ",filename," failed, status code : " , response.statusCode()); Logger.error("Upload_File file ",filename," failed, status code : " , response.statusCode());
@@ -179,7 +192,7 @@ public class ErhaAPI {
} }
} }
} }
return null; return uhr;
} }

View File

@@ -0,0 +1,10 @@
package ErhaAPI;
import lombok.Data;
@Data
public class UploadHttpResult {
int statusCode;
String body;
UploadResult result;
}

View File

@@ -44,7 +44,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import static Config.SomeCodes.*; import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*; import static org.bytedeco.opencv.global.opencv_imgproc.*;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@@ -157,6 +156,8 @@ public class Cameradetail {
private boolean use_qr = false; private boolean use_qr = false;
private boolean use_face = false; private boolean use_face = false;
private @Getter Detectors detector;
private void setSliderValue(Slider sld, CameraProperty prop, double value){ private void setSliderValue(Slider sld, CameraProperty prop, double value){
if (sld!=null){ if (sld!=null){
@@ -239,6 +240,8 @@ public class Cameradetail {
raise_log("Exposure for "+getCameraTitle()+" changed to "+newVal); raise_log("Exposure for "+getCameraTitle()+" changed to "+newVal);
}); });
detector = new Detectors();
} }
@FXML @FXML
@@ -903,7 +906,7 @@ public class Cameradetail {
int _face_width = 0; int _face_width = 0;
int _face_height = 0; int _face_height = 0;
List<DetectorResult> frontalfaces = HaveFrontalFace(GrayMat.clone()); List<DetectorResult> frontalfaces = detector.HaveFrontalFace(GrayMat.clone());
if (!frontalfaces.isEmpty()){ if (!frontalfaces.isEmpty()){
for(DetectorResult rect : frontalfaces){ for(DetectorResult rect : frontalfaces){
if (rect.haveFace() ){ if (rect.haveFace() ){
@@ -921,7 +924,7 @@ public class Cameradetail {
} else { } else {
// gak punya frontal face // gak punya frontal face
// coba cek punya profile left face 45 gak // coba cek punya profile left face 45 gak
List<DetectorResult> Left45Faces = HaveLeft45Face(GrayMat.clone()); List<DetectorResult> Left45Faces = detector.HaveLeft45Face(GrayMat.clone());
if (!Left45Faces.isEmpty()){ if (!Left45Faces.isEmpty()){
for(DetectorResult rect : Left45Faces){ for(DetectorResult rect : Left45Faces){
if (rect.haveFace()){ if (rect.haveFace()){

View File

@@ -7,10 +7,10 @@ import Config.CameraConfigEnum;
import Database.PhotoReviewClass; import Database.PhotoReviewClass;
import Database.Sqlite; import Database.Sqlite;
import ErhaAPI.ErhaAPI; import ErhaAPI.ErhaAPI;
import ErhaAPI.BarcodeResullt; import ErhaAPI.BarcodeHttpResult;
import ErhaAPI.UploadHttpResult;
import ErhaAPI.PhotoResult; import ErhaAPI.PhotoResult;
import ErhaAPI.PatientRecord; import ErhaAPI.PatientRecord;
import ErhaAPI.UploadResult;
import javafx.animation.KeyFrame; import javafx.animation.KeyFrame;
import javafx.animation.Timeline; import javafx.animation.Timeline;
@@ -520,14 +520,11 @@ public class CaptureView {
int totalfiles = files.length; int totalfiles = files.length;
int counter = 0; int counter = 0;
for (String ff : files) { for (String ff : files) {
UploadResult ur = erhaAPI.Upload_File(prefix, ff,true); UploadHttpResult ur = erhaAPI.Upload_File(prefix, ff,true);
if (ur != null) { if (ur.getResult().message.startsWith("Record has been created")) {
if (ur.message.startsWith("Record has been created")) {
counter++; counter++;
updateMessage("Upload success for " + ff); updateMessage("Upload success for " + ff);
} else updateMessage("Upload failed for " + ff+", Message : "+ur.message); } else updateMessage("Upload failed for " + ff+", Message : "+ur.getResult().message);
} else updateMessage("Upload failed for " + ff+" because UploadResult is null");
} }
if (counter == totalfiles) { if (counter == totalfiles) {
super.succeeded(); super.succeeded();
@@ -931,11 +928,11 @@ public class CaptureView {
Task<PatientRecord> checkpatientID = new Task<>() { Task<PatientRecord> checkpatientID = new Task<>() {
@Override @Override
protected PatientRecord call() throws Exception { protected PatientRecord call() throws Exception {
BarcodeResullt br = erhaAPI.Validate_Barcode(finalbarCode,true); BarcodeHttpResult br = erhaAPI.Validate_Barcode(finalbarCode,true);
if (br!=null){ if (br.getStatusCode()==200){
if (br.message.startsWith("Records found")){ if (br.getResult().message.startsWith("Records found")){
if (br.data!=null && br.data.length>0){ if (br.getResult().data!=null && br.getResult().data.length>0){
PatientRecord pr = br.data[0]; PatientRecord pr = br.getResult().data[0];
if (!pr.medical_record_detail_id.isBlank()){ if (!pr.medical_record_detail_id.isBlank()){
if (!pr.name.isBlank()){ if (!pr.name.isBlank()){
super.succeeded(); super.succeeded();
@@ -957,10 +954,12 @@ public class CaptureView {
throw new Exception("Data dengan barcode "+finalbarCode+" tidak ditemukan di server"); throw new Exception("Data dengan barcode "+finalbarCode+" tidak ditemukan di server");
} }
} else { } else {
Logger.error("BarcodeResullt with barcode ",finalbarCode," is null"); Logger.error("HTTP code ", br.getStatusCode(), " for barcode ", finalbarCode);
throw new Exception("BarcodeResult dengan barcode "+finalbarCode+" menghasilkan null"); throw new Exception("HTTP code "+br.getStatusCode()+" untuk barcode "+finalbarCode);
} }
} }
}; };
checkpatientID.setOnSucceeded(event -> { checkpatientID.setOnSucceeded(event -> {
@@ -1102,7 +1101,8 @@ public class CaptureView {
}; };
image.setCameraStatus("Camera Starting"); image.setCameraStatus("Camera Starting");
if (image.StartLiveView(lce, title, use_qr_detector, use_face_detector)){ if (image.StartLiveView(lce, title, use_qr_detector, use_face_detector)){
//Runtime.getRuntime().addShutdownHook(new Thread(image::Release)); MainApplication.detectorsList.put(devicenumber, image.getDetector());
Logger.info("Camera "+cameraname+" started with device number "+devicenumber);
} else image.setCameraStatus("Unable to Set Grabber"); } else image.setCameraStatus("Unable to Set Grabber");
} else image.setCameraStatus("Camera not found, please check setting"); } else image.setCameraStatus("Camera not found, please check setting");
} }

View File

@@ -20,16 +20,23 @@ public class Detectors {
private static Size FaceminSize; private static Size FaceminSize;
private static Size FacemaxSize; private static Size FacemaxSize;
public static void LoadAllDetectors(){ public Detectors(){
LoadFrontalFaceDetector(); LoadFrontalFaceDetector();
LoadEyeDetector(); LoadEyeDetector();
LoadProfileFaceDetector(); LoadProfileFaceDetector();
} }
private static void LoadFrontalFaceDetector(){ // public static void LoadAllDetectors(){
//
// LoadFrontalFaceDetector();
// LoadEyeDetector();
//
// LoadProfileFaceDetector();
//
// }
private void LoadFrontalFaceDetector(){
// revisi 09/05/2025, dari filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml"); // revisi 09/05/2025, dari filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml");
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml"); String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
if (filename!=null) { if (filename!=null) {
@@ -46,7 +53,7 @@ public class Detectors {
} else Logger.error("Unable to extract face detector file"); } else Logger.error("Unable to extract face detector file");
} }
private static void LoadProfileFaceDetector(){ private void LoadProfileFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml"); String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml");
if (filename!=null) { if (filename!=null) {
Logger.info("Profile Face Detector file : " + filename); Logger.info("Profile Face Detector file : " + filename);
@@ -62,7 +69,7 @@ public class Detectors {
} else Logger.error("Unable to extract profile face detector file"); } else Logger.error("Unable to extract profile face detector file");
} }
private static void LoadEyeDetector(){ private void LoadEyeDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_eye.xml"); String filename = SomeCodes.ExtractResource("/haarcascade_eye.xml");
if (filename!=null) { if (filename!=null) {
Logger.info("Eye Detector file : " + filename); Logger.info("Eye Detector file : " + filename);
@@ -84,7 +91,7 @@ public class Detectors {
* @param graymat Mat in Gray Scale * @param graymat Mat in Gray Scale
* @return List of Rect if face detected, otherwise empty list * @return List of Rect if face detected, otherwise empty list
*/ */
public static @NonNull List<DetectorResult> HaveFrontalFace(Mat graymat){ public @NonNull List<DetectorResult> HaveFrontalFace(Mat graymat){
List<DetectorResult> result = new ArrayList<>(); List<DetectorResult> result = new ArrayList<>();
RectVector faces = DetectFrontalFace(graymat); RectVector faces = DetectFrontalFace(graymat);
if (faces!=null && faces.size()>0){ if (faces!=null && faces.size()>0){
@@ -106,7 +113,7 @@ public class Detectors {
return result; return result;
} }
public static @NonNull List<DetectorResult> HaveLeft45Face(Mat graymat){ public @NonNull List<DetectorResult> HaveLeft45Face(Mat graymat){
List<DetectorResult> result = new ArrayList<>(); List<DetectorResult> result = new ArrayList<>();
RectVector faces = DetectProfileFace(graymat); RectVector faces = DetectProfileFace(graymat);
if (faces!=null && faces.size()>0){ if (faces!=null && faces.size()>0){
@@ -129,11 +136,11 @@ public class Detectors {
public static void setScaleFactor(double value){ public void setScaleFactor(double value){
if (scaleFactor!=value) scaleFactor = value; if (scaleFactor!=value) scaleFactor = value;
} }
public static void setFaceMinSize(int value){ public void setFaceMinSize(int value){
if (FaceminSize!=null){ if (FaceminSize!=null){
if (FaceminSize.width()!=value || FaceminSize.height()!=value) { if (FaceminSize.width()!=value || FaceminSize.height()!=value) {
FaceminSize = new Size(value, value); FaceminSize = new Size(value, value);
@@ -146,7 +153,7 @@ public class Detectors {
} }
public static void setFaceMaxSize(int value){ public void setFaceMaxSize(int value){
if (FacemaxSize!=null){ if (FacemaxSize!=null){
if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) { if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) {
FacemaxSize = new Size(value, value); FacemaxSize = new Size(value, value);
@@ -160,7 +167,7 @@ public class Detectors {
} }
public static RectVector DetectProfileFace(Mat graymat){ public RectVector DetectProfileFace(Mat graymat){
return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize); return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
} }
@@ -169,7 +176,7 @@ public class Detectors {
* @param graymat Mat in Gray Scale * @param graymat Mat in Gray Scale
* @return RectVector if face detected, otherwise null * @return RectVector if face detected, otherwise null
*/ */
public static RectVector DetectFrontalFace(Mat graymat){ public RectVector DetectFrontalFace(Mat graymat){
return Detect(graymat, frontalfaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize); return Detect(graymat, frontalfaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
} }
@@ -179,7 +186,7 @@ public class Detectors {
* @param graymat Mat in Gray Scale * @param graymat Mat in Gray Scale
* @return RectVector if eye detected, otherwise null * @return RectVector if eye detected, otherwise null
*/ */
public static RectVector DetectEye(Mat graymat, int facewidth){ public RectVector DetectEye(Mat graymat, int facewidth){
//return Detect(graymat, eyeDetector); //return Detect(graymat, eyeDetector);
int minwidth = (int)(facewidth*0.2); int minwidth = (int)(facewidth*0.2);
int maxwidth = (int)(facewidth*0.4); int maxwidth = (int)(facewidth*0.4);
@@ -189,7 +196,7 @@ public class Detectors {
} }
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private static RectVector Detect(Mat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){ private RectVector Detect(Mat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){
if (detector!=null && !detector.empty()){ if (detector!=null && !detector.empty()){
if (graymat!=null && graymat.channels()==1 && !graymat.empty()){ if (graymat!=null && graymat.channels()==1 && !graymat.empty()){
if (minSize!=null && maxSize!=null){ if (minSize!=null && maxSize!=null){

View File

@@ -15,6 +15,8 @@ import javafx.stage.Stage;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static Config.SomeCodes.ShowAlert; import static Config.SomeCodes.ShowAlert;
import static Config.SomeCodes.config; import static Config.SomeCodes.config;
@@ -22,8 +24,10 @@ import static Config.SomeCodes.config;
public class MainApplication extends Application { public class MainApplication extends Application {
final String version = "01072025-PRODUCTION-1.0.1"; final String version = "10072025-PRODUCTION-1.0.2";
PhotoCleaner photoCleaner; PhotoCleaner photoCleaner;
public static Map<Integer, Detectors> detectorsList = new HashMap<>();
@Override @Override
public void start(Stage stage) throws IOException { public void start(Stage stage) throws IOException {
@@ -62,7 +66,8 @@ public class MainApplication extends Application {
Logger.info("Application closed"); Logger.info("Application closed");
}); });
SomeCodes.LoadQRReader(); SomeCodes.LoadQRReader();
Detectors.LoadAllDetectors(); // buang, pindah ke Cameradetail
//Detectors.LoadAllDetectors();
stage.show(); stage.show();

View File

@@ -239,9 +239,20 @@ public class SettingView {
config.setCascadeScaleFactor(scale); config.setCascadeScaleFactor(scale);
config.Save(); config.Save();
Detectors.setFaceMaxSize(max); if (MainApplication.detectorsList!=null){
Detectors.setFaceMinSize(min); MainApplication.detectorsList.forEach((i,d)-> {
Detectors.setScaleFactor(scale); d.setFaceMaxSize(max);
d.setFaceMinSize(min);
d.setScaleFactor(scale);
});
} else {
Logger.error("MainApplication.detectorsList is null, unable to set cascade settings");
}
// Detectors.setFaceMaxSize(max);
// Detectors.setFaceMinSize(min);
// Detectors.setScaleFactor(scale);
ShowAlert(Alert.AlertType.INFORMATION, "Cascade Setting", "Cascade Setting Saved", "Cascade Setting Saved Successfully"); ShowAlert(Alert.AlertType.INFORMATION, "Cascade Setting", "Cascade Setting Saved", "Cascade Setting Saved Successfully");
} else show_cascade_alert("Max Size must be greater than Min Size"); } else show_cascade_alert("Max Size must be greater than Min Size");