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;
import id.co.gtc.erhacam.Detectors;
import id.co.gtc.erhacam.MainApplication;
import lombok.Getter;
import org.tinylog.Logger;
@@ -856,9 +856,20 @@ public class ConfigFile {
cascadeMinSize = toInt(prop.getProperty("cascadeMinSize"));
cascadeMaxSize = toInt(prop.getProperty("cascadeMaxSize"));
Detectors.setFaceMaxSize(cascadeMaxSize);
Detectors.setFaceMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
if (MainApplication.detectorsList!=null){
MainApplication.detectorsList.forEach((i, d) -> {
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"));
FlipCamera = toBoolean(prop.getProperty("FlipCamera"));
@@ -944,9 +955,16 @@ public class ConfigFile {
cascadeMinNeighbors = 3;
cascadeMinSize = 250;
cascadeMaxSize = 360;
Detectors.setFaceMaxSize(cascadeMaxSize);
Detectors.setFaceMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
if (MainApplication.detectorsList!= null) MainApplication.detectorsList.forEach((i, d) -> {
if (d != null) {
d.setFaceMaxSize(cascadeMaxSize);
d.setFaceMinSize(cascadeMinSize);
d.setScaleFactor(cascadeScaleFactor);
}
});
// Detectors.setFaceMaxSize(cascadeMaxSize);
// Detectors.setFaceMinSize(cascadeMinSize);
// Detectors.setScaleFactor(cascadeScaleFactor);
MirrorCamera = false;
FlipCamera = false;
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;
public class BarcodeResullt {
public class BarcodeResult {
public int currentPage;
public int limit;
public int totalPages;

View File

@@ -3,6 +3,7 @@ package ErhaAPI;
import Config.SomeCodes;
import com.google.gson.Gson;
import lombok.Getter;
import lombok.NonNull;
import org.tinylog.Logger;
@@ -68,12 +69,14 @@ public class ErhaAPI {
}
}
/**
* Validate Barcode data
* @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)){
try (HttpClient client = HttpClient.newHttpClient()) {
@@ -84,6 +87,11 @@ public class ErhaAPI {
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
bhr.setStatusCode(response.statusCode());
bhr.setBody(response.body());
if (response.statusCode()==200){
String body = response.body();
if (printdebug){
@@ -91,7 +99,8 @@ public class ErhaAPI {
System.out.println("Validate_Barcode HTTP body : ");
System.out.println(body);
}
return gson.fromJson(body, BarcodeResullt.class);
BarcodeResult brr = gson.fromJson(body, BarcodeResult.class);
bhr.setResult(brr);
} else {
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
* @param patientID Patient ID
* @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)){
int medical_record_detail_id = toInt(patientID);
if (ValidFile(filename)){
@@ -159,6 +169,8 @@ public class ErhaAPI {
// Send request
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
uhr.setStatusCode(response.statusCode());
uhr.setBody(response.body());
if (printdebug){
System.out.println("Upload_File status code : " + response.statusCode());
System.out.println("Upload_File HTTP body : ");
@@ -167,7 +179,8 @@ public class ErhaAPI {
if (response.statusCode()==200){
return gson.fromJson(response.body(), UploadResult.class);
UploadResult ur = gson.fromJson(response.body(), UploadResult.class);
uhr.setResult(ur);
} else {
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 static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
@SuppressWarnings({"unused"})
@@ -157,6 +156,8 @@ public class Cameradetail {
private boolean use_qr = false;
private boolean use_face = false;
private @Getter Detectors detector;
private void setSliderValue(Slider sld, CameraProperty prop, double value){
if (sld!=null){
@@ -239,6 +240,8 @@ public class Cameradetail {
raise_log("Exposure for "+getCameraTitle()+" changed to "+newVal);
});
detector = new Detectors();
}
@FXML
@@ -903,7 +906,7 @@ public class Cameradetail {
int _face_width = 0;
int _face_height = 0;
List<DetectorResult> frontalfaces = HaveFrontalFace(GrayMat.clone());
List<DetectorResult> frontalfaces = detector.HaveFrontalFace(GrayMat.clone());
if (!frontalfaces.isEmpty()){
for(DetectorResult rect : frontalfaces){
if (rect.haveFace() ){
@@ -921,7 +924,7 @@ public class Cameradetail {
} else {
// gak punya frontal face
// coba cek punya profile left face 45 gak
List<DetectorResult> Left45Faces = HaveLeft45Face(GrayMat.clone());
List<DetectorResult> Left45Faces = detector.HaveLeft45Face(GrayMat.clone());
if (!Left45Faces.isEmpty()){
for(DetectorResult rect : Left45Faces){
if (rect.haveFace()){

View File

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

View File

@@ -20,16 +20,23 @@ public class Detectors {
private static Size FaceminSize;
private static Size FacemaxSize;
public static void LoadAllDetectors(){
public Detectors(){
LoadFrontalFaceDetector();
LoadEyeDetector();
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");
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
if (filename!=null) {
@@ -46,7 +53,7 @@ public class Detectors {
} else Logger.error("Unable to extract face detector file");
}
private static void LoadProfileFaceDetector(){
private void LoadProfileFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml");
if (filename!=null) {
Logger.info("Profile Face Detector file : " + filename);
@@ -62,7 +69,7 @@ public class Detectors {
} else Logger.error("Unable to extract profile face detector file");
}
private static void LoadEyeDetector(){
private void LoadEyeDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_eye.xml");
if (filename!=null) {
Logger.info("Eye Detector file : " + filename);
@@ -84,7 +91,7 @@ public class Detectors {
* @param graymat Mat in Gray Scale
* @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<>();
RectVector faces = DetectFrontalFace(graymat);
if (faces!=null && faces.size()>0){
@@ -106,7 +113,7 @@ public class Detectors {
return result;
}
public static @NonNull List<DetectorResult> HaveLeft45Face(Mat graymat){
public @NonNull List<DetectorResult> HaveLeft45Face(Mat graymat){
List<DetectorResult> result = new ArrayList<>();
RectVector faces = DetectProfileFace(graymat);
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;
}
public static void setFaceMinSize(int value){
public void setFaceMinSize(int value){
if (FaceminSize!=null){
if (FaceminSize.width()!=value || FaceminSize.height()!=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.width()!=value || FacemaxSize.height()!=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);
}
@@ -169,7 +176,7 @@ public class Detectors {
* @param graymat Mat in Gray Scale
* @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);
}
@@ -179,7 +186,7 @@ public class Detectors {
* @param graymat Mat in Gray Scale
* @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);
int minwidth = (int)(facewidth*0.2);
int maxwidth = (int)(facewidth*0.4);
@@ -189,7 +196,7 @@ public class Detectors {
}
@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 (graymat!=null && graymat.channels()==1 && !graymat.empty()){
if (minSize!=null && maxSize!=null){

View File

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

View File

@@ -239,9 +239,20 @@ public class SettingView {
config.setCascadeScaleFactor(scale);
config.Save();
Detectors.setFaceMaxSize(max);
Detectors.setFaceMinSize(min);
Detectors.setScaleFactor(scale);
if (MainApplication.detectorsList!=null){
MainApplication.detectorsList.forEach((i,d)-> {
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");
} else show_cascade_alert("Max Size must be greater than Min Size");