# Conflicts:
#	out/artifacts/ErhaCam_jar/ErhaCam.jar
This commit is contained in:
2025-04-09 12:35:06 +07:00
11 changed files with 244 additions and 188 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -103,7 +103,7 @@ public class AudioPlayer {
* @param playbackstatus PlaybackStatus callback * @param playbackstatus PlaybackStatus callback
*/ */
public void PlayFile(final String filename, final PlaybackStatus playbackstatus){ public void PlayFile(final String filename, final PlaybackStatus playbackstatus){
if (inited && filename!=null && !filename.isEmpty()){ if (inited && filename!=null && !filename.isBlank()){
int filehandle = bass.BASS_StreamCreateFile(false, filename, 0, 0, 0); int filehandle = bass.BASS_StreamCreateFile(false, filename, 0, 0, 0);
if (filehandle!=0){ if (filehandle!=0){
if (bass.BASS_ChannelStart(filehandle)){ if (bass.BASS_ChannelStart(filehandle)){

View File

@@ -5,12 +5,9 @@ public interface LiveCamEvent {
void onFrontalFaceDetector(boolean hasface, int width, int height); void onFrontalFaceDetector(boolean hasface, int width, int height);
void onProfileFaceDetector(boolean hasface, int width, int height); void onProfileFaceDetector(boolean hasface, int width, int height);
void onEyeDetector(boolean hasEye); void onEyeDetector(boolean hasEye);
void onLeftEarDetector(boolean hasLeftEar, int width, int height);
void onRightEarDetector(boolean hasRightEar, int width, int height);
void onLeftEyeDetector(boolean hasLeftEye, int width, int height);
void onRightEyeDetector(boolean hasRightEye, int width, int height);
void onLog(String log); void onLog(String log);
void onBlink(int counter); void onBlink(int counter);
void onDoubleBlink(int counter);
void onStartCapturing(); void onStartCapturing();
void onIntervalUpdate(); void onIntervalUpdate();
} }

View File

@@ -413,7 +413,7 @@ public class SomeCodes {
*/ */
public static boolean ValidString(String x){ public static boolean ValidString(String x){
if (x!=null){ if (x!=null){
return !x.isEmpty(); return !x.isBlank();
} }
return false; return false;
} }
@@ -490,7 +490,7 @@ public class SomeCodes {
* @return true if valid, false if not valid * @return true if valid, false if not valid
*/ */
public static boolean ValidMedicalRecordId(String patientid){ public static boolean ValidMedicalRecordId(String patientid){
if (patientid!=null && !patientid.isEmpty()){ if (patientid!=null && !patientid.isBlank()){
boolean valid = true; boolean valid = true;
for(int i=0; i<patientid.length(); i++){ for(int i=0; i<patientid.length(); i++){
if (!Character.isDigit(patientid.charAt(i))){ if (!Character.isDigit(patientid.charAt(i))){
@@ -605,23 +605,29 @@ public class SomeCodes {
} }
public static void SetText(Object obj, String text){ public static void SetText(Object obj, String text){
if (obj!=null && text!=null){ if (obj!=null && ValidString(text)){
if (Platform.isFxApplicationThread()){ if (Platform.isFxApplicationThread()){
if (obj instanceof Label){ if (obj instanceof Label lbl){
((Label) obj).setText(text); if (text.equals(lbl.getText())) return;
} else if (obj instanceof TextArea){ lbl.setText(text);
((TextArea) obj).setText(text); } else if (obj instanceof TextArea ta){
} else if (obj instanceof TextField){ if (text.equals(ta.getText())) return;
((TextField) obj).setText(text); ta.setText(text);
} else if (obj instanceof TextField tf){
if (text.equals(tf.getText())) return;
tf.setText(text);
} }
} else{ } else{
Platform.runLater(()->{ Platform.runLater(()->{
if (obj instanceof Label){ if (obj instanceof Label lbl){
((Label) obj).setText(text); if (text.equals(lbl.getText())) return;
} else if (obj instanceof TextArea){ lbl.setText(text);
((TextArea) obj).setText(text); } else if (obj instanceof TextArea ta){
} else if (obj instanceof TextField){ if (text.equals(ta.getText())) return;
((TextField) obj).setText(text); ta.setText(text);
} else if (obj instanceof TextField tf){
if (text.equals(tf.getText())) return;
tf.setText(text);
} }
}); });
} }

View File

@@ -8,8 +8,12 @@ import javafx.scene.Scene;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Modality; import javafx.stage.Modality;
import javafx.stage.Screen; import javafx.stage.Screen;
import javafx.stage.Stage; import javafx.stage.Stage;
@@ -32,6 +36,11 @@ public class AutoCloseAlert {
public static Image shownBanner = null; public static Image shownBanner = null;
public static Image banner_01; public static Image banner_01;
public static Image banner_02; public static Image banner_02;
private static Circle Cam1;
private static Circle Cam2;
private static Circle Cam3;
private static Circle Cam4;
private static Circle Cam5;
public static void init(){ public static void init(){
String f_01 = ExtractResource("/IU photoboth-01.jpg"); String f_01 = ExtractResource("/IU photoboth-01.jpg");
@@ -42,6 +51,29 @@ public class AutoCloseAlert {
if (banner_01!=null) System.out.println("Banner 01 loaded"); else System.out.println("Banner 01 not loaded"); if (banner_01!=null) System.out.println("Banner 01 loaded"); else System.out.println("Banner 01 not loaded");
banner_02 = LoadImage(f_02); banner_02 = LoadImage(f_02);
if (banner_02!=null) System.out.println("Banner 02 loaded"); else System.out.println("Banner 02 not loaded"); if (banner_02!=null) System.out.println("Banner 02 loaded"); else System.out.println("Banner 02 not loaded");
Cam1 = new Circle(10, Color.RED);
Cam2 = new Circle(10, Color.RED);
Cam3 = new Circle(10, Color.RED);
Cam4 = new Circle(10, Color.RED);
Cam5 = new Circle(10, Color.RED);
}
public static void ChangeCamStatus(int id, boolean active){
Circle x = switch (id){
case 1 -> Cam1;
case 2 -> Cam2;
case 3 -> Cam3;
case 4 -> Cam4;
case 5 -> Cam5;
default -> null;
};
if (x!=null){
if (active){
x.setFill(Color.GREEN);
} else {
x.setFill(Color.RED);
}
}
} }
@@ -63,10 +95,16 @@ public class AutoCloseAlert {
* @param onClose What to do after auto close * @param onClose What to do after auto close
*/ */
public static void show(String title, String content, int seconds, Consumer<String> onClose){ public static void show(String title, String content, int seconds, Consumer<String> onClose){
if (Platform.isFxApplicationThread()){
Stage alertStage = _showtext(title, "", content);
closeAlertStage(seconds, onClose, alertStage);
} else {
Platform.runLater(()->{ Platform.runLater(()->{
Stage alertStage = _showtext(title, "", content); Stage alertStage = _showtext(title, "", content);
closeAlertStage(seconds, onClose, alertStage); closeAlertStage(seconds, onClose, alertStage);
}); });
}
} }
@@ -82,18 +120,35 @@ public class AutoCloseAlert {
* @param onClose What to do after auto close * @param onClose What to do after auto close
*/ */
public static void show(String title, String header, String content, int seconds, Consumer<String> onClose) { public static void show(String title, String header, String content, int seconds, Consumer<String> onClose) {
if (Platform.isFxApplicationThread()){
Stage alertStage = _showtext(title, header, content);
closeAlertStage(seconds, onClose, alertStage);
} else {
Platform.runLater(()->{ Platform.runLater(()->{
Stage alertStage = _showtext(title, header, content); Stage alertStage = _showtext(title, header, content);
closeAlertStage(seconds, onClose, alertStage); closeAlertStage(seconds, onClose, alertStage);
}); });
} }
}
/**
* Show a banner image
* @param b1 Image to show
* @param seconds the number of seconds before the alert is closed, or put 0 to keep it open
* @param onClose What to do after auto close
*/
public static void showbanner(Image b1, int seconds, Consumer<String> onClose){ public static void showbanner(Image b1, int seconds, Consumer<String> onClose){
if (Platform.isFxApplicationThread()){
Stage alertStage = _showbanner(b1);
closeAlertStage(seconds, onClose, alertStage);
} else {
Platform.runLater(()->{ Platform.runLater(()->{
Stage alertStage = _showbanner(b1); Stage alertStage = _showbanner(b1);
closeAlertStage(seconds, onClose, alertStage); closeAlertStage(seconds, onClose, alertStage);
}); });
} }
}
private static Stage _showbanner(Image image){ private static Stage _showbanner(Image image){
close(); close();
@@ -103,24 +158,41 @@ public class AutoCloseAlert {
alertStage.initStyle(StageStyle.UTILITY); alertStage.initStyle(StageStyle.UTILITY);
alertStage.setAlwaysOnTop(true); alertStage.setAlwaysOnTop(true);
alertStage.setResizable(false); alertStage.setResizable(false);
//System.out.println("_showbanner creating stage"); int width = (int) Screen.getPrimary().getBounds().getWidth();
int height = (int) Screen.getPrimary().getBounds().getHeight();
BorderPane borderPane = new BorderPane();
StackPane stackPane = new StackPane();
if (image!=null){ if (image!=null){
ImageView imageView = new ImageView(image); ImageView imageView = new ImageView(image);
imageView.setPreserveRatio(true); imageView.setPreserveRatio(true);
imageView.setFitWidth(1280); imageView.setFitWidth(width);
imageView.setSmooth(true); imageView.setSmooth(true);
StackPane stackPane = new StackPane(imageView); stackPane.getChildren().add(imageView);
alertStage.setScene(new Scene(stackPane, 1280, 720)); }
//System.out.println("_showbanner setscene"); HBox CamStatus = new HBox(30, Cam1, Cam2, Cam3, Cam4, Cam5);
} //else System.out.println("_showbanner not setscene because image is null"); CamStatus.setMinHeight(60);
CamStatus.setAlignment(Pos.CENTER);
VBox vBox = new VBox(CamStatus);
vBox.setAlignment(Pos.BOTTOM_CENTER);
stackPane.getChildren().add(vBox);
borderPane.setCenter(stackPane);
alertStage.setScene(new Scene(borderPane, width, height));
alertStage.centerOnScreen(); alertStage.centerOnScreen();
alertStage.show(); alertStage.show();
//System.out.println("_showbanner show stage");
currentAlertStage = alertStage; currentAlertStage = alertStage;
shownBanner = image; shownBanner = image;
CamStatus.prefWidthProperty().bind(currentAlertStage.widthProperty());
shownTitle = ""; shownTitle = "";
shownContent = ""; shownContent = "";
shownHeader = ""; shownHeader = "";
@@ -147,20 +219,22 @@ public class AutoCloseAlert {
alertStage.setAlwaysOnTop(true); alertStage.setAlwaysOnTop(true);
alertStage.setResizable(false); alertStage.setResizable(false);
double screenwidth = Screen.getPrimary().getVisualBounds().getWidth(); double screenwidth = Screen.getPrimary().getBounds().getWidth();
double width = screenwidth/4; double screenheight = Screen.getPrimary().getBounds().getHeight();
double height = width * 9 / 16;
double height = screenheight/4;
double width = height * 21/9;
List<Node> children = new ArrayList<>(); List<Node> children = new ArrayList<>();
if (ValidString(header)){ if (ValidString(header)){
Label headerLabel = new Label(header); Label headerLabel = new Label(header);
headerLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16px;"); headerLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 28px;");
headerLabel.setMinHeight(height*0.25); headerLabel.setMinHeight(height*0.25);
children.add(headerLabel); children.add(headerLabel);
} }
if (ValidString(content)){ if (ValidString(content)){
Label contentLabel = new Label(content); Label contentLabel = new Label(content);
contentLabel.setStyle("-fx-font-size: 12px;"); contentLabel.setStyle("-fx-font-size: 24px;");
contentLabel.setMinHeight(height*0.75); contentLabel.setMinHeight(height*0.75);
children.add(contentLabel); children.add(contentLabel);
} }
@@ -174,6 +248,11 @@ public class AutoCloseAlert {
alertStage.setTitle(title); alertStage.setTitle(title);
double x = screenwidth/2 - width/2;
double y = screenheight - height - 10;
alertStage.setX(x);
alertStage.setY(y);
alertStage.show(); alertStage.show();
currentAlertStage = alertStage; currentAlertStage = alertStage;
shownHeader = ValidString(header) ? header : ""; shownHeader = ValidString(header) ? header : "";

View File

@@ -108,6 +108,9 @@ public class Cameradetail {
@FXML @FXML
private Label eye_indicator; private Label eye_indicator;
@FXML
private Label BlinkCounterLabel;
@FXML @FXML
private Label sharpness_indicator; private Label sharpness_indicator;
@@ -604,7 +607,7 @@ public class Cameradetail {
public boolean PutText(UMat Mat, String text, double fontScale, Scalar textColor, int thickness){ public boolean PutText(UMat Mat, String text, double fontScale, Scalar textColor, int thickness){
if (!Mat.empty()){ if (!Mat.empty()){
if (text!=null && !text.isEmpty()){ if (text!=null && !text.isBlank()){
//String timestamp = prefix+" "+SomeCodes.GetDateTimeString(); //String timestamp = prefix+" "+SomeCodes.GetDateTimeString();
int fontFace = FONT_HERSHEY_SIMPLEX; int fontFace = FONT_HERSHEY_SIMPLEX;
//double fontScale = 4.0; //double fontScale = 4.0;
@@ -625,7 +628,7 @@ public class Cameradetail {
public boolean PutText(Mat Mat, String text, double fontScale, Scalar textColor, int thickness){ public boolean PutText(Mat Mat, String text, double fontScale, Scalar textColor, int thickness){
if (!Mat.empty()){ if (!Mat.empty()){
if (text!=null && !text.isEmpty()){ if (text!=null && !text.isBlank()){
//String timestamp = prefix+" "+SomeCodes.GetDateTimeString(); //String timestamp = prefix+" "+SomeCodes.GetDateTimeString();
int fontFace = FONT_HERSHEY_SIMPLEX; int fontFace = FONT_HERSHEY_SIMPLEX;
//double fontScale = 4.0; //double fontScale = 4.0;
@@ -791,34 +794,6 @@ public class Cameradetail {
IsGrabbingLiveView.set(false); IsGrabbingLiveView.set(false);
} }
// public Rect GetFace(UMat mat, boolean isfrontal){
// if (!mat.empty()){
// Mat originalmat = new Mat();
// mat.copyTo(originalmat);
// Mat graymat = new Mat();
// opencv_imgproc.cvtColor(originalmat,graymat, COLOR_BGR2GRAY); // convert to grayscale
// int size = Math.min(graymat.cols(), graymat.rows());
// int minsize = (int) (size * 0.4);
// int maxsize = (int) (size * 0.9);
// System.out.println("GetFace size = "+size+" minsize = "+minsize+" maxsize = "+maxsize);
// RectVector faces = isfrontal ? Detectors.DetectFrontalFace(graymat, minsize, maxsize) : Detectors.DetectProfileFace(graymat, minsize, maxsize);
// if (faces.size()>0){
// Rect result = null;
// for(Rect xx : faces.get()){
// if (result==null){
// result = xx;
// } else {
// if (xx.area()>result.area()){
// result = xx;
// }
// }
// }
// return result;
// }
// } else raise_log("GetFace failed, Mat is empty");
// return null;
// }
public boolean StartLiveView(LiveCamEvent event, String cameratitle, final boolean use_qr , final boolean use_face) { public boolean StartLiveView(LiveCamEvent event, String cameratitle, final boolean use_qr , final boolean use_face) {
this.event = event; this.event = event;
if (mGrabber != null) { if (mGrabber != null) {
@@ -861,7 +836,16 @@ public class Cameradetail {
if (fpsval!=LiveFPS){ if (fpsval!=LiveFPS){
LiveFPS = fpsval; LiveFPS = fpsval;
if (event!=null) event.onIntervalUpdate(); if (event!=null) event.onIntervalUpdate();
AutoCloseAlert.ChangeCamStatus(switch (cameratitle){
case "01" -> 1;
case "02" -> 2;
case "03" -> 3;
case "04" -> 4;
case "05" -> 5;
default -> 0;
}, LiveFPS>0 );
} }
} }
}; };
@@ -881,8 +865,9 @@ public class Cameradetail {
boolean have_fist = false; boolean have_fist = false;
int no_face_counter = 0; int no_face_counter = 0;
int face_counter = 0; int face_counter = 0;
//int open_eye_counter = 0; int blink_counter = 0;
//int close_eye_counter = 0; int have_eye_counter = 0;
int no_eye_counter = 0;
while (Capturing.get()) { while (Capturing.get()) {
try { try {
@@ -899,7 +884,7 @@ public class Cameradetail {
} catch (Exception e){ } catch (Exception e){
frame = null; frame = null;
if (e.getMessage()!=null && !e.getMessage().isEmpty()){ if (e.getMessage()!=null && !e.getMessage().isBlank()){
String msg = e.getMessage(); String msg = e.getMessage();
if (msg.contains("start() been called")){ if (msg.contains("start() been called")){
if (Capturing.get()){ if (Capturing.get()){
@@ -1008,13 +993,15 @@ public class Cameradetail {
if (theface.haveEyes()){ if (theface.haveEyes()){
// ada mata (buka mata) // ada mata (buka mata)
// close_eye_counter=0; // if (have_eye_counter<1){
// if (open_eye_counter<1){ // have_eye_counter++;
// open_eye_counter++;
// continue; // continue;
// } // }
//System.out.println("Valid Open Eyes"); // no_eye_counter = 0;
//System.out.println("Valid Eye Detected from camera "+cameratitle);
if (event!=null) event.onEyeDetector(true);
LabelVisible(eye_indicator,true);
// Valid eye condition
if (eye_state!=1){ if (eye_state!=1){
// transisi dari tutup mata ke buka mata // transisi dari tutup mata ke buka mata
@@ -1025,17 +1012,20 @@ public class Cameradetail {
} }
System.out.println("Transition from close to open eyes"); System.out.println("Transition from close to open eyes");
eye_state = 1; eye_state = 1;
if (event!=null) event.onEyeDetector(true);
LabelVisible(eye_indicator,true); blink_counter++;
if (event!=null) event.onBlink(blink_counter);
SetText(BlinkCounterLabel, String.valueOf(blink_counter));
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
if (waiting_for_second_blink){ if (waiting_for_second_blink){
long diff = now - last_blink; long diff = now - last_blink;
// kalau beda waktu antara blink 1 dan blink 2 kurang dari 2 detik // kalau beda waktu antara blink 1 dan blink 2 kurang dari 3 detik
if (diff<=2000){ if (diff<=3000){
System.out.println("Double Blink Detected from camera "+cameratitle); System.out.println("Double Blink Detected from camera "+cameratitle);
if (event!=null) event.onBlink((int)diff); if (event!=null) event.onDoubleBlink((int)diff);
} }
waiting_for_second_blink = false; waiting_for_second_blink = false;
} else { } else {
@@ -1047,17 +1037,20 @@ public class Cameradetail {
} else { } else {
// ada muka, tidak ada mata // ada muka, tidak ada mata
// transisi dari buka mata ke tutup mata // transisi dari buka mata ke tutup mata
// open_eye_counter=0; // if (no_eye_counter<1){
// if (close_eye_counter<1){ // no_eye_counter++;
// close_eye_counter++;
// continue; // continue;
// } // }
//System.out.println("Valid Closed Eyes"); // have_eye_counter = 0;
//System.out.println("Valid No Eye Detected from camera "+cameratitle);
if (event!=null) event.onEyeDetector(false);
LabelVisible(eye_indicator,false);
// Valid no eye condition
if (eye_state!=0){ if (eye_state!=0){
System.out.println("Transition from open to close eyes"); System.out.println("Transition from open to close eyes");
eye_state = 0; eye_state = 0;
if (event!=null) event.onEyeDetector(false);
LabelVisible(eye_indicator,false);
} }
} }
} else if (have_left_45_face ){ } else if (have_left_45_face ){
@@ -1065,29 +1058,35 @@ public class Cameradetail {
if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height); if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height);
LabelVisible(face_indicator,true); LabelVisible(face_indicator,true);
} else { } else {
// no face detected, but let's not cancel the previous state immediately // no face detected, but let's not cancel the previous state immediately
if (no_face_counter>90){ if (no_face_counter<60){
// kalau tidak ada face selama 30 frame, reset state // toleransi no face selama 60 frame
// 30 frame approximately 2 second no_face_counter++;
continue;
} else {
// beneran dianggap no face detected
eye_state = -1; eye_state = -1;
last_blink = 0; last_blink = 0;
waiting_for_second_blink = false; waiting_for_second_blink = false;
face_counter = 0; face_counter = 0;
// if (close_eye_counter!=0 || open_eye_counter!=0){ blink_counter = 0;
// close_eye_counter=0; no_eye_counter=0;
// open_eye_counter=0; have_eye_counter=0;
// System.out.println("Reset Open and Close Eyes");
// }
if (event!=null) { if (event!=null) {
event.onFrontalFaceDetector(false, _face_width, _face_height); event.onFrontalFaceDetector(false, _face_width, _face_height);
event.onProfileFaceDetector(false, _face_width, _face_height); event.onProfileFaceDetector(false, _face_width, _face_height);
event.onEyeDetector(false);
event.onBlink(blink_counter);
SetText(BlinkCounterLabel, "");
LabelVisible(face_indicator,false); LabelVisible(face_indicator,false);
LabelVisible(eye_indicator,false); LabelVisible(eye_indicator,false);
} }
} else no_face_counter++; }
} }

View File

@@ -25,10 +25,7 @@ import javafx.stage.DirectoryChooser;
import java.util.*; import java.util.*;
import java.util.concurrent.Callable; import java.util.concurrent.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Alert.AlertType;
@@ -91,6 +88,11 @@ public class CaptureView {
private final ErhaAPI erhaAPI = new ErhaAPI(false); private final ErhaAPI erhaAPI = new ErhaAPI(false);
// for timeout 180 detik
private final int timeout = 180;
ScheduledExecutorService timeoutExecutor = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> runningTask = null;
private void TakePhotoButtonChange(){ private void TakePhotoButtonChange(){
boolean disabled = false; boolean disabled = false;
String barcode = barcodeData.getText(); String barcode = barcodeData.getText();
@@ -552,6 +554,7 @@ public class CaptureView {
@Override @Override
public void onPlaybackFinished(String filename) { public void onPlaybackFinished(String filename) {
UploadFiles(prc, prefix); UploadFiles(prc, prefix);
if (runningTask!=null) runningTask.cancel(false);
} }
@Override @Override
@@ -569,6 +572,8 @@ public class CaptureView {
audioPlayer.PlayFile(audio_pengambilan_gagal, null); audioPlayer.PlayFile(audio_pengambilan_gagal, null);
} }
} }
clear();
if (runningTask!=null) runningTask.cancel(false);
} }
} }
@@ -609,14 +614,8 @@ public class CaptureView {
uploadtask.setOnSucceeded(e-> { uploadtask.setOnSucceeded(e-> {
System.out.println("UploadTask succeeded"); System.out.println("UploadTask succeeded");
Platform.runLater(()->{ clear();
AutoCloseAlert.close(); AutoCloseAlert.close();
barcodeData.setText("");
medicalRecordID.setText("");
PatientName.setText("");
isTakingPhoto.set(false);
});
}); });
uploadtask.setOnFailed(e-> { uploadtask.setOnFailed(e-> {
@@ -628,12 +627,7 @@ public class CaptureView {
} }
} }
AutoCloseAlert.show("Upload Failed", "Upload Failed", "Upload Failed", 5, s -> { AutoCloseAlert.show("Upload Failed", "Upload Failed", "Upload Failed", 5, s -> {
isTakingPhoto.set(false); clear();
Platform.runLater(()->{
barcodeData.setText("");
medicalRecordID.setText("");
PatientName.setText("");
});
}); });
}); });
@@ -674,7 +668,7 @@ public class CaptureView {
medicalRecordID.textProperty().addListener((observable, oldValue, newValue) -> TakePhotoButtonChange()); medicalRecordID.textProperty().addListener((observable, oldValue, newValue) -> TakePhotoButtonChange());
PatientName.textProperty().addListener((observable, oldValue, newValue) -> TakePhotoButtonChange()); PatientName.textProperty().addListener((observable, oldValue, newValue) -> TakePhotoButtonChange());
barcodeData.setText("");
audioPlayer = new AudioPlayer(1,48000); audioPlayer = new AudioPlayer(1,48000);
Logger.info("Audio Player : "+(audioPlayer.isInited()? "Inited" : "Not Inited")); Logger.info("Audio Player : "+(audioPlayer.isInited()? "Inited" : "Not Inited"));
@@ -698,6 +692,13 @@ public class CaptureView {
LoadCameraDetail(cam5, 5, CameraConfigEnum.CameraConfigRight90); LoadCameraDetail(cam5, 5, CameraConfigEnum.CameraConfigRight90);
Platform.runLater(()->{ Platform.runLater(()->{
if (!Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
if (AutoCloseAlert.banner_01!=null){
System.out.println("Showing banner 01 for first time");
AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0,null);
}
}
int indexleft90=-1; int indexleft90=-1;
int indexleft45=-1; int indexleft45=-1;
int indexcenter=-1; int indexcenter=-1;
@@ -770,6 +771,16 @@ public class CaptureView {
}); });
}
private void clear(){
isTakingPhoto.set(false);
Platform.runLater(()->{
medicalRecordID.setText("");
PatientName.setText("");
barcodeData.setText("");
});
} }
public void Unload(){ public void Unload(){
@@ -879,8 +890,10 @@ public class CaptureView {
if (ValidBarCode(barCode)){ if (ValidBarCode(barCode)){
String prefix = barcodeData.getText(); String prefix = barcodeData.getText();
if (!barCode.equals(prefix)){ if (!barCode.equals(prefix)){
String finalbarCode = barCode; final String finalbarCode = barCode;
Platform.runLater(()-> barcodeData.setText(finalbarCode)); Platform.runLater(()->{
barcodeData.setText(finalbarCode);
});
Task<PatientRecord> checkpatientID = new Task<>() { Task<PatientRecord> checkpatientID = new Task<>() {
@Override @Override
protected PatientRecord call() throws Exception { protected PatientRecord call() throws Exception {
@@ -889,8 +902,8 @@ public class CaptureView {
if (br.message.startsWith("Records found")){ if (br.message.startsWith("Records found")){
if (br.data!=null && br.data.length>0){ if (br.data!=null && br.data.length>0){
PatientRecord pr = br.data[0]; PatientRecord pr = br.data[0];
if (!pr.medical_record_detail_id.isEmpty()){ if (!pr.medical_record_detail_id.isBlank()){
if (!pr.name.isEmpty()){ if (!pr.name.isBlank()){
super.succeeded(); super.succeeded();
return pr; return pr;
} else { } else {
@@ -922,12 +935,18 @@ public class CaptureView {
checkpatientID.setOnSucceeded(event -> { checkpatientID.setOnSucceeded(event -> {
PatientRecord pr = checkpatientID.getValue(); PatientRecord pr = checkpatientID.getValue();
if (pr!=null){ if (pr!=null){
Platform.runLater(()->{
int medrecid = toInt(pr.medical_record_detail_id); int medrecid = toInt(pr.medical_record_detail_id);
medicalRecordID.setText(medrecid+""); System.out.println("checkpatientID.setOnSucceeded medrecid : "+medrecid);
Platform.runLater(()->{
medicalRecordID.setText(""+medrecid);
PatientName.setText(pr.name); PatientName.setText(pr.name);
}); });
runningTask = timeoutExecutor.schedule(()->{
// timeout
clear();
}, timeout, TimeUnit.SECONDS);
if (audioPlayer!=null && audioPlayer.isInited()){ if (audioPlayer!=null && audioPlayer.isInited()){
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_posisikan_muka)) { if (!Objects.equals(audioPlayer.getCurrentFile(),audio_posisikan_muka)) {
audioPlayer.StopCurrentPlayback(); audioPlayer.StopCurrentPlayback();
@@ -952,12 +971,7 @@ public class CaptureView {
AutoCloseAlert.show("Data Tidak Ditemukan", message, "Pastikan data barcode anda benar", 5, s -> { AutoCloseAlert.show("Data Tidak Ditemukan", message, "Pastikan data barcode anda benar", 5, s -> {
isTakingPhoto.set(false); clear();
Platform.runLater(()->{
medicalRecordID.setText("");
PatientName.setText("");
barcodeData.setText("");
});
}); });
}); });
@@ -1002,26 +1016,6 @@ public class CaptureView {
//update_status(image); //update_status(image);
} }
@Override
public void onLeftEarDetector(boolean hasLeftEar, int width, int height) {
}
@Override
public void onRightEarDetector(boolean hasRightEar, int width, int height) {
}
@Override
public void onLeftEyeDetector(boolean hasLeftEye, int width, int height) {
}
@Override
public void onRightEyeDetector(boolean hasRightEye, int width, int height) {
}
@Override @Override
public void onLog(String log) { public void onLog(String log) {
String ss = String.format("[%s] : %s", title, log); String ss = String.format("[%s] : %s", title, log);
@@ -1030,50 +1024,20 @@ public class CaptureView {
@Override @Override
public void onBlink(int counter) { public void onBlink(int counter) {
System.out.println("Blink detected at camera "+title+" delay= "+counter);
}
@Override
public void onDoubleBlink(int counter) {
System.out.println("Double Blink detected at camera "+title+" delay= "+counter);
if (audioPlayer!=null && audioPlayer.isPlaying()) return; // let audio finish playback if (audioPlayer!=null && audioPlayer.isPlaying()) return; // let audio finish playback
if (isTakingPhoto.get()) return; // other camera is taking picture if (isTakingPhoto.get()) return; // other camera is taking picture
// revisi 08/04/2025 // revisi 08/04/2025
TakePhotos(); TakePhotos();
// String directory = config.getPhotoDirectory();
// String prefix = RemoveSpaces(medicalRecordID.getText()) ;
// if (ValidDirectory(directory)){
// if (ValidMedicalRecordId(prefix)){
// isTakingPhoto.set(true);
// TakePhotos();
// } else {
// System.out.println("Prefix invalid, not taking photo");
// isTakingPhoto.set(false);
// //AutoCloseAlert.show("QR Code Not Available", "", "Please scan QR before continue", 5, s -> AutoCloseAlert.show("Scan Barcode", "Silahkan Scan Barcode Anda", "Arahkan kertas barcode ke kamera", 0, null));
// if (!Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
// if (AutoCloseAlert.banner_01!=null){
// System.out.println("Showing banner 01 because prefix invalid");
// AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0,null);
// }
// }
// if (audioPlayer!=null && audioPlayer.isInited()){
// if (!Objects.equals(audioPlayer.getCurrentFile(), audio_scan_barcode)) {
// audioPlayer.StopCurrentPlayback();
// audioPlayer.PlayFile(audio_scan_barcode, null);
// }
// }
// }
// } else {
// System.out.println("Photo Directory invalid, not taking photo");
// isTakingPhoto.set(false);
// AutoCloseAlert.show("Invalid Photo Directory","Photo Directory not set", "Please set photo directory at Setting", 5, s -> AutoCloseAlert.show("Setting", "Setting", "Please set photo directory", 0, null));
// }
} }
@Override @Override
public void onStartCapturing() { public void onStartCapturing() {
if (!Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
if (AutoCloseAlert.banner_01!=null){
System.out.println("Showing banner 01 for first time");
AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0,null);
}
}
} }

View File

@@ -5,6 +5,7 @@ import lombok.Setter;
import org.bytedeco.opencv.opencv_core.Rect; import org.bytedeco.opencv.opencv_core.Rect;
import org.bytedeco.opencv.opencv_core.Scalar; import org.bytedeco.opencv.opencv_core.Scalar;
import org.bytedeco.opencv.opencv_core.UMat; import org.bytedeco.opencv.opencv_core.UMat;
import org.opencv.imgproc.Imgproc;
import java.util.List; import java.util.List;
@@ -14,6 +15,9 @@ import static org.bytedeco.opencv.global.opencv_imgproc.rectangle;
public class DetectorResult { public class DetectorResult {
private @Setter Rect Face; private @Setter Rect Face;
private List<Rect> Eyes; private List<Rect> Eyes;
private final int linethickness = 3;
private final int linetype = Imgproc.LINE_8;
private final int lineshift = 0;
public void AddEye(Rect eye){ public void AddEye(Rect eye){
if (Eyes == null) Eyes = new java.util.ArrayList<>(); if (Eyes == null) Eyes = new java.util.ArrayList<>();
@@ -22,7 +26,8 @@ public class DetectorResult {
public void FaceRectangle(UMat mat){ public void FaceRectangle(UMat mat){
if (haveFace()){ if (haveFace()){
rectangle(mat, Face, Scalar.GREEN);
rectangle(mat, Face, Scalar.GREEN, linethickness, linetype, lineshift);
} }
} }

View File

@@ -32,9 +32,9 @@ public class MainApplication extends Application {
Logger.info("Secure Dongle UserID valid"); Logger.info("Secure Dongle UserID valid");
FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("main-view.fxml")); FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("main-view.fxml"));
Screen screen = Screen.getPrimary(); Screen screen = Screen.getPrimary();
Rectangle2D screenbound = screen.getVisualBounds(); Rectangle2D screenbound = screen.getBounds();
Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight()); Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight());
stage.setTitle("MultiCam Capture App for ERHA 08042025-003"); stage.setTitle("MultiCam Capture App for ERHA 09042025-002");
stage.setScene(scene); stage.setScene(scene);
stage.setResizable(true); stage.setResizable(true);
stage.setMaximized(true); stage.setMaximized(true);

View File

@@ -20,11 +20,12 @@
<children> <children>
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" prefWidth="100.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
@@ -52,9 +53,14 @@
<Label fx:id="eye_indicator" alignment="CENTER" layoutY="8.0" prefHeight="30.0" prefWidth="35.0" text="Eye" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> <Label fx:id="eye_indicator" alignment="CENTER" layoutY="8.0" prefHeight="30.0" prefWidth="35.0" text="Eye" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children> </children>
</AnchorPane> </AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="5">
<children>
<Label fx:id="sharpness_indicator" alignment="CENTER" layoutX="7.0" layoutY="8.0" prefHeight="30.0" prefWidth="35.0" style="-fx-border-color: black;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="4"> <AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="4">
<children> <children>
<Label fx:id="sharpness_indicator" alignment="CENTER" layoutX="7.0" layoutY="8.0" prefHeight="30.0" prefWidth="35.0" style="-fx-border-color: black;" text="0.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> <Label fx:id="BlinkCounterLabel" alignment="CENTER" layoutY="8.0" prefHeight="30.0" prefWidth="35.0" style="-fx-border-color: black;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children> </children>
</AnchorPane> </AnchorPane>
</children> </children>