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 @@ - - + + - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -