diff --git a/.idea/artifacts/ErhaCam_jar.xml b/.idea/artifacts/ErhaCam_jar.xml
index f7fc4b1..e145d6d 100644
--- a/.idea/artifacts/ErhaCam_jar.xml
+++ b/.idea/artifacts/ErhaCam_jar.xml
@@ -3,63 +3,50 @@
$PROJECT_DIR$/out/artifacts/ErhaCam_jar
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config.properties b/config.properties
index c4abeaa..c04f7c3 100644
--- a/config.properties
+++ b/config.properties
@@ -1,4 +1,4 @@
-#Thu Feb 13 11:48:36 WIB 2025
+#Mon Mar 17 15:01:40 WIB 2025
AudioPhase1=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase1.mp3
AudioPhase2=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase2.mp3
AudioPhase3=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase3.mp3
@@ -11,7 +11,7 @@ CameraConfigLeft90={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0
CameraConfigRight45={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:1.0,"Sharpness"\:0.0,"Gamma"\:0.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigRight90={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:1.0,"Sharpness"\:0.0,"Gamma"\:0.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraLeft45=
-CameraLeft90=
+CameraLeft90=ACER QHD User Facing
CameraRight45=
CameraRight90=
FTPHost=192.168.10.2
@@ -19,7 +19,7 @@ FTPPass=password
FTPPath=/
FTPPort=21
FTPUser=user
-PhotoDirectory=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam
+PhotoDirectory=C\:\\Users\\rdkar\\OneDrive\\Desktop\\Erha Capture
cascadeMaxSize=500
cascadeMinNeighbors=3
cascadeMinSize=250
diff --git a/countdown321.wav b/countdown321.wav
deleted file mode 100644
index 2e0f9a3..0000000
Binary files a/countdown321.wav and /dev/null differ
diff --git a/out/artifacts/ErhaCam_jar/ErhaCam.jar b/out/artifacts/ErhaCam_jar/ErhaCam.jar
index 392b80c..c3d34c4 100644
Binary files a/out/artifacts/ErhaCam_jar/ErhaCam.jar and b/out/artifacts/ErhaCam_jar/ErhaCam.jar differ
diff --git a/pengambilan_berhasil.wav b/pengambilan_berhasil.wav
deleted file mode 100644
index c56c170..0000000
Binary files a/pengambilan_berhasil.wav and /dev/null differ
diff --git a/pengambilan_gagal.wav b/pengambilan_gagal.wav
deleted file mode 100644
index 4afa67b..0000000
Binary files a/pengambilan_gagal.wav and /dev/null differ
diff --git a/pom.xml b/pom.xml
index cd57724..ffccc88 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,76 +36,81 @@
${junit.version}
test
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
org.bytedeco
- javacv-platform
+ javacv
1.5.10
-
-
- org.bytedeco
- leptonica-platform
-
-
- org.bytedeco
- artoolkitplus-platform
-
-
- org.bytedeco
- libdc1394-platform
-
-
- org.bytedeco
- libfreenect-platform
-
-
- org.bytedeco
- libfreenect2-platform
-
-
- org.bytedeco
- flycapture-platform
-
-
- org.bytedeco
- librealsense-platform
-
-
- org.bytedeco
- librealsense2-platform
-
-
- org.bytedeco
- tesseract-platform
-
-
-
- org.bytedeco
- flandmark-platform
-
-
-
- org.bytedeco
- openblas-platform
-
-
-
- org.bytedeco
- ffmpeg-platform
-
-
- org.bytedeco
- videoinput-platform
-
-
- org.bytedeco
- javacpp-platform
-
-
- org.bytedeco
- opencv-platform
-
-
-
@@ -126,11 +131,6 @@
4.9.0-1.5.10
windows-x86_64
-
- org.bytedeco
- javacpp
- 1.5.10
-
org.bytedeco
javacpp
diff --git a/posisikan_wajah.wav b/posisikan_wajah.wav
deleted file mode 100644
index 18ab44d..0000000
Binary files a/posisikan_wajah.wav and /dev/null differ
diff --git a/scan_barcode.wav b/scan_barcode.wav
deleted file mode 100644
index 0d9c7f3..0000000
Binary files a/scan_barcode.wav and /dev/null differ
diff --git a/src/main/java/Config/ConfigFile.java b/src/main/java/Config/ConfigFile.java
index ce3617e..043e30b 100644
--- a/src/main/java/Config/ConfigFile.java
+++ b/src/main/java/Config/ConfigFile.java
@@ -724,11 +724,11 @@ public class ConfigFile {
private @Getter String ThumbsDirectory;
private void MakeDirectories(){
- String FullQualityDirectory = Path.of(PhotoDirectory,"FullQuality").toString();
- String FullQualityCropDirectory = Path.of(PhotoDirectory,"FullQualityCrop").toString();
- String CompressedDirectory = Path.of(PhotoDirectory,"Compressed").toString();
- String CompressedCropDirectory = Path.of(PhotoDirectory,"CompressedCrop").toString();
- String ThumbsDirectory = Path.of(PhotoDirectory,"thumbs").toString();
+ FullQualityDirectory = Path.of(PhotoDirectory,"FullQuality").toString();
+ FullQualityCropDirectory = Path.of(PhotoDirectory,"FullQualityCrop").toString();
+ CompressedDirectory = Path.of(PhotoDirectory,"Compressed").toString();
+ CompressedCropDirectory = Path.of(PhotoDirectory,"CompressedCrop").toString();
+ ThumbsDirectory = Path.of(PhotoDirectory,"thumbs").toString();
MakeDirectory(FullQualityDirectory);
MakeDirectory(FullQualityCropDirectory);
MakeDirectory(CompressedDirectory);
diff --git a/src/main/java/Config/SomeCodes.java b/src/main/java/Config/SomeCodes.java
index 46ad0f3..3aa6d09 100644
--- a/src/main/java/Config/SomeCodes.java
+++ b/src/main/java/Config/SomeCodes.java
@@ -8,6 +8,7 @@ import javafx.scene.control.Alert;
import javafx.scene.image.Image;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
+import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
@@ -29,6 +30,8 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
+import static org.bytedeco.opencv.global.opencv_core.CV_64F;
+
@SuppressWarnings("unused")
public class SomeCodes {
public final static String currentDirectory = System.getProperty("user.dir");
@@ -130,10 +133,6 @@ public class SomeCodes {
}
}
-
-
-
-
/**
* Make thumbfile from source jpg file
* @param sourcejpg source jpg file
@@ -516,6 +515,14 @@ public class SomeCodes {
return false;
}
+ public static void Print(String... x){
+ if (x!=null && x.length>0){
+ for(String xx : x){
+ System.out.println(xx);
+ }
+ }
+ }
+
/**
* Check if Region of Interest is inside UMat
* @param ROI Region of Interest
@@ -598,4 +605,50 @@ public class SomeCodes {
alert.showAndWait();
}
+ public static double CalculateSharpness(String filename){
+ if (ValidFile(filename)){
+ try(Mat mat = opencv_imgcodecs.imread(filename)){
+ return CalculateSharpness(new UMat(mat));
+ } catch (Exception e){
+ Logger.error("Error calculating sharpness: "+filename+", Msg : "+e.getMessage());
+ }
+ }
+ return 0;
+ }
+
+ public static double FindLowestValue(double... values){
+ if (values!=null && values.length>0){
+ double lowest = values[0];
+ for(double x : values){
+ if (x response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode()==200){
String body = response.body();
+ if (printdebug){
+ System.out.println("Validate_Barcode status code : " + response.statusCode());
+ System.out.println("Validate_Barcode HTTP body : ");
+ System.out.println(body);
+ }
return gson.fromJson(body, BarcodeResullt.class);
- } else System.out.println("Validate Barcode status code : " + response.statusCode());
+ } else {
+ Logger.error("Validate_Barcode failed, status code : " , response.statusCode());
+ System.out.println("Validate Barcode status code : " + response.statusCode());
+ }
} catch (IOException e) {
System.out.println("Validate_Barcode IO Exception, Msg : " + e.getMessage());
+ Logger.error("Validate_Barcode IO Exception, Msg : " , e.getMessage());
} catch (InterruptedException e) {
System.out.println("Validate_Barcode Interrupted Exception, Msg : " + e.getMessage());
+ Logger.error("Validate_Barcode Interrupted Exception, Msg : " , e.getMessage());
}
}
return null;
}
-// public String Upload_File_OKHttp(String patientID, String filename){
-// if (ValidMedicalRecordId(patientID)){
-// int medical_record_detail_id = toInt(patientID);
-// if (ValidFile(filename)){
-// try {
-// okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
-// okhttp3.RequestBody requestBody = new okhttp3.MultipartBody.Builder()
-// .setType(okhttp3.MultipartBody.FORM)
-// .addFormDataPart("medical_record_detail_id", String.valueOf(medical_record_detail_id))
-// .addFormDataPart("file", filename, okhttp3.RequestBody.create(okhttp3.MediaType.parse("application/octet-stream"), new java.io.File(filename)))
-// .build();
-//
-// okhttp3.Request request = new okhttp3.Request.Builder()
-// .url(API_URL + "/photobooth/photobooth")
-// .header("Authorization", "Basic " + auth)
-// .post(requestBody)
-// .build();
-//
-// okhttp3.Response response = client.newCall(request).execute();
-// if (response.isSuccessful()){
-// return response.body().string();
-// } else System.out.println("Upload_File_OKHttp status code : " + response.code());
-// } catch (Exception e){
-// System.out.println("Upload_File_OKHttp Exception, Msg : " + e.getMessage());
-// }
-// } else return "Invalid File";
-// } else return "Invalid Patient ID";
-// return null;
-// }
+
/**
@@ -129,7 +118,7 @@ public class ErhaAPI {
* @param filename File to upload
* @return null if failed, or response body if success
*/
- public UploadResult Upload_File(String patientID, String filename) {
+ public UploadResult Upload_File(String patientID, String filename, boolean printdebug) {
if (ValidMedicalRecordId(patientID)){
int medical_record_detail_id = toInt(patientID);
if (ValidFile(filename)){
@@ -173,14 +162,25 @@ public class ErhaAPI {
// Send request
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ if (printdebug){
+ System.out.println("Upload_File status code : " + response.statusCode());
+ System.out.println("Upload_File HTTP body : ");
+ System.out.println(response.body());
+ }
+
+
if (response.statusCode()==200){
return gson.fromJson(response.body(), UploadResult.class);
- } else System.out.println("Upload_File status code : " + response.statusCode());
+ } else {
+ System.out.println("Upload_File status code : " + response.statusCode());
+ Logger.error("Upload_File file ",filename," failed, status code : " , response.statusCode());
+ }
} catch (Exception e){
System.out.println("Upload_File Exception, Msg : " + e.getMessage());
+ Logger.error("Upload_File file ",filename," failed, Exception, Msg : " , e.getMessage());
}
}
}
diff --git a/src/main/java/ErhaAPI/PhotoResult.java b/src/main/java/ErhaAPI/PhotoResult.java
index b97365b..d691260 100644
--- a/src/main/java/ErhaAPI/PhotoResult.java
+++ b/src/main/java/ErhaAPI/PhotoResult.java
@@ -14,6 +14,7 @@ public class PhotoResult {
private String thumbnail;
private Rect BestROI;
private Rect ReducedROI;
+ private double sharpscore;
public PhotoResult(String cameraname){
this.cameraname = cameraname;
this.fullres = "";
diff --git a/src/main/java/id/co/gtc/erhacam/AutoCloseAlert.java b/src/main/java/id/co/gtc/erhacam/AutoCloseAlert.java
new file mode 100644
index 0000000..f9e5f58
--- /dev/null
+++ b/src/main/java/id/co/gtc/erhacam/AutoCloseAlert.java
@@ -0,0 +1,99 @@
+package id.co.gtc.erhacam;
+
+import javafx.animation.PauseTransition;
+import javafx.application.Platform;
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+import javafx.stage.Modality;
+import javafx.stage.Screen;
+import javafx.stage.Stage;
+import javafx.stage.StageStyle;
+import javafx.util.Duration;
+
+import java.util.Optional;
+
+public class AutoCloseAlert {
+
+ private static Stage currentAlertStage;
+ public static String shownTitle = "";
+ public static String shownContent = "";
+ public static String shownHeader = "";
+
+ private static void clear(){
+ shownTitle = "";
+ shownContent = "";
+ shownHeader = "";
+ }
+
+ /**
+ * Close the current alert if it is shown
+ */
+ public static void close(){
+ Optional.ofNullable(currentAlertStage).ifPresent(Stage::close);
+ currentAlertStage = null;
+ clear();
+ }
+
+ /**
+ * Show an alert with a title, header, content, and automatically close after a few seconds
+ * If called several times, the previous alert will be closed before showing a new one
+ * @param title the title of the alert
+ * @param header the header of the alert
+ * @param content the content of the alert
+ * @param seconds the number of seconds before the alert is closed, or put 0 to keep it open
+ */
+ public static void show(String title, String header, String content, int seconds) {
+ Platform.runLater(()->{
+ // close previous alert before showing a new one
+ Optional.ofNullable(currentAlertStage).ifPresent(Stage::close);
+
+ Stage alertStage = new Stage();
+ alertStage.initModality(Modality.APPLICATION_MODAL);
+ alertStage.initStyle(StageStyle.UTILITY);
+ alertStage.setAlwaysOnTop(true);
+ alertStage.setResizable(false);
+
+ double screenwidth = Screen.getPrimary().getVisualBounds().getWidth();
+ double width = screenwidth/4;
+ double height = width * 9 / 16;
+ Label headerLabel = new Label(header);
+ headerLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16px;");
+ headerLabel.setMinHeight(height*0.25);
+ Label contentLabel = new Label(content);
+ contentLabel.setStyle("-fx-font-size: 12px;");
+ contentLabel.setMinHeight(height*0.75);
+
+ VBox root = new VBox(10, headerLabel, contentLabel);
+ root.setPrefSize(width, height);
+ root.setAlignment(Pos.CENTER);
+
+ Scene scene = new Scene(root);
+ alertStage.setScene(scene);
+
+ alertStage.setTitle(title);
+ currentAlertStage = alertStage;
+
+ alertStage.show();
+
+ shownHeader = header;
+ shownContent = content;
+ shownTitle = title;
+
+ if (seconds>0){
+ PauseTransition delay = new PauseTransition(Duration.seconds(seconds));
+ delay.setOnFinished(e -> {
+ alertStage.close();
+ if (currentAlertStage == alertStage) {
+ currentAlertStage = null;
+ }
+ clear();
+ } );
+ delay.play();
+ }
+
+ });
+
+ }
+}
diff --git a/src/main/java/id/co/gtc/erhacam/Cameradetail.java b/src/main/java/id/co/gtc/erhacam/Cameradetail.java
index 4e0c87d..4958beb 100644
--- a/src/main/java/id/co/gtc/erhacam/Cameradetail.java
+++ b/src/main/java/id/co/gtc/erhacam/Cameradetail.java
@@ -31,6 +31,7 @@ import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*;
import org.opencv.videoio.Videoio;
+import org.tinylog.Logger;
import java.awt.image.BufferedImage;
@@ -48,7 +49,6 @@ import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.*;
import static org.bytedeco.opencv.global.opencv_core.CV_8UC3;
import static org.bytedeco.opencv.global.opencv_core.mean;
-import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
@SuppressWarnings({"unused"})
@@ -58,6 +58,7 @@ public class Cameradetail {
isCudaAvailable = opencv_core.getCudaEnabledDeviceCount()>0;
if (isCudaAvailable){
System.out.println("CUDA is available");
+ opencv_core.printCudaDeviceInfo(0);
} else {
System.out.println("CUDA is not available");
}
@@ -608,23 +609,27 @@ public class Cameradetail {
}
public String GetFullQualityPhotoPath(String directory, String prefix){
- if (!ValidDirectory(directory)) directory = currentDirectory;
- return Path.of(directory, "FullQuality", makeFileName(prefix,".png")).toString();
+ //if (!ValidDirectory(directory)) directory = currentDirectory;
+ //return Path.of(directory, "FullQuality", makeFileName(prefix,".png")).toString();
+ return Path.of(config.getFullQualityDirectory(), makeFileName(prefix,".png")).toString();
}
public String GetReducedPhotoPath(String directory, String prefix){
- if (!ValidDirectory(directory)) directory = currentDirectory;
- return Path.of(directory, "Compressed", makeReducedFileName(prefix,".jpg")).toString();
+ //if (!ValidDirectory(directory)) directory = currentDirectory;
+ //return Path.of(directory, "Compressed", makeReducedFileName(prefix,".jpg")).toString();
+ return Path.of(config.getCompressedDirectory(), makeFileName(prefix,".jpg")).toString();
}
public String GetFullQualityCropPhotoPath(String directory, String prefix){
- if (!ValidDirectory(directory)) directory = currentDirectory;
- return Path.of(directory, "FullQualityCrop", makeFileName(prefix,".png")).toString();
+ //if (!ValidDirectory(directory)) directory = currentDirectory;
+ //return Path.of(directory, "FullQualityCrop", makeFileName(prefix,".png")).toString();
+ return Path.of(config.getFullQualityCropDirectory(), makeFileName(prefix,".png")).toString();
}
public String GetReducedCropPhotoPath(String directory, String prefix){
- if (!ValidDirectory(directory)) directory = currentDirectory;
- return Path.of(directory, "CompressedCrop", makeReducedFileName(prefix,".jpg")).toString();
+ //if (!ValidDirectory(directory)) directory = currentDirectory;
+ //return Path.of(directory, "CompressedCrop", makeReducedFileName(prefix,".jpg")).toString();
+ return Path.of(config.getCompressedCropDirectory(), makeFileName(prefix,".jpg")).toString();
}
/**
@@ -643,18 +648,10 @@ public class Cameradetail {
}
TakingPhoto.set(true);
if (!BestMat.empty()){
- Size sz = BestMat.size();
- raise_log("TakePhoto got frame with width: " + sz.width() + " and height: " + sz.height());
-
-// String timestamp = prefix+" "+SomeCodes.GetDateTimeString();
-// Scalar color = new Scalar(255, 255, 255, 0); // white
-// PutText(BestMat, timestamp, 4.0, color, 2);
-
-
// save BestMat at quality 9 PNG
- String filename = GetFullQualityCropPhotoPath(directory, prefix);
- //String filename = Path.of(directory, "FullQuality", makeFileName(prefix,".png")).toString();
+ String filename = GetFullQualityPhotoPath(directory, prefix);
+
if (opencv_imgcodecs.imwrite(filename, BestMat, parampng)){
result.setFullres(filename);
} else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+cameratitle.getText());
@@ -664,22 +661,9 @@ public class Cameradetail {
result.setFullcrop(xx);
result.setBestROI(new Rect(BestMatROI.x(), BestMatROI.y(), BestMatROI.width(), BestMatROI.height()));
}
-// if (BestMatROI!=null){
-// UMat FullCrop = CropUMat(BestMat, BestMatROI);
-// if (FullCrop!=null){
-// //String roifilename = Path.of(directory, "FullQualityCrop", makeFileName(prefix,".png")).toString();
-// String roifilename = GetFullQualityCropPhotoPath(directory, prefix);
-// if (!opencv_imgcodecs.imwrite(roifilename, FullCrop, parampng)){
-// System.out.println("TakePhoto failed, Unable to Save FullQUalityCrop for camera "+cameratitle.getText());
-// } else {
-// result.setFullcrop(roifilename);
-// result.setBestROI(new Rect(BestMatROI.x(), BestMatROI.y(), BestMatROI.width(), BestMatROI.height()));
-// }
-// }
-// }
+
// save ReducedMat at 100% JPEG
- //String reducedfilename = Path.of(directory, "Compressed", makeReducedFileName(prefix,".jpg")).toString();
String reducedfilename = GetReducedPhotoPath(directory, prefix);
opencv_imgproc.resize(BestMat, ReducedMat, ReducedSize);
if (!opencv_imgcodecs.imwrite(reducedfilename, ReducedMat, paramjpeg)){
@@ -691,19 +675,6 @@ public class Cameradetail {
result.setCompressedcrop(xy);
result.setReducedROI(new Rect(ReducedMatROI.x(), ReducedMatROI.y(), ReducedMatROI.width(), ReducedMatROI.height()));
}
-// if (ReducedMatROI!=null){
-// UMat ReducedCrop = CropUMat(ReducedMat, ReducedMatROI);
-// if (ReducedCrop!=null){
-// //String roifilename = Path.of(directory, "CompressedCrop", makeReducedFileName(prefix,".jpg")).toString();
-// String roifilename = GetReducedCropPhotoPath(directory, prefix);
-// if (!opencv_imgcodecs.imwrite(roifilename, ReducedCrop, paramjpeg)){
-// System.out.println("TakePhoto failed, Unable to Save CompressedCrop for camera "+cameratitle.getText());
-// } else {
-// result.setCompressedcrop(roifilename);
-// result.setReducedROI(new Rect(ReducedMatROI.x(), ReducedMatROI.y(), ReducedMatROI.width(), ReducedMatROI.height()));
-// }
-// }
-// }
} else raise_log("TakePhoto failed, Live View is Empty");
} else raise_log("TakePhoto failed, Grabber is null");
@@ -711,22 +682,25 @@ public class Cameradetail {
return result;
}
+
+
public String CropBestMat(String directory, String prefix, Rect ROI){
- if (!BestMat.empty()) {
+ UMat cloned = new UMat();
+ BestMat.copyTo(cloned);
+ if (!cloned.empty()) {
if (ValidROI(ROI)){
- if (ROIInsideUMat(ROI, BestMat)){
- UMat cropped = CropUMat(BestMat, ROI);
+ if (ROIInsideUMat(ROI, cloned)){
+ UMat cropped = CropUMat(cloned, ROI);
if (cropped != null) {
String filename = GetFullQualityCropPhotoPath(directory, prefix);
if (opencv_imgcodecs.imwrite(filename, cropped, parampng)) {
- System.out.println("CropBestMat success, saved as " + filename);
- Wait(500);
+ Logger.info("CropBestMat success, saved as " + filename);
return filename;
- } //else System.out.println("CropBestMat failed, Unable to Save BestMat");
- } //else System.out.println("CropBestMat failed, Unable to Crop BestMat");
- } //else System.out.println("CropBestMat failed, ROI is outside BestMat");
- } //else System.out.println("CropBestMat failed, ROI is invalid");
- } //else System.out.println("CropBestMat failed, BestMat is empty");
+ } else Logger.error("CropBestMat failed, Unable to Save BestMat as ",filename);
+ } else Logger.error("CropBestMat failed, Unable to Crop BestMat");
+ } else Logger.error("CropBestMat failed, ROI is outside BestMat");
+ } else Logger.error("CropBestMat failed, ROI is invalid");
+ } else Logger.error("CropBestMat failed, BestMat is empty");
return null;
}
@@ -738,14 +712,13 @@ public class Cameradetail {
if (cropped!=null){
String filename = GetReducedCropPhotoPath(directory, prefix);
if (opencv_imgcodecs.imwrite(filename, cropped, paramjpeg)){
- System.out.println("CropReducedMat success, saved as "+filename);
- Wait(100);
+ Logger.info("CropReducedMat success, saved as ",filename);
return filename;
- } //else System.out.println("CropReducedMat failed, Unable to Save ReducedMat");
- } //else System.out.println("CropReducedMat failed, Unable to Crop ReducedMat");
- } //else System.out.println("CropReducedMat failed, ROI is outside ReducedMat");
- } //else System.out.println("CropReducedMat failed, ROI is invalid");
- } //else System.out.println("CropReducedMat failed, ReducedMat is empty");
+ } else Logger.error("CropReducedMat failed, Unable to Save ReducedMat as ",filename);
+ } else Logger.error("CropReducedMat failed, Unable to Crop ReducedMat");
+ } else Logger.error("CropReducedMat failed, ROI is outside ReducedMat");
+ } else Logger.error("CropReducedMat failed, ROI is invalid");
+ } else Logger.error("CropReducedMat failed, ReducedMat is empty");
return null;
}
@@ -770,7 +743,8 @@ public class Cameradetail {
Capturing.set(false);
if (mGrabber!=null){
try{
- mGrabber.stop();
+ mGrabber.close();
+ System.out.println("Camera "+cameratitle.getText()+" stopped");
Platform.runLater(()->setCameraStatus("Camera Stopped"));
} catch (Exception e){
raise_log("StopLiveView failed, Unable to Stop Camera, Error: " + e.getMessage());
@@ -827,6 +801,8 @@ public class Cameradetail {
LiveFPS = 0;
mGrabber.start();
+ mGrabber.flush();
+ System.out.println("Camera "+cameratitle+" started");
Capturing.set(true);
// just information
@@ -870,6 +846,8 @@ public class Cameradetail {
boolean have_fist = false;
int no_face_counter = 0;
int face_counter = 0;
+ int open_eye_counter = 0;
+ int close_eye_counter = 0;
while (Capturing.get()) {
try {
@@ -880,11 +858,26 @@ public class Cameradetail {
if (!Capturing.get()) return null;
IsGrabbingLiveView.set(true);
- Frame frame=null;
+ Frame frame;
try{
frame = mGrabber.grab(); // grab frame
} catch (Exception e){
- System.out.println("Exception on grab frame from camera "+cameratitle+", Message : "+e.getMessage());
+ frame = null;
+
+ if (e.getMessage()!=null && e.getMessage().length()>0){
+ String msg = e.getMessage();
+ if (msg.contains("start() been called")){
+ if (Capturing.get()){
+ System.out.println("Camera "+cameratitle+" has been stopped, restarting");
+ mGrabber.close();
+ Wait(100);
+ mGrabber.start();
+ mGrabber.flush();
+ } else {
+ System.out.println("Camera "+cameratitle+" has been stopped, not restarting");
+ }
+ } else System.out.println("Exception on grab frame from camera "+cameratitle+", Message : "+e.getMessage());
+ }
}
if (frame==null) continue;
Mat mat = matconverter.convert(frame); // convert to Mat
@@ -892,7 +885,10 @@ public class Cameradetail {
UMat originalmat = new UMat();
mat.copyTo(originalmat); // copy to BestMat for using OpenCL
- opencv_core.rotate(originalmat, BestMat, opencv_core.ROTATE_90_COUNTERCLOCKWISE);
+ // revisi 18/03/2025
+ UMat flippedmat = new UMat();
+ opencv_core.flip(originalmat, flippedmat, 1); // flip horizontal
+ opencv_core.rotate(flippedmat, BestMat, opencv_core.ROTATE_90_COUNTERCLOCKWISE);
IsGrabbingLiveView.set(false);
if (!BestMat.empty()) {
@@ -962,21 +958,29 @@ public class Cameradetail {
if (theface.haveEyes()){
// ada mata (buka mata)
+ close_eye_counter=0;
+ if (open_eye_counter<1){
+ open_eye_counter++;
+ continue;
+ }
+ System.out.println("Valid Open Eyes");
+
+
if (eye_state==0){
// transisi dari tutup mata ke buka mata
- //System.out.println("Eye Open Detected from camera "+cameratitle);
+ System.out.println("Transition from close to open eyes");
long now = System.currentTimeMillis();
if (waiting_for_second_blink){
long diff = now - last_blink;
// kalau beda waktu antara blink 1 dan blink 2 kurang dari 10 detik
if (diff<=10000){
waiting_for_second_blink = false;
- //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);
}
} else {
waiting_for_second_blink = true;
- //System.out.println("First Blink Detected from camera "+cameratitle);
+ System.out.println("First Blink Detected from camera "+cameratitle);
}
last_blink = now;
}
@@ -984,28 +988,36 @@ public class Cameradetail {
} else {
// ada muka, tidak ada mata
// transisi dari buka mata ke tutup mata
+ open_eye_counter=0;
+ if (close_eye_counter<1){
+ close_eye_counter++;
+ continue;
+ }
+ System.out.println("Valid Closed Eyes");
if (eye_state!=0){
- //System.out.println("Eye Closed Detected from camera "+cameratitle);
+ System.out.println("Transition from open to close eyes");
}
eye_state = 0;
-
}
-
-
-
} else if (have_left_45_face ){
no_face_counter = 0;
if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height);
} else {
// no face detected, but let's not cancel the previous state immediately
- if (no_face_counter>60){
+ if (no_face_counter>30){
// kalau tidak ada face selama 30 frame, reset state
- // 60 frame approximately 2 second
+ // 30 frame approximately 2 second
eye_state = -1;
last_blink = 0;
waiting_for_second_blink = false;
face_counter = 0;
+ if (close_eye_counter!=0 || open_eye_counter!=0){
+ close_eye_counter=0;
+ open_eye_counter=0;
+ System.out.println("Reset Open and Close Eyes");
+ }
+
if (event!=null) {
event.onFrontalFaceDetector(false, _face_width, _face_height);
event.onProfileFaceDetector(false, _face_width, _face_height);
@@ -1040,7 +1052,9 @@ public class Cameradetail {
updateValue(matToWritableImage(imgmat, imgmat.cols(), imgmat.rows()));
}
} catch (Exception e) {
- raise_log("Unable to Grab Frame, Error: " + e.getMessage());
+ if (ValidString(e.getMessage())){
+ raise_log("Unable to Grab Frame, Error: " + e.getMessage());
+ }
//if (!Capturing.get()) Platform.runLater(this::StopLiveView);
}
}
@@ -1067,17 +1081,19 @@ public class Cameradetail {
return false;
}
+
+
/**
* Remap LiveMatROI to BestMatROI and ReducedMatROI Resolution
* @param scaleX scale factor for width
* @param scaleY scale factor for height
*/
- public void RemapROI(double scaleX, double scaleY){
+ public void RemapROI(double scaleX, double scaleY, boolean printdebug){
BestMatROI = null;
ReducedMatROI = null;
if (ValidROI(LiveMatROI)){
if (ROIInsideUMat(LiveMatROI, LiveMat)){
- System.out.println("LiveMatROI camera "+cameratitle.getText()+" = "+RectToString(LiveMatROI));
+ if (printdebug) System.out.println("LiveMatROI camera "+cameratitle.getText()+" = "+RectToString(LiveMatROI));
double scaleXBest = 1.0*BestSize.width()/LiveSize.width();
double scaleYBest = 1.0*BestSize.height()/LiveSize.height();
@@ -1096,8 +1112,11 @@ public class Cameradetail {
HBest = HBest + deltaHBest;
if (HBest>BestSize.height()) HBest = BestSize.height();
BestMatROI = new Rect(XBest, YBest, WBest, HBest);
- System.out.println("scaleXBest = "+scaleXBest+" scaleYBest = "+scaleYBest);
- System.out.println("BestMatROI camera "+cameratitle.getText()+" = "+RectToString(BestMatROI));
+
+ if (printdebug){
+ System.out.println("scaleXBest = "+scaleXBest+" scaleYBest = "+scaleYBest);
+ System.out.println("BestMatROI camera "+cameratitle.getText()+" = "+RectToString(BestMatROI));
+ }
double scaleXReduced = 1.0*ReducedSize.width()/LiveSize.width();
double scaleYReduced = 1.0*ReducedSize.height()/LiveSize.height();
@@ -1116,8 +1135,11 @@ public class Cameradetail {
HReduced = HReduced + deltaHReduced;
if (HReduced>ReducedSize.height()) HReduced = ReducedSize.height();
ReducedMatROI = new Rect(XReduced, YReduced, WReduced, HReduced);
- System.out.println("scaleXReduced = "+scaleXReduced+" scaleYReduced = "+scaleYReduced);
- System.out.println("ReducedMatROI camera "+cameratitle.getText()+" = "+RectToString(ReducedMatROI));
+ if (printdebug){
+ System.out.println("scaleXReduced = "+scaleXReduced+" scaleYReduced = "+scaleYReduced);
+ System.out.println("ReducedMatROI camera "+cameratitle.getText()+" = "+RectToString(ReducedMatROI));
+ }
+
} //else System.out.println("LiveMatROI is Outside LiveMat for camera "+cameratitle.getText());
} //else System.out.println("LiveMatROI is invalid for camera "+cameratitle.getText());
diff --git a/src/main/java/id/co/gtc/erhacam/CaptureView.java b/src/main/java/id/co/gtc/erhacam/CaptureView.java
index da0c765..3915460 100644
--- a/src/main/java/id/co/gtc/erhacam/CaptureView.java
+++ b/src/main/java/id/co/gtc/erhacam/CaptureView.java
@@ -12,17 +12,14 @@ import ErhaAPI.BarcodeResullt;
import ErhaAPI.PhotoResult;
import ErhaAPI.PatientRecord;
import ErhaAPI.UploadResult;
-import FTP.FTPUpload;
-import FTP.FTPUploadEvent;
-import FTP.FtpMonitorData;
+
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
+import javafx.beans.Observable;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
-import javafx.scene.control.Alert;
-import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
@@ -64,9 +61,6 @@ public class CaptureView {
private Cameradetail image1, image2, image3, image4, image5;
-
- @FXML
- private TextArea directorypath;
@FXML
private TextArea barcodeData;
@FXML
@@ -74,15 +68,6 @@ public class CaptureView {
@FXML
private TextArea PatientName;
- @FXML
- private Button btnTakePhoto;
- @FXML
- private Button btnAutoFocus;
-
-
- @FXML
- private AnchorPane progressanchor;
-
private AudioPlayer audioPlayer;
private String audio_posisikan_muka = "posisikan_wajah.wav";
private String audio_scan_barcode = "scan_barcode.wav";
@@ -91,6 +76,7 @@ public class CaptureView {
private String audio_upload_berhasil = "upload_berhasil.wav";
private String audio_upload_gagal = "upload_gagal.wav";
private String audio_countdown = "countdown321.wav";
+ private String audio_tahan_posisi = "tahan_posisi.wav";
private List cams;
@@ -105,6 +91,7 @@ public class CaptureView {
private final ErhaAPI erhaAPI = new ErhaAPI(false);
+ private final double sharpness_threshold = 150;
@FXML
private void ChangeDirectory(){
DirectoryChooser dc = new DirectoryChooser();
@@ -113,7 +100,6 @@ public class CaptureView {
config.SetPhotoDirectory(path);
config.Save();
- directorypath.setText(path);
}
private void trigger_autofocus(Cameradetail image) throws InterruptedException {
@@ -139,29 +125,34 @@ public class CaptureView {
}
+
@SuppressWarnings("resource")
@FXML
private void TakePhotos(){
boolean has_face = Arrays.stream(have_face).anyMatch(AtomicBoolean::get);
if (has_face){
+ AutoCloseAlert.show("Pengambilan Foto", "Tahan Posisi Anda", "Proses ini kurang lebih 3 detik", 5);
if (audioPlayer!=null && audioPlayer.isInited()){
if (!audioPlayer.getCurrentFile().equals(audio_countdown)) {
audioPlayer.StopCurrentPlayback();
Wait(200);
- }
- audioPlayer.PlayFile(audio_countdown, ps);
+ audioPlayer.PlayFile(audio_tahan_posisi, ps);
+ } else System.out.println("audioPlayer already playing countdown");
+
}
- try{
- AutoFocus();
- Thread.sleep(2000);
- } catch (InterruptedException e){
- Logger.error("Error AutoFocus: "+e.getMessage());
- }
+// try{
+// AutoFocus();
+// Thread.sleep(1000);
+// } catch (InterruptedException e){
+// Logger.error("Error AutoFocus: "+e.getMessage());
+// }
+
+
Size thumbsize = new Size(160,120);
- String directory = directorypath.getText();
+ String directory = config.getPhotoDirectory();
String prefix = RemoveSpaces(medicalRecordID.getText()) ;
if (ValidDirectory(directory)){
if (ValidMedicalRecordId(prefix)){
@@ -175,12 +166,17 @@ public class CaptureView {
Callable task1 = ()->{
if (image1!=null) {
- image1.RemapROI(0.1,0.3);
+ image1.RemapROI(0.1,0.3, false);
+
+ double sharpness = CalculateSharpness(image1.getBestMat());
+ if (sharpness task2 = ()->{
if (image2!=null) {
- image2.RemapROI(0.1,0.3);
+ image2.RemapROI(0.1,0.3, false);
+ double sharpness = CalculateSharpness(image2.getBestMat());
+ if (sharpness task3 = ()->{
if (image3!=null) {
- image3.RemapROI(0.1,0.3);
+ image3.RemapROI(0.1,0.3, false);
+ double sharpness = CalculateSharpness(image3.getBestMat());
+ if (sharpness task4 = ()->{
if (image4!=null) {
- image4.RemapROI(0.1,0.3);
+ image4.RemapROI(0.1,0.3, false);
+ double sharpness = CalculateSharpness(image4.getBestMat());
+ if (sharpness task5 = ()->{
if (image5!=null) {
- image5.RemapROI(0.1,0.3);
+ image5.RemapROI(0.1,0.3, false);
+ double sharpness = CalculateSharpness(image5.getBestMat());
+ if (sharpness{
- progressanchor.getChildren().clear();
- barcodeData.setText("");
- medicalRecordID.setText("");
- PatientName.setText("");
- isTakingPhoto.set(false);
- });
+ AutoCloseAlert.show("Photos Taken", "Photos Taken", "Photos Taken", 5);
if (audioPlayer!=null && audioPlayer.isInited()){
if (!audioPlayer.getCurrentFile().equals(audio_pengambilan_berhasil)) {
audioPlayer.StopCurrentPlayback();
Wait(200);
- }
- audioPlayer.PlayFile(audio_pengambilan_berhasil, ps);
+ audioPlayer.PlayFile(audio_pengambilan_berhasil, ps);
+ } else System.out.println("audioPlayer already playing pengambilan berhasil");
}
+ // file untuk di upload
String[] files = prc.compressed();
-
-
if (files.length>0){
InsertSQL(prc);
@@ -450,7 +494,7 @@ public class CaptureView {
int totalfiles = files.length;
int counter = 0;
for (String ff : files) {
- UploadResult ur = erhaAPI.Upload_File(prefix, ff);
+ UploadResult ur = erhaAPI.Upload_File(prefix, ff,true);
if (ur != null) {
if (ur.message.startsWith("Record has been created")) {
counter++;
@@ -475,90 +519,57 @@ public class CaptureView {
uploadtask.setOnSucceeded(e-> {
+ System.out.println("UploadTask succeeded");
if (audioPlayer!=null && audioPlayer.isInited()){
if (!audioPlayer.getCurrentFile().equals(audio_upload_berhasil)) {
audioPlayer.StopCurrentPlayback();
Wait(200);
- }
- audioPlayer.PlayFile(audio_upload_berhasil, ps);
- audioPlayer.WaitUntilFinished();
+ audioPlayer.PlayFile(audio_upload_berhasil, ps);
+ } else System.out.println("audioPlayer already playing upload berhasil");
}
-
+ AutoCloseAlert.show("Upload Success", "Upload Success", "Upload Success", 5);
+ Platform.runLater(()->{
+ barcodeData.setText("");
+ medicalRecordID.setText("");
+ PatientName.setText("");
+ isTakingPhoto.set(false);
+ });
});
uploadtask.setOnFailed(e-> {
+ System.out.println("UploadTask failed");
if (audioPlayer!=null && audioPlayer.isInited()){
if (!audioPlayer.getCurrentFile().equals(audio_upload_gagal)) {
audioPlayer.StopCurrentPlayback();
Wait(200);
- }
- audioPlayer.PlayFile(audio_upload_gagal, ps);
- audioPlayer.WaitUntilFinished();
+ audioPlayer.PlayFile(audio_upload_gagal, ps);
+ } else System.out.println("audioPlayer already playing upload gagal");
}
-
+ AutoCloseAlert.show("Upload Failed", "Upload Failed", "Upload Failed", 5);
+ Platform.runLater(()->{
+ barcodeData.setText("");
+ medicalRecordID.setText("");
+ PatientName.setText("");
+ isTakingPhoto.set(false);
+ });
});
new Thread(uploadtask).start();
+ } else ShowAlert(AlertType.ERROR, "Error", "No Photos Taken", "No Photos Taken, please check camera");
+ } else ShowAlert(AlertType.ERROR, "Error", "Invalid Prefix", "Please input valid prefix or scan QR Code");
+ } else ShowAlert(AlertType.ERROR,"Error","Invalid Directory","Please select valid directory");
-
-
-
-// new Thread(()-> {
-// try{
-// InetAddress target = InetAddress.getByName(config.getFTPHost());
-// int port = toInt(config.getFTPPort());
-// if (target.isReachable(2000)){
-// Socket socket = new Socket();
-// InetSocketAddress isa = new InetSocketAddress(target, port);
-// socket.connect(isa,2000);
-// socket.close();
-// // sampai sini berarti FTP Host reachable
-// UploadToFTP(files);
-// } else throw new Exception("FTP Host not reachable");
-// } catch (Exception e){
-// Logger.error("Error UploadToFTP: "+e.getMessage());
-// Platform.runLater(()->{
-// Alert alert = new Alert(AlertType.ERROR);
-// alert.setTitle("Error");
-// alert.setHeaderText("Upload to FTP Failed");
-// alert.setContentText("Error: "+e.getMessage());
-// alert.showAndWait();
-// });
-//
-// }
-// }).start();
- } else {
- Alert Alert = new Alert(AlertType.ERROR);
- Alert.setTitle("Error");
- Alert.setHeaderText("No Photos Taken");
- Alert.setContentText("No Photos Taken, please check camera");
- Alert.showAndWait();
- }
- } else {
- Alert Alert = new Alert(AlertType.ERROR);
- Alert.setTitle("Error");
- Alert.setHeaderText("Invalid Prefix");
- Alert.setContentText("Please input valid prefix or scan QR Code");
- Alert.showAndWait();
- }
- } else {
- Alert Alert = new Alert(AlertType.ERROR);
- Alert.setTitle("Error");
- Alert.setHeaderText("Invalid Directory");
- Alert.setContentText("Please select valid directory");
- Alert.showAndWait();
- }
-
} else {
+ AutoCloseAlert.show("Error", "No Face Detected", "No Face Detected", 5);
if (audioPlayer!=null && audioPlayer.isInited()){
if (!audioPlayer.getCurrentFile().equals(audio_posisikan_muka)) {
audioPlayer.StopCurrentPlayback();
Wait(200);
- }
- audioPlayer.PlayFile(audio_posisikan_muka, ps);
+ audioPlayer.PlayFile(audio_posisikan_muka, ps);
+ } else System.out.println("audioPlayer already playing posisikan muka");
}
}
@@ -566,11 +577,6 @@ public class CaptureView {
}
- private void UpdateBtnTakePhoto(){
- boolean valid = ValidDirectory(directorypath.getText()) && ValidString(barcodeData.getText()) && ValidString(medicalRecordID.getText()) && ValidString(PatientName.getText());
- btnTakePhoto.setDisable(!valid);
- }
-
@FXML
public void initialize(){
audio_posisikan_muka = ExtractResource("/posisikan_wajah.wav");
@@ -580,16 +586,29 @@ public class CaptureView {
audio_upload_berhasil = ExtractResource("/upload_berhasil.wav");
audio_upload_gagal = ExtractResource("/upload_gagal.wav");
audio_countdown = ExtractResource("/countdown321.wav");
+ audio_tahan_posisi = ExtractResource("/tahan_posisi.wav");
+
+
+ //tambahan 19/03/2025
+ barcodeData.textProperty().addListener(new InvalidationListener() {
+ @Override
+ public void invalidated(Observable observable) {
+ String barcode = barcodeData.getText();
+ System.out.println("barcodeData invalidated, value: "+barcode);
+ if (ValidBarCode(barcode)){
+ if (AutoCloseAlert.shownTitle.equals("Scan Barcode")){
+ AutoCloseAlert.close();
+ }
+ } else {
+ AutoCloseAlert.show("Scan Barcode", "Silahkan Scan Barcode Anda", "Arahkan kertas barcode ke kamera", 0);
+ }
+ }
+ });
+ barcodeData.setText("");
audioPlayer = new AudioPlayer(1,48000);
Logger.info("Audio Player : "+(audioPlayer.isInited()? "Inited" : "Not Inited"));
- btnTakePhoto.setDisable(true);
-
- directorypath.textProperty().addListener((obs, oldval, newval)-> UpdateBtnTakePhoto());
- barcodeData.textProperty().addListener((obs, oldval, newval)-> UpdateBtnTakePhoto());
- medicalRecordID.textProperty().addListener((obs, oldval, newval)-> UpdateBtnTakePhoto());
- PatientName.textProperty().addListener((obs, oldval, newval)-> UpdateBtnTakePhoto());
cams = null;
try{
String[] xxx = VideoInputFrameGrabber.getDeviceDescriptions();
@@ -678,10 +697,9 @@ public class CaptureView {
}
}
- directorypath.setText(config.getPhotoDirectory());
-
- progressanchor.prefWidthProperty().bind(controlpane.widthProperty());
});
+
+
}
public void Unload(){
@@ -879,7 +897,7 @@ public class CaptureView {
Task checkpatientID = new Task<>() {
@Override
protected PatientRecord call() {
- BarcodeResullt br = erhaAPI.Validate_Barcode(finalbarCode);
+ BarcodeResullt br = erhaAPI.Validate_Barcode(finalbarCode,true);
if (br!=null){
if (br.message.startsWith("Records found")){
if (br.data!=null && br.data.length>0){
@@ -911,8 +929,8 @@ public class CaptureView {
if (!audioPlayer.getCurrentFile().equals(audio_posisikan_muka)) {
audioPlayer.StopCurrentPlayback();
Wait(200);
- }
- audioPlayer.PlayFile(audio_posisikan_muka, ps);
+ audioPlayer.PlayFile(audio_posisikan_muka, ps);
+ } else System.out.println("audioPlayer already playing posisikan muka");
}
}
@@ -927,6 +945,7 @@ public class CaptureView {
});
System.out.println("checkpatientID failed");
+ AutoCloseAlert.show("Error","checkpatientID failed","checkpatientID failed",5);
});
new Thread(checkpatientID).start();
@@ -1001,15 +1020,18 @@ public class CaptureView {
String prefix = medicalRecordID.getText();
if (!prefix.isEmpty()){
System.out.println("Prefix valid, taking photo");
- btnTakePhoto.fire();
+ 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);
if (audioPlayer!=null && audioPlayer.isInited()){
if (!audioPlayer.getCurrentFile().equals(audio_scan_barcode)) {
audioPlayer.StopCurrentPlayback();
Wait(200);
- }
- audioPlayer.PlayFile(audio_scan_barcode, ps);
+ audioPlayer.PlayFile(audio_scan_barcode, ps);
+ } else System.out.println("audioPlayer already playing scan barcode");
+
}
}
@@ -1117,157 +1139,6 @@ public class CaptureView {
}
}
- @Deprecated
- private void UploadToFTP(String[] files){
-
- final double uploadprogressheight = 50;
- Map progressmap = new HashMap<>();
-
- // Load uploadprogress.fxml for each file
- for (String filetoupload : files){
- Task loadtask = new Task<>() {
- @Override
- protected AnchorPane call() throws Exception {
- FXMLLoader loader = new FXMLLoader(getClass().getResource("uploadprogress.fxml"));
- AnchorPane pane = loader.load();
- pane.prefWidthProperty().bind(progressanchor.widthProperty());
- pane.setPrefHeight(uploadprogressheight);
- UploadProgress up = loader.getController();
- up.SetFile(filetoupload);
- up.SetStatus("Initialized");
- up.SetProgress(0,0);
- int ii = progressmap.size();
- AnchorPane.setTopAnchor(pane, (ii*uploadprogressheight)+10);
- progressmap.put(GetFileName(filetoupload), up);
- return pane;
- }
- };
- // kalau berhasil, add ke progressanchor
- loadtask.setOnSucceeded(e-> progressanchor.getChildren().add(loadtask.getValue()));
- // kalau gagal, log error
- loadtask.setOnFailed(e-> Logger.error("Error LoadTask: {}",e.getSource().getMessage()));
-
- new Thread(loadtask).start();
- }
-
-
-
- InvalidationListener progressanchorlistener = observable -> {
- // kalau sudah selesai load semua, mulai upload
- Logger.info("Progress Anchor Children Size: {}", progressanchor.getChildren().size());
- if (progressanchor.getChildren().size()==files.length){
- Task monitorFTP = new Task<>() {
- @Override
- protected FtpMonitorData call() throws Exception {
- FTPUpload ftp = new FTPUpload(config.getFTPHost(), toInt(config.getFTPPort()), config.getFTPUser(), config.getFTPPass(), config.getFTPPath());
- ftp.UploadFile(new FTPUploadEvent() {
- @Override
- public void onUploadSuccess(String file) {
- Logger.info("Upload Success: {}" ,file);
- String filename = GetFileName(file);
- UploadProgress up = progressmap.get(filename);
- if (up!=null){
- updateValue(new FtpMonitorData("Success", filename, up, 1, 1));
-// Platform.runLater(()->{
-// up.SetStatus("Success");
-// up.SetProgress(1,1);
-// });
-
- }
- }
-
- @Override
- public void onUploadFailed(String file) {
- Logger.info("Upload Failed: {}",file);
- String filename = GetFileName(file);
- UploadProgress up = progressmap.get(filename);
- if (up!=null){
- updateValue(new FtpMonitorData("Failed", filename, up, 1, 0));
-// Platform.runLater(()->{
-// up.SetStatus("Failed");
-// up.SetProgress(0,1);
-// });
-
- }
- }
-
- @Override
- public void onUploadProgress(String file, long bytes, long total) {
- String filename = GetFileName(file);
- UploadProgress up = progressmap.get(filename);
- if (up!=null){
- updateValue(new FtpMonitorData("Uploading", filename, up, total, bytes));
-// Platform.runLater(()->up.SetProgress(bytes, total));
- }
- }
-
- @Override
- public void onUploadStarted(String file) {
- Logger.info("Upload Started: {}",file);
- String filename = GetFileName(file);
- UploadProgress up = progressmap.get(filename);
- if (up!=null){
- updateValue(new FtpMonitorData("Started", filename, up, 0, 0));
-// Platform.runLater(()->{
-// up.SetStatus("Started");
-// up.SetProgress(0,0);
-// });
- }
-
- }
-
- @Override
- public void uploadLog(String msg) {
- Logger.info("Upload Log: {}",msg);
- }
-
- @Override
- public void onUploadFinished(int total, int success, int failed, String[] files) {
- Logger.info("Upload Finished, Total: {}, Success: {}, Failed: {}", total, success, failed);
- Platform.runLater(()->{
- if (!audioPlayer.getCurrentFile().equals(audio_upload_berhasil)) {
- audioPlayer.StopCurrentPlayback();
- Wait(200);
- }
- audioPlayer.PlayFile(audio_upload_berhasil, ps);
- Alert Alert = new Alert(AlertType.INFORMATION);
- Alert.setTitle("Upload Finished");
- Alert.setHeaderText("Upload Finished");
- Alert.setContentText("Total: "+total+"\nSuccess: "+success+"\nFailed: "+failed);
- Alert.showAndWait();
- });
- }
- }, files);
-
-
-
- // Task selesai, return null
- return null;
- }
- };
-
- monitorFTP.valueProperty().addListener(
- (observable1, oldValue, newValue) -> {
- if (newValue!=null){
- if (newValue.progress!=null){
- newValue.progress.SetStatus(newValue.information);
- newValue.progress.SetProgress(newValue.current, newValue.total);
- }
- }
- }
- );
-
- new Thread(monitorFTP).start();
- }
- };
-
- progressanchor.getChildren().addListener(progressanchorlistener);
-
-
- }
-
-
-
private void InsertSQL(PhotoReviewClass prc){
Sqlite sql = new Sqlite();
sql.Insert(prc);
diff --git a/src/main/java/id/co/gtc/erhacam/Detectors.java b/src/main/java/id/co/gtc/erhacam/Detectors.java
index f74bfd0..85aeac2 100644
--- a/src/main/java/id/co/gtc/erhacam/Detectors.java
+++ b/src/main/java/id/co/gtc/erhacam/Detectors.java
@@ -14,10 +14,9 @@ import static Config.SomeCodes.IsInsideRect;
public class Detectors {
public static CascadeClassifier frontalfaceDetector;
private static CascadeClassifier eyeDetector;
-
private static CascadeClassifier profilefaceDetector;
- private static CascadeClassifier palmDetector;
- private static CascadeClassifier fistDetector;
+ //private static CascadeClassifier palmDetector;
+ //private static CascadeClassifier fistDetector;
private static double scaleFactor = 1.1;
private final static int minNeighbors = 3;
@@ -37,43 +36,43 @@ public class Detectors {
LoadProfileFaceDetector();
- LoadFistDetector();
- LoadRightPalmDetector();
+ //LoadFistDetector();
+ //LoadRightPalmDetector();
}
- private static void LoadFistDetector(){
- String filename = SomeCodes.ExtractResource("/fist.xml");
- if (filename!=null) {
- Logger.info("Fist Detector file : " + filename);
- if (fistDetector ==null) {
- try{
+// private static void LoadFistDetector(){
+// String filename = SomeCodes.ExtractResource("/fist.xml");
+// if (filename!=null) {
+// Logger.info("Fist Detector file : " + filename);
+// if (fistDetector ==null) {
+// try{
+//
+// fistDetector = new CascadeClassifier(filename);
+// Logger.info("FistDetector loaded");
+// } catch (Exception e){
+// Logger.error("Exception on loading FistDetector : " + e.getMessage());
+// }
+//
+// } else Logger.info("FistDetector already loaded");
+// } else Logger.error("Unable to extract fist detector file");
+// }
- fistDetector = new CascadeClassifier(filename);
- Logger.info("FistDetector loaded");
- } catch (Exception e){
- Logger.error("Exception on loading FistDetector : " + e.getMessage());
- }
-
- } else Logger.info("FistDetector already loaded");
- } else Logger.error("Unable to extract fist detector file");
- }
-
- private static void LoadRightPalmDetector(){
- String filename = SomeCodes.ExtractResource("/rpalm.xml");
- if (filename!=null) {
- Logger.info("Right Palm Detector file : " + filename);
- if (palmDetector ==null) {
- try{
-
- palmDetector = new CascadeClassifier(filename);
- Logger.info("RightPalmDetector loaded");
- } catch (Exception e){
- Logger.error("Exception on loading RightPalmDetector : " + e.getMessage());
- }
-
- } else Logger.info("RightPalmDetector already loaded");
- } else Logger.error("Unable to extract right palm detector file");
- }
+// private static void LoadRightPalmDetector(){
+// String filename = SomeCodes.ExtractResource("/rpalm.xml");
+// if (filename!=null) {
+// Logger.info("Right Palm Detector file : " + filename);
+// if (palmDetector ==null) {
+// try{
+//
+// palmDetector = new CascadeClassifier(filename);
+// Logger.info("RightPalmDetector loaded");
+// } catch (Exception e){
+// Logger.error("Exception on loading RightPalmDetector : " + e.getMessage());
+// }
+//
+// } else Logger.info("RightPalmDetector already loaded");
+// } else Logger.error("Unable to extract right palm detector file");
+// }
private static void LoadFrontalFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
@@ -129,15 +128,15 @@ public class Detectors {
- public static boolean HavePalm(UMat graymat){
- RectVector palms = Detect(graymat, palmDetector);
- return palms!=null && palms.size()>0;
- }
-
- public static boolean HaveFist(UMat graymat){
- RectVector fists = Detect(graymat, fistDetector);
- return fists!=null && fists.size()>0;
- }
+// public static boolean HavePalm(UMat graymat){
+// RectVector palms = Detect(graymat, palmDetector);
+// return palms!=null && palms.size()>0;
+// }
+//
+// public static boolean HaveFist(UMat graymat){
+// RectVector fists = Detect(graymat, fistDetector);
+// return fists!=null && fists.size()>0;
+// }
/**
diff --git a/src/main/java/id/co/gtc/erhacam/MainApplication.java b/src/main/java/id/co/gtc/erhacam/MainApplication.java
index e2d49d3..8d43f3f 100644
--- a/src/main/java/id/co/gtc/erhacam/MainApplication.java
+++ b/src/main/java/id/co/gtc/erhacam/MainApplication.java
@@ -30,12 +30,11 @@ public class MainApplication extends Application {
if (UserID.equals("14022025")){
Logger.info("Secure Dongle UserID valid");
-
FXMLLoader fxmlLoader = new FXMLLoader(MainApplication.class.getResource("main-view.fxml"));
Screen screen = Screen.getPrimary();
Rectangle2D screenbound = screen.getVisualBounds();
Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight());
- stage.setTitle("MultiCam Capture App for ERHA 18022025-032");
+ stage.setTitle("MultiCam Capture App for ERHA 11032025-006");
stage.setScene(scene);
stage.setResizable(true);
stage.setMaximized(true);
diff --git a/src/main/java/id/co/gtc/erhacam/PhotoRow.java b/src/main/java/id/co/gtc/erhacam/PhotoRow.java
index b623f6c..bc35dc5 100644
--- a/src/main/java/id/co/gtc/erhacam/PhotoRow.java
+++ b/src/main/java/id/co/gtc/erhacam/PhotoRow.java
@@ -15,6 +15,7 @@ import org.tinylog.Logger;
import java.io.File;
import java.nio.file.Path;
+import static Config.SomeCodes.ShowAlert;
import static Config.SomeCodes.config;
public class PhotoRow {
@@ -47,18 +48,22 @@ public class PhotoRow {
imgview.setStyle(borderstyle);
imgview.setOnMouseClicked(e->{
if (e.getClickCount()>=2){
+ //System.out.println("Photo path: "+photopath);
File ff = new File(photopath);
- String hires = Path.of(config.getPhotoDirectory(), ff.getName()).toString();
+// System.out.println("Config exists : "+(config!=null));
+// System.out.println("Photo directory: "+config.getPhotoDirectory());
+// System.out.println("Full quality directory: "+config.getFullQualityDirectory());
+// System.out.println("Full Quality Crop directory: "+config.getFullQualityCropDirectory());
+// System.out.println("Reduced quality directory: "+config.getCompressedDirectory());
+// System.out.println("Reduced quality crop directory: "+config.getCompressedCropDirectory());
+ //String hires = Path.of(config.getPhotoDirectory(), ff.getName()).toString();
+ String hires = Path.of(config.getFullQualityDirectory(), ff.getName()).toString();
+ //System.out.println("Hires: "+hires);
File hiresfile = new File(hires);
if (hiresfile.isFile()){
+ System.out.println("Opening file: "+hires);
SomeCodes.OpenPictureInDefaultViewer(hires);
- } else {
- Alert alert = new Alert(Alert.AlertType.ERROR);
- alert.setTitle("Error");
- alert.setHeaderText("File not found");
- alert.setContentText("File not found: "+hires);
- alert.showAndWait();
- }
+ } else ShowAlert(Alert.AlertType.ERROR, "Error", "File not found", "File not found: "+hires);
e.consume();
}
});
diff --git a/src/main/java/id/co/gtc/erhacam/SettingView.java b/src/main/java/id/co/gtc/erhacam/SettingView.java
index 441ea1e..2ba0419 100644
--- a/src/main/java/id/co/gtc/erhacam/SettingView.java
+++ b/src/main/java/id/co/gtc/erhacam/SettingView.java
@@ -6,6 +6,7 @@ import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
+import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import lombok.val;
import org.bytedeco.javacv.VideoInputFrameGrabber;
@@ -13,21 +14,9 @@ import org.tinylog.Logger;
import java.io.File;
-import static Config.SomeCodes.ValidString;
-import static Config.SomeCodes.config;
+import static Config.SomeCodes.*;
public class SettingView {
- @FXML
- private TextField AudioPhase1;
- @FXML
- private TextField AudioPhase2;
- @FXML
- private TextField AudioPhase3;
- @FXML
- private TextField AudioPhase4;
- @FXML
- private TextField AudioPhase5;
-
@FXML
private ComboBox CameraLeft90;
@FXML
@@ -50,6 +39,11 @@ public class SettingView {
@FXML
private TextField FTPPath;
+ @FXML
+ private TextField PhotoDirectoryPath;
+
+
+
final FileChooser jfc = new FileChooser();
String[] cameranames = null;
@@ -63,6 +57,17 @@ public class SettingView {
@FXML
private TextField cascadeMaxSize;
+ @FXML
+ private void ChangePhotoDirectoryPath(){
+ DirectoryChooser dc = new DirectoryChooser();
+ dc.setTitle("Select Directory");
+ String path = dc.showDialog(null).getAbsolutePath();
+
+ config.SetPhotoDirectory(path);
+ config.Save();
+ PhotoDirectoryPath.setText(path);
+ }
+
@FXML
private void CascadeSettingApply(){
String minsize = cascadeMinSize.getText();
@@ -87,11 +92,8 @@ public class SettingView {
Detectors.setFaceMaxSize(max);
Detectors.setFaceMinSize(min);
Detectors.setScaleFactor(scale);
- val alert = new Alert(Alert.AlertType.INFORMATION);
- alert.setTitle("Cascade Setting");
- alert.setHeaderText("Cascade Setting Saved");
- alert.setContentText("Cascade Setting Saved Successfully");
- alert.showAndWait();
+ 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("Min Size must be greater than 0");
} else show_cascade_alert("Scale Factor must be greater than 1.0");
@@ -105,11 +107,7 @@ public class SettingView {
}
private void show_cascade_alert(String content){
- val alert = new Alert(Alert.AlertType.ERROR);
- alert.setTitle("Cascade Setting Error");
- alert.setHeaderText("Cascade Setting Error");
- alert.setContentText(content);
- alert.showAndWait();
+ ShowAlert(Alert.AlertType.ERROR, "Cascade Setting Error", "Cascade Setting Error", content);
}
@FXML
@@ -129,11 +127,6 @@ public class SettingView {
Platform.runLater(()->{
- AudioPhase1.setText(config.getAudioPhase1());
- AudioPhase2.setText(config.getAudioPhase2());
- AudioPhase3.setText(config.getAudioPhase3());
- AudioPhase4.setText(config.getAudioPhase4());
- AudioPhase5.setText(config.getAudioPhase5());
CameraLeft90.getItems().clear();
CameraLeft45.getItems().clear();
@@ -168,6 +161,8 @@ public class SettingView {
FTPPass.setText(config.getFTPPass());
FTPPath.setText(config.getFTPPath());
+ PhotoDirectoryPath.setText(config.getPhotoDirectory());
+
cascadeScaleFactor.setText(String.valueOf(config.getCascadeScaleFactor()));
cascadeMinSize.setText(String.valueOf(config.getCascadeMinSize()));
cascadeMaxSize.setText(String.valueOf(config.getCascadeMaxSize()));
@@ -178,52 +173,6 @@ public class SettingView {
config.Save();
}
- @FXML
- private void BrowseAudioPhase1(){
- File file = jfc.showOpenDialog(null);
- if (file!=null){
- config.SetAudioPhase1(file.getAbsolutePath());
- AudioPhase1.setText(config.getAudioPhase1());
- }
-
- }
-
- @FXML
- private void BrowseAudioPhase2(){
- File file = jfc.showOpenDialog(null);
- if (file!=null){
- config.SetAudioPhase2(file.getAbsolutePath());
- AudioPhase2.setText(config.getAudioPhase2());
- }
- }
-
- @FXML
- private void BrowseAudioPhase3(){
- File file = jfc.showOpenDialog(null);
- if (file!=null){
- config.SetAudioPhase3(file.getAbsolutePath());
- AudioPhase3.setText(config.getAudioPhase3());
- }
- }
-
- @FXML
- private void BrowseAudioPhase4(){
- File file = jfc.showOpenDialog(null);
- if (file!=null){
- config.SetAudioPhase4(file.getAbsolutePath());
- AudioPhase4.setText(config.getAudioPhase4());
- }
- }
-
- @FXML
- private void BrowseAudioPhase5(){
- File file = jfc.showOpenDialog(null);
- if (file!=null){
- config.SetAudioPhase5(file.getAbsolutePath());
- AudioPhase5.setText(config.getAudioPhase5());
- }
- }
-
@FXML
private void ApplyCameraLeft90(){
config.SetCameraLeft90(CameraLeft90.getValue());
@@ -261,18 +210,8 @@ public class SettingView {
config.SetFTPPass(FTPPass.getText());
config.SetFTPPath(FTPPath.getText());
- val alert = new Alert(Alert.AlertType.INFORMATION);
- alert.setTitle("FTP Configuration");
- alert.setHeaderText("FTP Configuration Saved");
- alert.setContentText("FTP Configuration Saved Successfully");
- alert.showAndWait();
- } else {
- val alert = new Alert(Alert.AlertType.ERROR);
- alert.setTitle("FTP Error");
- alert.setHeaderText("FTP Configuration Error");
- alert.setContentText("FTP Configuration is incorrect, please check your FTP Configuration");
- alert.showAndWait();
- }
+ ShowAlert(Alert.AlertType.INFORMATION, "FTP Configuration", "FTP Configuration Saved", "FTP Configuration Saved Successfully");
+ } else ShowAlert(Alert.AlertType.ERROR, "FTP Error", "FTP Configuration Error", "FTP Configuration is incorrect, please check your FTP Configuration");
}
}
diff --git a/src/main/java/unusedcodes/Cameradetail_Arducam.java b/src/main/java/unusedcodes/Cameradetail_Arducam.java
index b021c50..7c1e698 100644
--- a/src/main/java/unusedcodes/Cameradetail_Arducam.java
+++ b/src/main/java/unusedcodes/Cameradetail_Arducam.java
@@ -639,7 +639,7 @@ public class Cameradetail_Arducam {
Capturing.set(false);
if (mGrabber!=null){
try{
- mGrabber.stop();
+ mGrabber.close();
Platform.runLater(()->setCameraStatus("Camera Stopped"));
} catch (Exception e){
if (event!=null) event.onLog("StopLiveView failed, Unable to Stop Camera, Error: " + e.getMessage());
diff --git a/src/main/resources/id/co/gtc/erhacam/capture-view.fxml b/src/main/resources/id/co/gtc/erhacam/capture-view.fxml
index 11ad239..4a56e30 100644
--- a/src/main/resources/id/co/gtc/erhacam/capture-view.fxml
+++ b/src/main/resources/id/co/gtc/erhacam/capture-view.fxml
@@ -3,6 +3,7 @@
+
@@ -35,109 +36,78 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/id/co/gtc/erhacam/setting-view.fxml b/src/main/resources/id/co/gtc/erhacam/setting-view.fxml
index bca173d..02d6c7a 100644
--- a/src/main/resources/id/co/gtc/erhacam/setting-view.fxml
+++ b/src/main/resources/id/co/gtc/erhacam/setting-view.fxml
@@ -14,122 +14,22 @@
-
-
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -311,7 +211,7 @@
-
+
@@ -389,6 +289,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/upload_berhasil.wav b/upload_berhasil.wav
deleted file mode 100644
index 8a8a5d3..0000000
Binary files a/upload_berhasil.wav and /dev/null differ
diff --git a/upload_gagal.wav b/upload_gagal.wav
deleted file mode 100644
index f7dfcea..0000000
Binary files a/upload_gagal.wav and /dev/null differ
diff --git a/voices/countdown321.wav b/voices/countdown321.wav
index 2e0f9a3..f77a93d 100644
Binary files a/voices/countdown321.wav and b/voices/countdown321.wav differ
diff --git a/voices/data_barcode_tidak_ditemukan.wav b/voices/data_barcode_tidak_ditemukan.wav
new file mode 100644
index 0000000..6096936
Binary files /dev/null and b/voices/data_barcode_tidak_ditemukan.wav differ
diff --git a/voices/kesalahan_server.wav b/voices/kesalahan_server.wav
new file mode 100644
index 0000000..ea51697
Binary files /dev/null and b/voices/kesalahan_server.wav differ
diff --git a/voices/pengambilan_berhasil.wav b/voices/pengambilan_berhasil.wav
index c56c170..96027f6 100644
Binary files a/voices/pengambilan_berhasil.wav and b/voices/pengambilan_berhasil.wav differ
diff --git a/voices/pengambilan_gagal.wav b/voices/pengambilan_gagal.wav
index 4afa67b..a22cb16 100644
Binary files a/voices/pengambilan_gagal.wav and b/voices/pengambilan_gagal.wav differ
diff --git a/voices/posisikan_wajah.wav b/voices/posisikan_wajah.wav
index 18ab44d..a780198 100644
Binary files a/voices/posisikan_wajah.wav and b/voices/posisikan_wajah.wav differ
diff --git a/voices/scan_barcode.wav b/voices/scan_barcode.wav
index 0d9c7f3..7aad891 100644
Binary files a/voices/scan_barcode.wav and b/voices/scan_barcode.wav differ
diff --git a/voices/tahan_posisi.wav b/voices/tahan_posisi.wav
new file mode 100644
index 0000000..2f2871f
Binary files /dev/null and b/voices/tahan_posisi.wav differ
diff --git a/voices/upload_berhasil.wav b/voices/upload_berhasil.wav
index 8a8a5d3..56cc561 100644
Binary files a/voices/upload_berhasil.wav and b/voices/upload_berhasil.wav differ
diff --git a/voices/upload_gagal.wav b/voices/upload_gagal.wav
index f7dfcea..2ec2c19 100644
Binary files a/voices/upload_gagal.wav and b/voices/upload_gagal.wav differ