commit 22/07/2025
This commit is contained in:
Binary file not shown.
@@ -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;
|
||||
|
||||
10
src/main/java/ErhaAPI/BarcodeHttpResult.java
Normal file
10
src/main/java/ErhaAPI/BarcodeHttpResult.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package ErhaAPI;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BarcodeHttpResult {
|
||||
private int statusCode;
|
||||
private String body;
|
||||
private BarcodeResult result;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package ErhaAPI;
|
||||
|
||||
|
||||
public class BarcodeResullt {
|
||||
public class BarcodeResult {
|
||||
public int currentPage;
|
||||
public int limit;
|
||||
public int totalPages;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
10
src/main/java/ErhaAPI/UploadHttpResult.java
Normal file
10
src/main/java/ErhaAPI/UploadHttpResult.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package ErhaAPI;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UploadHttpResult {
|
||||
int statusCode;
|
||||
String body;
|
||||
UploadResult result;
|
||||
}
|
||||
@@ -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()){
|
||||
|
||||
@@ -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")) {
|
||||
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");
|
||||
|
||||
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.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");
|
||||
}
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user