diff --git a/out/artifacts/ErhaCam_jar/ErhaCam.jar b/out/artifacts/ErhaCam_jar/ErhaCam.jar index edac0e1..2b027ad 100644 Binary files a/out/artifacts/ErhaCam_jar/ErhaCam.jar and b/out/artifacts/ErhaCam_jar/ErhaCam.jar differ diff --git a/src/main/java/BASS/AudioPlayer.java b/src/main/java/BASS/AudioPlayer.java index 28edb34..5c9c91d 100644 --- a/src/main/java/BASS/AudioPlayer.java +++ b/src/main/java/BASS/AudioPlayer.java @@ -3,6 +3,8 @@ package BASS; import lombok.Getter; import org.tinylog.Logger; +import java.util.function.Consumer; + import static Config.SomeCodes.Wait; @@ -121,7 +123,7 @@ public class AudioPlayer { iscontinue = false; break; default : { - Wait(100); + Wait(1000); } } } diff --git a/src/main/java/Config/SomeCodes.java b/src/main/java/Config/SomeCodes.java index cc94a14..958ba08 100644 --- a/src/main/java/Config/SomeCodes.java +++ b/src/main/java/Config/SomeCodes.java @@ -105,6 +105,7 @@ public class SomeCodes { Mat resized = new Mat(); opencv_imgproc.resize(mat, resized, new org.bytedeco.opencv.opencv_core.Size(width, height)); BufferedImage img = converter.convert(matconverter.convert(resized)); + resized.release(); return SwingFXUtils.toFXImage(img, null); } return null; @@ -163,6 +164,7 @@ public class SomeCodes { Mat resized = new Mat(); opencv_imgproc.resize(source, resized, thumbsize); opencv_imgcodecs.imwrite(thumbfile, resized); + resized.release(); return thumbfile; } } @@ -752,7 +754,8 @@ public class SomeCodes { stddev.copyTo(_std); double value = _std.createIndexer().getDouble(0,0); - + _std.release(); + laplacian.release(); return Math.pow(value,2); } return 0; diff --git a/src/main/java/id/co/gtc/erhacam/Cameradetail.java b/src/main/java/id/co/gtc/erhacam/Cameradetail.java index ba39059..979ad82 100644 --- a/src/main/java/id/co/gtc/erhacam/Cameradetail.java +++ b/src/main/java/id/co/gtc/erhacam/Cameradetail.java @@ -690,11 +690,15 @@ public class Cameradetail { if (!BestMat.empty()){ + UMat cloned; + synchronized (BestMat){ + cloned = BestMat.clone(); + } + // save BestMat at quality 9 PNG String filename = GetFullQualityPhotoPath(directory, prefix); - - if (opencv_imgcodecs.imwrite(filename, BestMat, parampng)){ + if (opencv_imgcodecs.imwrite(filename, cloned, parampng)){ result.setFullres(filename); } else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+cameratitle.getText()); @@ -707,7 +711,7 @@ public class Cameradetail { // save ReducedMat at 100% JPEG String reducedfilename = GetReducedPhotoPath(directory, prefix); - opencv_imgproc.resize(BestMat, ReducedMat, ReducedSize); + opencv_imgproc.resize(cloned, ReducedMat, ReducedSize); if (!opencv_imgcodecs.imwrite(reducedfilename, ReducedMat, paramjpeg)){ System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+cameratitle.getText()); } else result.setCompressedfile(reducedfilename); @@ -717,6 +721,7 @@ public class Cameradetail { result.setCompressedcrop(xy); result.setReducedROI(new Rect(ReducedMatROI.x(), ReducedMatROI.y(), ReducedMatROI.width(), ReducedMatROI.height())); } + cloned.release(); } else raise_log("TakePhoto failed, Live View is Empty"); } catch (InterruptedException e){ @@ -735,8 +740,10 @@ public class Cameradetail { public String CropBestMat(String directory, String prefix, Rect ROI){ - UMat cloned = new UMat(); - BestMat.copyTo(cloned); + UMat cloned; + synchronized (BestMat){ + cloned = BestMat.clone(); + } if (!cloned.empty()) { if (ValidROI(ROI)){ if (ROIInsideUMat(ROI, cloned)){ @@ -751,6 +758,7 @@ public class Cameradetail { } 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"); + cloned.release(); return null; } @@ -881,6 +889,7 @@ public class Cameradetail { if (rect.haveEyes()){ rect.EyesRectangle(LiveMat); } + } } } else { @@ -1004,11 +1013,14 @@ public class Cameradetail { } Mat imgmat = new Mat(); - LiveMat.copyTo(imgmat); // copy back to CPU + + LiveMat.copyTo(imgmat); + // copy back to CPU setCameraStream(MatToImage(imgmat)); + imgmat.release(); } catch (Exception e) { - System.out.println(Thread.currentThread().getName()+" interrupted"); + //System.out.println(Thread.currentThread().getName()+" interrupted"); } } }); @@ -1098,20 +1110,20 @@ public class Cameradetail { UMat flippedmat = new UMat(); opencv_core.flip(originalmat, flippedmat, 0); // flip vertical flippedmat.copyTo(originalmat); - flippedmat.close(); + flippedmat.release(); } if (config.isFlipCamera()){ // revisi 18/03/2025 UMat flippedmat = new UMat(); opencv_core.flip(originalmat, flippedmat, 1); // flip horizontal flippedmat.copyTo(originalmat); - flippedmat.close(); + flippedmat.release(); } // rotate 90 degree counter clockwise karena kamera potrait opencv_core.rotate(originalmat, BestMat, opencv_core.ROTATE_90_COUNTERCLOCKWISE); - + originalmat.release(); if (!BestMat.empty()) { @@ -1306,6 +1318,7 @@ public class Cameradetail { } } catch (Exception ignored) { } + mat.release(); } return null; } diff --git a/src/main/java/id/co/gtc/erhacam/CaptureView.java b/src/main/java/id/co/gtc/erhacam/CaptureView.java index 01c6856..fcfb250 100644 --- a/src/main/java/id/co/gtc/erhacam/CaptureView.java +++ b/src/main/java/id/co/gtc/erhacam/CaptureView.java @@ -27,6 +27,7 @@ import javafx.stage.DirectoryChooser; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import javafx.scene.control.Alert.AlertType; import org.bytedeco.javacv.OpenCVFrameGrabber; @@ -151,6 +152,7 @@ public class CaptureView { if (audioPlayer!=null && audioPlayer.isInited()){ if (!Objects.equals(audioPlayer.getCurrentFile(), audio_tahan_posisi)){ audioPlayer.StopCurrentPlayback(); + Wait(500); audioPlayer.PlayFile(audio_tahan_posisi, new PlaybackStatus() { @Override public void onPlaybackStarted(String filename) { @@ -160,7 +162,7 @@ public class CaptureView { @Override public void onPlaybackFinished(String filename) { - + Wait(500); audioPlayer.PlayFile(audio_countdown, new PlaybackStatus() { @Override public void onPlaybackStarted(String filename) { @@ -196,6 +198,7 @@ public class CaptureView { if (audioPlayer!=null && audioPlayer.isInited()){ if (!Objects.equals(audioPlayer.getCurrentFile(),audio_posisikan_muka)) { audioPlayer.StopCurrentPlayback(); + Wait(500); audioPlayer.PlayFile(audio_posisikan_muka, null); } } @@ -214,7 +217,9 @@ public class CaptureView { if (audioPlayer!=null && audioPlayer.isInited()){ if (!Objects.equals(audioPlayer.getCurrentFile(), audio_scan_barcode)) { audioPlayer.StopCurrentPlayback(); + Wait(500); audioPlayer.PlayFile(audio_scan_barcode, null); + } } } @@ -256,6 +261,8 @@ public class CaptureView { } } + AtomicInteger takephoto_failure_counter = new AtomicInteger(0); + private void take_photo_lanjutan(String directory, String prefix){ audioPlayer.PlayFile(audio_camera_shutter, null); Size thumbsize = new Size(160,120); @@ -322,6 +329,7 @@ public class CaptureView { System.out.println("Sharpness score: "+score1+", "+score2+", "+score3+", "+score4+", "+score5); double lowest = FindLowestValue(score1,score2,score3,score4,score5); if (lowest<=config.getSharpnessThreshold()){ + // jelek String culprit = ""; if (lowest==score1) culprit = "camera 1"; else if (lowest==score2) culprit = "camera 2"; @@ -329,9 +337,29 @@ public class CaptureView { else if (lowest==score4) culprit = "camera 4"; else if (lowest==score5) culprit = "camera 5"; String lowest_string = String.format("%.2f", lowest); - AutoCloseAlert.show("Take Photos Failed", "Blurred Image Detected", "Blurred Image Detected at "+culprit+" with sharpness score "+lowest_string, 5, null); - isTakingPhoto.set(false); + AutoCloseAlert.show("Take Photos Failed", "Blurred Image Detected", "Blurred Image Detected at "+culprit+" with sharpness score "+lowest_string, 5, s -> isTakingPhoto.set(false)); + takephoto_failure_counter.incrementAndGet(); + if (audioPlayer!=null && audioPlayer.isInited()){ + if (takephoto_failure_counter.get() < 2){ + if (!Objects.equals(audio_pengambilan_gagal, audioPlayer.getCurrentFile())){ + audioPlayer.StopCurrentPlayback(); + Wait(500); + audioPlayer.PlayFile(audio_pengambilan_gagal, null); + } + } else { + if (!Objects.equals(audio_hubungi_staf_kami, audioPlayer.getCurrentFile())){ + audioPlayer.StopCurrentPlayback(); + Wait(500); + audioPlayer.PlayFile(audio_hubungi_staf_kami, null); + } + } + + } + return; + } else { + // bagus + takephoto_failure_counter.set(0); } @@ -490,6 +518,7 @@ public class CaptureView { if (audioPlayer!=null && audioPlayer.isInited()){ if (!Objects.equals(audioPlayer.getCurrentFile(),audio_pengambilan_berhasil)){ audioPlayer.StopCurrentPlayback(); + Wait(500); audioPlayer.PlayFile(audio_pengambilan_berhasil, new PlaybackStatus() { @Override public void onPlaybackStarted(String filename) { @@ -498,7 +527,7 @@ public class CaptureView { @Override public void onPlaybackFinished(String filename) { - AutoCloseAlert.showpictures(prc.compressed(),2, (s)->{ + AutoCloseAlert.showpictures(prc.compressed(),3, (s)->{ if (AutoCloseAlert.banner_02!=null) { System.out.println("Showing banner 02 after photo taken"); AutoCloseAlert.showbanner(AutoCloseAlert.banner_02, 0, null); @@ -523,6 +552,7 @@ public class CaptureView { if (audioPlayer!=null && audioPlayer.isInited()){ if (!Objects.equals(audioPlayer.getCurrentFile(),audio_pengambilan_gagal)){ audioPlayer.StopCurrentPlayback(); + Wait(500); audioPlayer.PlayFile(audio_pengambilan_gagal, null); } } @@ -576,6 +606,7 @@ public class CaptureView { if (audioPlayer!=null && audioPlayer.isInited()){ if (!Objects.equals(audioPlayer.getCurrentFile(), audio_upload_gagal)){ audioPlayer.StopCurrentPlayback(); + Wait(500); audioPlayer.PlayFile(audio_upload_gagal, null); } } @@ -770,6 +801,7 @@ public class CaptureView { config.Save(); } + AtomicBoolean anti_bawel = new AtomicBoolean(false); private void SetupCameraWithController(Cameradetail image, String cameraname, int devicenumber){ if (image!=null){ @@ -910,8 +942,37 @@ public class CaptureView { if (audioPlayer!=null && audioPlayer.isInited()){ if (!Objects.equals(audioPlayer.getCurrentFile(),audio_posisikan_muka)) { - audioPlayer.StopCurrentPlayback(); - audioPlayer.PlayFile(audio_posisikan_muka, null); + if (!anti_bawel.get()){ + audioPlayer.StopCurrentPlayback(); + Wait(500); + audioPlayer.PlayFile(audio_posisikan_muka, new PlaybackStatus() { + @Override + public void onPlaybackStarted(String filename) { + anti_bawel.set(true); + } + + @Override + public void onPlaybackFinished(String filename) { + anti_bawel.set(false); + Thread antibawel = new Thread(()->{ + try { + Thread.sleep(15*1000); + } catch (InterruptedException ignored) { + } + anti_bawel.set(false); + }); + antibawel.setName("anti bawel"); + antibawel.setDaemon(true); + antibawel.start(); + } + + @Override + public void onPlaybackFailure(String filename) { + anti_bawel.set(false); + } + }); + } + } } @@ -944,6 +1005,8 @@ public class CaptureView { } } + + @Override public void onFrontalFaceDetector(boolean hasface, int width, int height) { if (hasface!= _have_face.get()){ @@ -958,7 +1021,34 @@ public class CaptureView { if (audioPlayer!=null && audioPlayer.isInited()){ if (!Objects.equals(audioPlayer.getCurrentFile(), audio_scan_barcode)) { audioPlayer.StopCurrentPlayback(); - audioPlayer.PlayFile(audio_scan_barcode, null); + if (anti_bawel.get()) return; + audioPlayer.PlayFile(audio_scan_barcode, new PlaybackStatus() { + @Override + public void onPlaybackStarted(String filename) { + anti_bawel.set(true); + } + + @Override + public void onPlaybackFinished(String filename) { + Thread antibawel = new Thread(()->{ + try { + Thread.sleep(15*1000); + } catch (InterruptedException ignored) { + } + anti_bawel.set(false); + }); + antibawel.setName("anti bawel"); + antibawel.setDaemon(true); + antibawel.start(); + + } + + @Override + public void onPlaybackFailure(String filename) { + anti_bawel.set(false); + } + }); + } } } diff --git a/src/main/java/id/co/gtc/erhacam/Detectors.java b/src/main/java/id/co/gtc/erhacam/Detectors.java index b007a89..e3e375a 100644 --- a/src/main/java/id/co/gtc/erhacam/Detectors.java +++ b/src/main/java/id/co/gtc/erhacam/Detectors.java @@ -14,7 +14,7 @@ public class Detectors { private static CascadeClassifier eyeDetector; private static CascadeClassifier profilefaceDetector; - private static double scaleFactor = 1.1; + private static double scaleFactor = 1.05; private final static int minNeighbors = 3; private final static int flags = 0; private static Size FaceminSize; @@ -94,7 +94,10 @@ public class Detectors { dr.setFace(face); if (eyes!=null && eyes.size()>=2){ for(Rect eye : eyes.get()){ - if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye); + if (SomeCodes.IsInsideRect(eye, face)) { + dr.AddEye(eye); + System.out.println("face width : " + face.width() + " eye width : " + eye.width()); + } } } result.add(dr); @@ -180,7 +183,7 @@ public class Detectors { */ public static RectVector DetectEye(UMat graymat, int facewidth){ //return Detect(graymat, eyeDetector); - int minwidth = Math.max((int)(facewidth*0.25), 24); + int minwidth = (int)(facewidth*0.2); int maxwidth = (int)(facewidth*0.4); Size minsize = new Size(minwidth, minwidth); Size maxsize = new Size(maxwidth, maxwidth); diff --git a/src/main/java/id/co/gtc/erhacam/MainApplication.java b/src/main/java/id/co/gtc/erhacam/MainApplication.java index 7ed48e3..161c2bb 100644 --- a/src/main/java/id/co/gtc/erhacam/MainApplication.java +++ b/src/main/java/id/co/gtc/erhacam/MainApplication.java @@ -24,6 +24,14 @@ public class MainApplication extends Application { @Override public void start(Stage stage) throws IOException { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + System.out.println("ShutdownHook Checking running threads..."); + Map allThreads = Thread.getAllStackTraces(); + for(Thread thread : allThreads.keySet()){ + System.out.println("Thread: " + thread.getName()+", State: " + thread.getState()+", Daemon: " + thread.isDaemon()); + //thread.interrupt(); + } + })); SecureDongle sd = new SecureDongle((short)0x4B30, (short)0xA66C, (short)0x3109, (short)0x37B1); @@ -38,7 +46,7 @@ public class MainApplication extends Application { Screen screen = Screen.getPrimary(); Rectangle2D screenbound = screen.getBounds(); Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight()); - stage.setTitle("MultiCam Capture App for ERHA 14042025-041"); + stage.setTitle("MultiCam Capture App for ERHA 25042025-013"); stage.setScene(scene); stage.setResizable(true); stage.setMaximized(true); @@ -98,14 +106,6 @@ public class MainApplication extends Application { public void stop() throws Exception { Logger.info("Application stopped"); super.stop(); - Map allThreads = Thread.getAllStackTraces(); - if (!allThreads.isEmpty()){ - System.out.println("Checking running threads..."); - for(Thread thread : allThreads.keySet()){ - System.out.println("Thread: " + thread.getName()+", State: " + thread.getState()+", Daemon: " + thread.isDaemon()); - //thread.interrupt(); - } - } }