Compare commits

...

11 Commits

Author SHA1 Message Date
rdkartono
58194d8979 commit 21/03/2025 2025-03-24 08:10:17 +07:00
093c32058c Commit 21032025 2025-03-21 14:41:53 +07:00
80d468a79a Commit 21032025 2025-03-21 14:24:05 +07:00
b248c59e32 Commit 19022025 2025-02-19 10:14:10 +07:00
64f5b619b7 Commit 18022025 2025-02-18 15:30:02 +07:00
00f9852fa8 Trial 11022025 2025-02-11 09:10:36 +07:00
30ef123832 Trial 05022025 2025-02-05 15:20:21 +07:00
29884c03ed Trial 04022025 2025-02-04 08:48:28 +07:00
a60fe56510 Improvement 21/01/2025 2025-01-21 13:13:39 +07:00
f80662a453 Improvement 21/01/2025 2025-01-21 10:53:41 +07:00
30660b9afb * tambah timestamp
* full resolution ganti ke PNG compression 0
* tambah reduced resolution di 1280x720 JPG quality 100
2025-01-15 10:23:18 +07:00
87 changed files with 182848 additions and 26702 deletions

View File

@@ -3,63 +3,50 @@
<output-path>$PROJECT_DIR$/out/artifacts/ErhaCam_jar</output-path>
<root id="archive" name="ErhaCam.jar">
<element id="module-output" name="ErhaCam" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21/javafx-fxml-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/xerial/sqlite-jdbc/3.46.0.0/sqlite-jdbc-3.46.0.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/controlsfx/controlsfx/11.2.1/controlsfx-11.2.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21/javafx-base-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacv-platform/1.5.10/javacv-platform-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacv/1.5.10/javacv-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacpp/1.5.10/javacpp-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/openblas/0.3.26-1.5.10/openblas-0.3.26-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/opencv/4.9.0-1.5.10/opencv-4.9.0-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/ffmpeg/6.1.1-1.5.10/ffmpeg-6.1.1-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/flycapture/2.13.3.31-1.5.9/flycapture-2.13.3.31-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libdc1394/2.2.6-1.5.9/libdc1394-2.2.6-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libfreenect/0.5.7-1.5.9/libfreenect-0.5.7-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libfreenect2/0.2.0-1.5.9/libfreenect2-0.2.0-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/librealsense/1.12.4-1.5.9/librealsense-1.12.4-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/librealsense2/2.53.1-1.5.9/librealsense2-2.53.1-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/videoinput/0.200-1.5.9/videoinput-0.200-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/artoolkitplus/2.3.1-1.5.9/artoolkitplus-2.3.1-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/leptonica/1.84.1-1.5.10/leptonica-1.84.1-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/tesseract/5.3.4-1.5.10/tesseract-5.3.4-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacpp-platform/1.5.10/javacpp-platform-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacpp/1.5.10/javacpp-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/openblas-platform/0.3.26-1.5.10/openblas-platform-0.3.26-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/opencv-platform/4.9.0-1.5.10/opencv-platform-4.9.0-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/opencv/4.9.0-1.5.10/opencv-4.9.0-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/ffmpeg-platform/6.1.1-1.5.10/ffmpeg-platform-6.1.1-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/flycapture-platform/2.13.3.31-1.5.9/flycapture-platform-2.13.3.31-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libdc1394-platform/2.2.6-1.5.9/libdc1394-platform-2.2.6-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libfreenect-platform/0.5.7-1.5.9/libfreenect-platform-0.5.7-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libfreenect2-platform/0.2.0-1.5.9/libfreenect2-platform-0.2.0-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/librealsense-platform/1.12.4-1.5.9/librealsense-platform-1.12.4-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/librealsense2-platform/2.53.1-1.5.9/librealsense2-platform-2.53.1-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/videoinput-platform/0.200-1.5.9/videoinput-platform-0.200-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/videoinput/0.200-1.5.9/videoinput-0.200-1.5.9-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/artoolkitplus-platform/2.3.1-1.5.9/artoolkitplus-platform-2.3.1-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/leptonica-platform/1.84.1-1.5.10/leptonica-platform-1.84.1-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/tesseract-platform/5.3.4-1.5.10/tesseract-platform-5.3.4-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-net/commons-net/3.11.1/commons-net-3.11.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/zxing/javase/3.5.3/javase-3.5.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/zxing/core/3.5.3/core-3.5.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/beust/jcommander/1.82/jcommander-1.82.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/jai-imageio/jai-imageio-core/1.4.0/jai-imageio-core-1.4.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/tinylog/tinylog-impl/2.7.0/tinylog-impl-2.7.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/tinylog/tinylog-api/2.7.0/tinylog-api-2.7.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21/javafx-controls-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21/javafx-fxml-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21/javafx-graphics-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.11.0/gson-2.11.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.27.0/error_prone_annotations-2.27.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21/javafx-graphics-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21/javafx-base-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/java/dev/jna/jna/5.15.0/jna-5.15.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-jcl/1.7.36/slf4j-jcl-1.7.36.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacpp/1.5.10/javacpp-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.1.1/commons-logging-1.1.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21/javafx-controls-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/tinylog/tinylog-impl/2.7.0/tinylog-impl-2.7.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/opencv/4.9.0-1.5.10/opencv-4.9.0-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/openblas/0.3.26-1.5.10/openblas-0.3.26-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/controlsfx/controlsfx/11.2.1/controlsfx-11.2.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21/javafx-base-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21/javafx-fxml-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/openblas/0.3.26-1.5.10/openblas-0.3.26-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/videoinput/0.200-1.5.9/videoinput-0.200-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/zxing/javase/3.5.3/javase-3.5.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21/javafx-controls-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/java/dev/jna/jna/5.15.0/jna-5.15.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/leptonica/1.84.1-1.5.10/leptonica-1.84.1-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.30/lombok-1.18.30.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21/javafx-graphics-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-graphics/21/javafx-graphics-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libfreenect/0.5.7-1.5.9/libfreenect-0.5.7-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/github/jai-imageio/jai-imageio-core/1.4.0/jai-imageio-core-1.4.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/librealsense2/2.53.1-1.5.9/librealsense2-2.53.1-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-fxml/21/javafx-fxml-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/libfreenect2/0.2.0-1.5.9/libfreenect2-0.2.0-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.27.0/error_prone_annotations-2.27.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/xerial/sqlite-jdbc/3.46.0.0/sqlite-jdbc-3.46.0.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.11.0/gson-2.11.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/videoinput/0.200-1.5.9/videoinput-0.200-1.5.9-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-controls/21/javafx-controls-21-win.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/slf4j/slf4j-jcl/1.7.36/slf4j-jcl-1.7.36.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/opencv/4.9.0-1.5.10/opencv-4.9.0-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacv/1.5.10/javacv-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/google/zxing/core/3.5.3/core-3.5.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/librealsense/1.12.4-1.5.9/librealsense-1.12.4-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/flycapture/2.13.3.31-1.5.9/flycapture-2.13.3.31-1.5.9.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/tesseract/5.3.4-1.5.10/tesseract-5.3.4-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/beust/jcommander/1.82/jcommander-1.82.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/tinylog/tinylog-api/2.7.0/tinylog-api-2.7.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/openjfx/javafx-base/21/javafx-base-21.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/ffmpeg/6.1.1-1.5.10/ffmpeg-6.1.1-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/ffmpeg/6.1.1-1.5.10/ffmpeg-6.1.1-1.5.10.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/javacpp/1.5.10/javacpp-1.5.10-windows-x86_64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/bytedeco/artoolkitplus/2.3.1-1.5.9/artoolkitplus-2.3.1-1.5.9.jar" path-in-jar="/" />
</root>
</artifact>
</component>

View File

@@ -1,22 +1,26 @@
#Thu Dec 19 11:49:05 WIB 2024
#Fri Mar 21 14:45:24 ICT 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
AudioPhase4=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase4.mp3
AudioPhase5=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase5.mp3
CameraCenter=OBSBOT Meet 2 StreamCamera
CameraConfigCenter={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigLeft45={"Brightness"\:37.58730158730158,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigLeft90={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigRight45={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigRight90={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraLeft45=OBSBOT Meet 2 StreamCamera
CameraCenter=
CameraConfigCenter={"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}
CameraConfigLeft45={"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}
CameraConfigLeft90={"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}
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=OBSBOT Meet 2 StreamCamera
CameraRight45=OBSBOT Meet 2 StreamCamera
CameraRight90=OBSBOT Meet 2 StreamCamera
CameraRight45=
CameraRight90=
FTPHost=192.168.10.2
FTPPass=password
FTPPath=/
FTPPort=21
FTPUser=user
PhotoDirectory=C\:\\Users\\rdkar\\OneDrive\\Desktop\\photoresult
PhotoDirectory=C\:\\Users\\Erha\\Desktop\\ErhaCapture
cascadeMaxSize=500
cascadeMinNeighbors=3
cascadeMinSize=250
cascadeScaleFactor=1.1

BIN
countdown321.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
dua.wav

Binary file not shown.

BIN
empat.wav

Binary file not shown.

12213
haarcascade_eye.xml Normal file

File diff suppressed because it is too large Load Diff

29690
haarcascade_profileface.xml Normal file

File diff suppressed because it is too large Load Diff

3527
haarcascades/fist.xml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

5211
haarcascades/rpalm.xml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

BIN
kesalahan_server.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,22 +1,26 @@
#Wed Oct 23 10:37:24 WIB 2024
AudioPhase1=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\out\\artifacts\\ErhaCam_jar\\audio\\phase1.mp3
AudioPhase2=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\out\\artifacts\\ErhaCam_jar\\audio\\phase2.mp3
AudioPhase3=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\out\\artifacts\\ErhaCam_jar\\audio\\phase3.mp3
AudioPhase4=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\out\\artifacts\\ErhaCam_jar\\audio\\phase4.mp3
AudioPhase5=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\out\\artifacts\\ErhaCam_jar\\audio\\phase5.mp3
CameraCenter=
CameraConfigCenter={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:1.0,"Sharpness"\:0.0,"Gamma"\:0.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigLeft45={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:1.0,"Sharpness"\:0.0,"Gamma"\:0.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigLeft90={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:1.0,"Sharpness"\:0.0,"Gamma"\:0.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigRight45={"Brightness"\:0.0,"Contrast"\:0.0,"Saturation"\:0.0,"Hue"\:0.0,"Gain"\:0.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"\:0.0,"Exposure"\:1.0,"Sharpness"\:0.0,"Gamma"\:0.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraLeft45=
CameraLeft90=
CameraRight45=
CameraRight90=
#Mon Feb 03 15:09:08 ICT 2025
AudioPhase1=\\\\RDKARTONO_SFG14\\ErhaCam_jar\\audio\\phase1.mp3
AudioPhase2=\\\\RDKARTONO_SFG14\\ErhaCam_jar\\audio\\phase2.mp3
AudioPhase3=\\\\RDKARTONO_SFG14\\ErhaCam_jar\\audio\\phase3.mp3
AudioPhase4=\\\\RDKARTONO_SFG14\\ErhaCam_jar\\audio\\phase4.mp3
AudioPhase5=\\\\RDKARTONO_SFG14\\ErhaCam_jar\\audio\\phase5.mp3
CameraCenter=OBSBOT Meet 2 StreamCamera
CameraConfigCenter={"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}
CameraConfigLeft45={"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}
CameraConfigLeft90={"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}
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=OBSBOT Meet 2 StreamCamera
CameraLeft90=OBSBOT Meet 2 StreamCamera
CameraRight45=OBSBOT Meet 2 StreamCamera
CameraRight90=OBSBOT Meet 2 StreamCamera
FTPHost=192.168.10.2
FTPPass=password
FTPPath=/
FTPPort=21
FTPUser=user
PhotoDirectory=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\out\\artifacts\\ErhaCam_jar
PhotoDirectory=\\\\RDKARTONO_SFG14\\ErhaCam_jar
cascadeMaxSize=400
cascadeMinNeighbors=3
cascadeMinSize=200
cascadeScaleFactor=1.1

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

BIN
pengambilan_berhasil.wav Normal file

Binary file not shown.

BIN
pengambilan_gagal.wav Normal file

Binary file not shown.

105
pom.xml
View File

@@ -36,16 +36,115 @@
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>javacv-platform</artifactId>-->
<!-- <version>1.5.10</version>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>leptonica-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>artoolkitplus-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>libdc1394-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>libfreenect-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>libfreenect2-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>flycapture-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>librealsense-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>librealsense2-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>tesseract-platform</artifactId>-->
<!-- </exclusion>-->
<!-- &lt;!&ndash; platform dibuangin semua, kemudian tambah sendiri linux-arm64, windows-x86_64, linux-x86_64 &ndash;&gt;-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>flandmark-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>openblas-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>ffmpeg-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>videoinput-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>javacpp-platform</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>opencv-platform</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<artifactId>javacv</artifactId>
<version>1.5.10</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>videoinput</artifactId>
<version>0.200-1.5.9</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
<version>1.5.10</version>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.10</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>

BIN
posisikan_wajah.wav Normal file

Binary file not shown.

BIN
satu.wav

Binary file not shown.

BIN
scan_barcode.wav Normal file

Binary file not shown.

View File

@@ -3,10 +3,37 @@ package BASS;
import lombok.Getter;
import org.tinylog.Logger;
@SuppressWarnings("unused")
public class AudioPlayer {
private final Bass bass = Bass.Instance;
private @Getter boolean inited = false;
private @Getter String currentFile = "";
private int currentFileHandle = 0;
public void WaitUntilFinished(){
while(currentFileHandle!=0){
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
}
}
public boolean isPlaying(){
return currentFileHandle!=0;
}
public void StopCurrentPlayback(){
if (currentFileHandle!=0){
if (bass.BASS_ChannelStop(currentFileHandle)){
Logger.info("AudioPlayer StopCurrentPlayback success");
} else Logger.error("AudioPlayer StopCurrentPlayback failed, error code: "+bass.BASS_ErrorGetCode());
}
currentFileHandle = 0;
currentFile = "";
}
/**
* Initialize AudioPlayer
@@ -18,6 +45,7 @@ public class AudioPlayer {
if (deviceid>-1){
int initflags = Bass.BASS_DEVICE_16BITS | Bass.BASS_DEVICE_STEREO | Bass.BASS_DEVICE_FREQ | Bass.BASS_DEVICE_REINIT;
if (bass.BASS_Init(deviceid,samplingrate,initflags)){
currentFileHandle = 0;
inited = true;
} else Logger.error("AudioPlayer initialization failed, BASS_Init failed, error code: " + bass.BASS_ErrorGetCode());
} else Logger.error("AudioPlayer initialization failed, deviceid is not correct");
@@ -34,6 +62,8 @@ public class AudioPlayer {
} else Logger.error("AudioPlayer Free failed, error code: "+bass.BASS_ErrorGetCode());
inited = false;
}
currentFile = "";
currentFileHandle = 0;
}
/**
@@ -75,10 +105,12 @@ public class AudioPlayer {
* @return true if success, false if failed
*/
public boolean PlayFile(final String filename, final PlaybackStatus playbackstatus){
if (inited){
if (inited && filename!=null && !filename.isEmpty()){
int filehandle = bass.BASS_StreamCreateFile(false, filename, 0, 0, 0);
if (filehandle!=0){
if (bass.BASS_ChannelStart(filehandle)){
currentFile = filename;
currentFileHandle = filehandle;
new Thread(()->{
if (playbackstatus!=null) playbackstatus.onPlaybackStarted(filename);
boolean iscontinue = true;
@@ -101,6 +133,8 @@ public class AudioPlayer {
}
}
if (playbackstatus!=null) playbackstatus.onPlaybackFinished(filename);
currentFile = "";
currentFileHandle = 0;
}).start();
return true;
} else Logger.error("AudioPlayer PlayFile failed, BASS_ChannelStart failed, error code: "+bass.BASS_ErrorGetCode());

View File

@@ -2,6 +2,13 @@ package Camera;
public interface LiveCamEvent {
void onDetectedQRCode(String qrCode);
void onFaceDetector(boolean hasface, int width, int height);
void onFrontalFaceDetector(boolean hasface, int width, int height);
void onProfileFaceDetector(boolean hasface, int width, int height);
void onEyeDetector(boolean hasEye, int width, int height);
void onLeftEarDetector(boolean hasLeftEar, int width, int height);
void onRightEarDetector(boolean hasRightEar, int width, int height);
void onLeftEyeDetector(boolean hasLeftEye, int width, int height);
void onRightEyeDetector(boolean hasRightEye, int width, int height);
void onLog(String log);
void onBlink(int counter);
}

View File

@@ -10,7 +10,7 @@ public enum ObsbotMeet2 {
Mode4(0.2, 640, 360, "16:9"),
Mode5(0.3, 640, 480, "4:3"),
ModeBest(8.3, 3840, 2160, "16:9"),
ModeLive(0.3, 640, 480, "4:3");
ModeLive(0.3, 640, 360, "16:9");
private final double Megapixel;
private final int width;

View File

@@ -1,7 +1,7 @@
package Config;
import id.co.gtc.erhacam.Detectors;
import lombok.Getter;
import lombok.val;
import org.tinylog.Logger;
import java.io.File;
@@ -40,6 +40,11 @@ public class ConfigFile {
private String PhotoDirectory;
private @Getter double cascadeScaleFactor;
private @Getter int cascadeMinNeighbors;
private @Getter int cascadeMinSize;
private @Getter int cascadeMaxSize;
private boolean needsave = false;
public ConfigFile(){
@@ -48,6 +53,34 @@ public class ConfigFile {
Load();
}
public void setCascadeScaleFactor(double value){
if (cascadeScaleFactor != value){
cascadeScaleFactor = value;
needsave = true;
}
}
public void setCascadeMinNeighbors(int value){
if (cascadeMinNeighbors != value){
cascadeMinNeighbors = value;
needsave = true;
}
}
public void setCascadeMinSize(int value){
if (cascadeMinSize != value){
cascadeMinSize = value;
needsave = true;
}
}
public void setCascadeMaxSize(int value){
if (cascadeMaxSize != value){
cascadeMaxSize = value;
needsave = true;
}
}
public void SetPhotoDirectory(String path){
if (ValidString(path)){
if (!path.equals(PhotoDirectory)){
@@ -528,6 +561,11 @@ public class ConfigFile {
if (prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()) == null) allcorrect = false;
if (prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()) == null) allcorrect = false;
if (prop.getProperty("cascadeScaleFactor") == null) allcorrect = false;
if (prop.getProperty("cascadeMinNeighbors") == null) allcorrect = false;
if (prop.getProperty("cascadeMinSize") == null) allcorrect = false;
if (prop.getProperty("cascadeMaxSize") == null) allcorrect = false;
if (allcorrect){
AudioPhase1 = prop.getProperty("AudioPhase1");
AudioPhase2 = prop.getProperty("AudioPhase2");
@@ -554,7 +592,17 @@ public class ConfigFile {
ConfigRight45 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()), CameraConfig.class);
ConfigRight90 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()), CameraConfig.class);
cascadeScaleFactor = toDouble(prop.getProperty("cascadeScaleFactor"));
cascadeMinNeighbors = toInt(prop.getProperty("cascadeMinNeighbors"));
cascadeMinSize = toInt(prop.getProperty("cascadeMinSize"));
cascadeMaxSize = toInt(prop.getProperty("cascadeMaxSize"));
Detectors.setFaceMaxSize(cascadeMaxSize);
Detectors.setFaceMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
Logger.info("Config Loaded");
MakeDirectories();
return;
} else {
Logger.info("Config File Not Correct, Creating Default");
@@ -568,6 +616,14 @@ public class ConfigFile {
CreateDefault();
}
private double toDouble(String cascadeScaleFactor) {
try{
return Double.parseDouble(cascadeScaleFactor);
} catch (Exception e){
return 1.1;
}
}
private void CreateDefault(){
AudioPhase1 = Path.of(currentDirectory, "audio", "phase1.mp3").toString();
AudioPhase2 = Path.of(currentDirectory, "audio", "phase2.mp3").toString();
@@ -590,9 +646,17 @@ public class ConfigFile {
SetDefaultCameraConfig(ConfigCenter);
SetDefaultCameraConfig(ConfigRight45);
SetDefaultCameraConfig(ConfigRight90);
cascadeScaleFactor = 1.1;
cascadeMinNeighbors = 3;
cascadeMinSize = 250;
cascadeMaxSize = 500;
Detectors.setFaceMaxSize(cascadeMaxSize);
Detectors.setFaceMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
Logger.info("Default Config Created");
needsave = true;
Save();
MakeDirectories();
}
private void SetDefaultCameraConfig(CameraConfig cc){
@@ -640,6 +704,11 @@ public class ConfigFile {
prop.setProperty(CameraConfigEnum.CameraConfigRight45.toString(), gson.toJson(ConfigRight45));
prop.setProperty(CameraConfigEnum.CameraConfigRight90.toString(), gson.toJson(ConfigRight90));
prop.setProperty("cascadeScaleFactor", String.valueOf(cascadeScaleFactor));
prop.setProperty("cascadeMinNeighbors", String.valueOf(cascadeMinNeighbors));
prop.setProperty("cascadeMinSize", String.valueOf(cascadeMinSize));
prop.setProperty("cascadeMaxSize", String.valueOf(cascadeMaxSize));
try{
prop.store(new FileOutputStream(Path.of(currentDirectory, "config.properties").toString()), null);
Logger.info("Config Saved");
@@ -647,4 +716,23 @@ public class ConfigFile {
Logger.error("Error Save Config: " + e.getMessage());
}
}
private @Getter String FullQualityDirectory;
private @Getter String FullQualityCropDirectory;
private @Getter String CompressedDirectory;
private @Getter String CompressedCropDirectory;
private @Getter String ThumbsDirectory;
private void MakeDirectories(){
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);
MakeDirectory(CompressedCropDirectory);
MakeDirectory(ThumbsDirectory);
}
}

View File

@@ -4,15 +4,17 @@ package Config;
import com.google.gson.Gson;
import com.google.zxing.MultiFormatReader;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.control.Alert;
import javafx.scene.image.Image;
import lombok.val;
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;
import org.bytedeco.opencv.opencv_core.Rect;
import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import org.bytedeco.opencv.opencv_core.UMat;
import org.tinylog.Logger;
import java.awt.image.BufferedImage;
@@ -28,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");
@@ -37,6 +41,10 @@ public class SomeCodes {
public static final Gson gson = new Gson();
public static final ConfigFile config = new ConfigFile();
public static String GetDateTimeString(){
return LocalDateTime.now().format(dtf);
}
public static Path GetLogsPath(){
return Path.of(currentDirectory, "logs");
}
@@ -94,6 +102,14 @@ public class SomeCodes {
}
public static String RectToString(Rect rect){
if (rect!=null){
return "X:"+rect.x()+",Y:"+rect.y()+",W:"+rect.width()+",H:"+rect.height();
}
return "";
}
/**
* Find thumbfile in thumbs directory
* @param sourcejpg source jpg file
@@ -101,12 +117,7 @@ public class SomeCodes {
*/
public static String FindThumbfile(String sourcejpg){
File sourcefile = new File(sourcejpg);
Path thumbpath = Path.of(sourcefile.getParent(), "thumbs");
try{
if (!Files.exists(thumbpath)) Files.createDirectories(thumbpath);
} catch (Exception e){
Logger.error("Error creating thumbs directory: "+thumbpath+", Msg : "+e.getMessage());
}
Path thumbpath = Path.of(config.getThumbsDirectory());
Path thumbfile = thumbpath.resolve(sourcefile.getName());
if (Files.exists(thumbfile)){
return thumbfile.toString();
@@ -114,6 +125,14 @@ public class SomeCodes {
return null;
}
public static void Wait(int millis){
try{
Thread.sleep(millis);
} catch (Exception e){
Logger.error("Error waiting: "+e.getMessage());
}
}
/**
* Make thumbfile from source jpg file
* @param sourcejpg source jpg file
@@ -124,23 +143,22 @@ public class SomeCodes {
try{
File ff = new File(sourcejpg);
if (ff.exists()){
Path thumbpath = Path.of(ff.getParent(), "thumbs");
if (!Files.exists(thumbpath)) Files.createDirectories(thumbpath);
String thumbfile = thumbpath.resolve(ff.getName()).toString();
String thumbfile = Path.of(config.getPhotoDirectory(),"thumbs", ff.getName()).toString();
File thumb = new File(thumbfile);
if (thumb.exists()) return thumbfile;
if (thumb.exists()) {
return thumbfile;
}
Mat source = opencv_imgcodecs.imread(sourcejpg);
if (source!=null && !source.empty()){
Mat resized = new Mat();
opencv_imgproc.resize(source, resized, thumbsize);
opencv_imgcodecs.imwrite(thumbfile, resized);
Logger.info("Thumbfile created: "+thumbfile);
return thumbfile;
} else Logger.info("MakeThumbfile failed, Source File not valid image : "+sourcejpg);
} else Logger.info("MakeThumbfile failed, Source File not found: "+sourcejpg);
}
}
} catch (Exception e){
Logger.error("Error making thumbfile: "+sourcejpg+", Msg : "+e.getMessage());
System.out.println("Error making thumbfile: "+sourcejpg+", Msg : "+e.getMessage());
}
return null;
}
@@ -153,6 +171,11 @@ public class SomeCodes {
return x.format(dtf);
}
/**
* Extract resource file to current directory
* @param filename resource file name
* @return extracted file path if success, or null if failed
*/
public static String ExtractResource(String filename){
try{
File destination = new File(currentDirectory, filename);
@@ -171,6 +194,11 @@ public class SomeCodes {
return null;
}
/**
* Check if path is valid directory
* @param path directory path
* @return true if valid directory, false if not valid directory
*/
public static boolean ValidDirectory(String path){
if (ValidString(path)){
File ff = new File(path);
@@ -179,10 +207,20 @@ public class SomeCodes {
return false;
}
/**
* Check if port number is valid
* @param port port number
* @return true if valid port number, false if not valid port number
*/
public static boolean ValidPortNumber(int port){
return port>0 && port<65536;
}
/**
* Convert string to integer
* @param x string
* @return integer value if success, or 0 if failed
*/
public static int toInt(String x){
try {
return Integer.parseInt(x);
@@ -191,6 +229,11 @@ public class SomeCodes {
}
}
/**
* Check if string is valid IPV4 address
* @param ipaddress IPV4 address
* @return true if valid IPV4 address, false if not valid IPV4 address
*/
public static boolean ValidIPV4(String ipaddress){
if (ValidString(ipaddress)){
try{
@@ -206,6 +249,11 @@ public class SomeCodes {
return false;
}
/**
* Check if string is valid IPV6 address
* @param ipaddress IPV6 address
* @return true if valid IPV6 address, false if not valid IPV6 address
*/
public static boolean ValidIPV6(String ipaddress){
if (ValidString(ipaddress)){
try{
@@ -221,6 +269,11 @@ public class SomeCodes {
return false;
}
/**
* Get file name from file path
* @param filepath file path
* @return file name if success, or empty string if failed
*/
public static String GetFileName(String filepath){
if (ValidString(filepath)){
File ff = new File(filepath);
@@ -231,6 +284,11 @@ public class SomeCodes {
return "";
}
/**
* Check if string is valid file
* @param filename file name
* @return true if valid file, false if not valid file
*/
public static boolean ValidFile(String filename){
if (ValidString(filename)){
File ff = new File(filename);
@@ -239,6 +297,113 @@ public class SomeCodes {
return false;
}
/**
* Read file as byte array
* @param filename file name
* @return byte array if success, or null if failed
*/
public static byte[] ReadFile(String filename){
if (ValidFile(filename)){
try{
return Files.readAllBytes(Path.of(filename));
} catch (Exception e){
Logger.error("Error reading file: "+filename+", Msg : "+e.getMessage());
}
}
return null;
}
/**
* Resize Rect
* @param original original Rect
* @param scaleX scale factor
* @param scaleY scale factor
* @param Xoffset X offset, positive value to increase width, negative value to decrease width
* @param Yoffset Y offset, positive value to increase height, negative value to decrease height
* @return resized Rect if success, or null if failed
*/
public static Rect ResizeRect(Rect original, double scaleX, double scaleY, int Xoffset, int Yoffset){
if (original!=null){
int newX = (int)(original.x()*scaleX);
newX -= Xoffset;
if (newX<0) newX = 0;
int newY = (int)(original.y()*scaleY);
newY -= Yoffset;
if (newY<0) newY = 0;
int newWidth = (int)(original.width()*scaleX);
newWidth += Xoffset*2;
int newHeight = (int)(original.height()*scaleX);
newHeight += Yoffset*2;
return new Rect(newX, newY, newWidth, newHeight);
}
return null;
}
public static UMat CropUMat(UMat source, Rect ROI){
if (source!=null && !source.empty() && ValidROI(ROI)){
int x = ROI.x();
int y = ROI.y();
int width = ROI.width();
int height = ROI.height();
if (x>=0 && y>=0 && width>0 && height>0){
if (x+width>source.cols()) width = source.cols()-x;
if (y+height>source.rows()) height = source.rows()-y;
if (width>0 && height>0){
Rect crop = new Rect(x, y, width, height);
return new UMat(source, crop);
}
}
}
return null;
}
public static boolean Save(UMat source, String filename, int[] param){
if (source!=null && !source.empty() && ValidString(filename)){
try{
return opencv_imgcodecs.imwrite(filename, source, param);
} catch (Exception e){
Logger.error("Error saving file: "+filename+", Msg : "+e.getMessage());
}
}
return false;
}
/**
* Concatenate byte arrays
* @param args byte arrays
* @return concatenated byte array if success, or null if failed
*/
public static byte[] Concat(byte[]... args){
if (args!=null && args.length>0){
int total = 0;
for(byte[] x : args){
if (x!=null && x.length>0){
total += x.length;
}
}
if (total>0){
byte[] result = new byte[total];
int offset = 0;
for(byte[] x : args){
if (x!=null && x.length>0){
System.arraycopy(x, 0, result, offset, x.length);
offset += x.length;
}
}
return result;
}
}
return null;
}
/**
* Check if string is valid
* @param x string
* @return true if valid, false if not valid
*/
public static boolean ValidString(String x){
if (x!=null){
return !x.isEmpty();
@@ -246,6 +411,10 @@ public class SomeCodes {
return false;
}
/**
* Open picture in default viewer
* @param filename picture file name
*/
public static void OpenPictureInDefaultViewer(String filename){
try{
File ff = new File(filename);
@@ -275,20 +444,16 @@ public class SomeCodes {
}
}
public static CascadeClassifier faceDetector;
public static void LoadFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
if (filename!=null) {
if (faceDetector==null) {
faceDetector = new CascadeClassifier(filename);
Logger.info("FaceDetector loaded");
}
}
}
/**
* Make array from string arguments
* @param args string arguments
* @return array of strings if success, or empty array if failed
*/
public static String[] MakeArray(String... args){
if (args!=null && args.length>0){
List<String> ll = new ArrayList<String>();
List<String> ll = new ArrayList<>();
for(String x : args){
if (ValidString(x)) ll.add(x);
}
@@ -297,8 +462,193 @@ public class SomeCodes {
return new String[0];
}
public static boolean ValidBarCode(String value){
if (value!=null && value.length()==10){
boolean valid = true;
for(int i=0; i<value.length(); i++){
if (!Character.isDigit(value.charAt(i))){
valid = false;
break;
}
}
return valid;
}
return false;
}
/**
* Check if Valid PatientID found
* Patient ID is 10 digits number
* @param patientid Patient ID
* @return true if valid, false if not valid
*/
public static boolean ValidMedicalRecordId(String patientid){
if (patientid!=null && !patientid.isEmpty()){
boolean valid = true;
for(int i=0; i<patientid.length(); i++){
if (!Character.isDigit(patientid.charAt(i))){
valid = false;
break;
}
}
return valid;
} else return false;
}
/**
* Check Region of Interest is a valid Rect
* @param ROI Region of Interest
* @return true if valid, false if not valid
*/
public static boolean ValidROI(Rect ROI){
if (ROI!=null){
if (ROI.x()>=0){
if (ROI.y()>=0){
if (ROI.width()>0){
if (ROI.height()>0){
return true;
}
}
}
}
}
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
* @param mat UMat
* @return true if inside, false if not inside
*/
public static boolean ROIInsideUMat(Rect ROI, UMat mat){
if (ValidROI(ROI)){
if (mat!=null){
return ROI.x()>=0 && ROI.y()>=0 &&
ROI.x()+ROI.width()<=mat.cols() &&
ROI.y()+ROI.height()<=mat.rows();
}
}
return false;
}
/**
* Check if Region of Interest 1 is same with Region of Interest 2
* @param ROI1 Region of Interest 1
* @param ROI2 Region of Interest 2
* @return true if same, false if not same
*/
public static boolean IsSameROI(Rect ROI1, Rect ROI2){
if (ValidROI(ROI1) && ValidROI(ROI2)){
return ROI1.x()==ROI2.x() && ROI1.y()==ROI2.y() &&
ROI1.width()==ROI2.width() && ROI1.height()==ROI2.height();
}
return false;
}
/**
* Check if Rect 1 is inside Rect 2
* @param smaller Rect 1
* @param bigger Rect 2
* @return true if inside, false if not inside
*/
public static boolean IsInsideRect(Rect smaller, Rect bigger){
if (smaller!=null && bigger!=null){
return smaller.x()>=bigger.x() && smaller.y()>=bigger.y() &&
smaller.x()+smaller.width()<=bigger.x()+bigger.width() &&
smaller.y()+smaller.height()<=bigger.y()+bigger.height();
}
return false;
}
/**
* Make directory if not exists
* @param path directory path
*/
public static void MakeDirectory(String path){
if (ValidString(path)){
File ff = new File(path);
if (!ff.isDirectory()){
try{
Files.createDirectories(ff.toPath());
Logger.info("Directory created: "+path);
} catch (Exception e){
Logger.info("Error creating directory: "+path+", Msg : "+e.getMessage());
}
} else Logger.info("Directory exists: "+path);
}
}
public static short ToShort(String x){
try{
return Short.parseShort(x);
} catch (Exception e){
return 0;
}
}
public static void ShowAlert(Alert.AlertType type, String title, String header, String content){
Alert alert = new Alert(type);
alert.setTitle(title);
alert.setHeaderText(header);
alert.setContentText(content);
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<lowest){
lowest = x;
}
}
return lowest;
}
return 0;
}
public static double CalculateSharpness(UMat mat){
if (mat!=null && !mat.empty()){
UMat gray = new UMat();
opencv_imgproc.cvtColor(mat, gray, opencv_imgproc.COLOR_BGR2GRAY);
UMat laplacian = new UMat();
opencv_imgproc.Laplacian(gray, laplacian, CV_64F);
UMat mean = new UMat(1,1, CV_64F);
UMat stddev = new UMat(1,1, CV_64F);
opencv_core.meanStdDev(laplacian, mean, stddev);
Mat _std = new Mat();
stddev.copyTo(_std);
return _std.ptr(0).getDouble() * _std.ptr(0).getDouble();
}
return 0;
}
public static boolean IsBlurred(UMat mat, double threshold){
return CalculateSharpness(mat)<threshold;
}
}

View File

@@ -10,10 +10,25 @@ public class PhotoReviewClass {
private String DateTime;
private String Prefix;
private String FileLeft90;
private String CompressedLeft90;
private String CroppedLeft90;
private String CompressedCropLeft90;
private String FileLeft45;
private String CompressedLeft45;
private String CroppedLeft45;
private String CompressedCropLeft45;
private String FileCenter;
private String CompressedCenter;
private String CroppedCenter;
private String CompressedCropCenter;
private String FileRight45;
private String CompressedRight45;
private String CroppedRight45;
private String CompressedCropRight45;
private String FileRight90;
private String CompressedRight90;
private String CroppedRight90;
private String CompressedCropRight90;
private String ThumbLeft90;
private String ThumbLeft45;
private String ThumbCenter;
@@ -52,16 +67,49 @@ public class PhotoReviewClass {
this.ThumbRight90 = ThumbRight90;
}
@Override
public String toString(){
return "id: "+id+"\r\nDateTime: "+DateTime+"\r\nPrefix: "+Prefix+"\r\nFileLeft90: "+FileLeft90+"\r\nFileLeft45: "+FileLeft45+"\r\nFileCenter: "+FileCenter+"\r\nFileRight45: "+FileRight45+"\r\nFileRight90: "+FileRight90+"\r\nThumbLeft90: "+ThumbLeft90+"\r\nThumbLeft45: "+ThumbLeft45+"\r\nThumbCenter: "+ThumbCenter+"\r\nThumbRight45: "+ThumbRight45+"\r\nThumbRight90: "+ThumbRight90;
}
/**
* Get all files that are not null
* Get all Full Resolution files that are not null
* @return array of files
*/
public String[] files(){
public String[] fullres(){
return MakeArray(FileLeft90, FileLeft45, FileCenter, FileRight45, FileRight90);
}
/**
* Get all Thumbnail files that are not null
* @return array of files
*/
public String[] thumbnails(){
return MakeArray(ThumbLeft90, ThumbLeft45, ThumbCenter, ThumbRight45, ThumbRight90);
}
/**
* Get all Compressed files that are not null
* @return array of files
*/
public String[] compressed(){
return MakeArray(CompressedLeft90, CompressedLeft45, CompressedCenter, CompressedRight45, CompressedRight90);
}
/**
* Get all Cropped full resolution files that are not null
* @return array of files
*/
public String[] cropped(){
return MakeArray(CroppedLeft90, CroppedLeft45, CroppedCenter, CroppedRight45, CroppedRight90);
}
/**
* Get all Cropped compressed files that are not null
* @return array of files
*/
public String[] compressedcrop(){
return MakeArray(CompressedCropLeft90, CompressedCropLeft45, CompressedCropCenter, CompressedCropRight45, CompressedCropRight90);
}
}

View File

@@ -3,7 +3,6 @@ package Database;
import static Config.SomeCodes.LocalDateTimeToString;
import static Config.SomeCodes.ValidString;
import lombok.val;
import org.tinylog.Logger;
import java.sql.*;
@@ -41,6 +40,8 @@ public class Sqlite {
*/
public void Insert(PhotoReviewClass pr){
if (pr!=null){
// System.out.println("Inserting PhotoReviewClass");
// System.out.println(pr);
Insert(pr.getPrefix(), pr.getFileLeft90(), pr.getFileLeft45(), pr.getFileCenter(), pr.getFileRight45(), pr.getFileRight90(), pr.getThumbLeft90(), pr.getThumbLeft45(), pr.getThumbCenter(), pr.getThumbRight45(), pr.getThumbRight90());
}
}
@@ -107,6 +108,13 @@ public class Sqlite {
try{
Connection conn = GetConnection();
if (conn != null){
// System.out.println("Inserting data");
// System.out.println("prefix: "+prefix);
// System.out.println("fileLeft90: "+fileLeft90);
// System.out.println("fileLeft45: "+fileLeft45);
// System.out.println("fileCenter: "+fileCenter);
// System.out.println("fileRight45: "+fileRight45);
// System.out.println("fileRight90: "+fileRight90);
PreparedStatement stmt = conn.prepareStatement("INSERT INTO photos (DateTime, Prefix, FileLeft90, FileLeft45, FileCenter, FileRight45, FileRight90, ThumbLeft90, ThumbLeft45, ThumbCenter, ThumbRight45, ThumbRight90 ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
stmt.setString(1, LocalDateTimeToString(LocalDateTime.now()));

View File

@@ -0,0 +1,29 @@
package ErhaAPI;
public class BarcodeResullt {
public int currentPage;
public int limit;
public int totalPages;
public int totalRecords;
public String message;
public boolean error;
public String errorId;
public String errorMessage;
public String errorCode;
public PatientRecord[] data;
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("currentPage : ").append(currentPage).append(", limit : ").append(limit).append(", totalPages : ").append(totalPages).append(", totalRecords : ").append(totalRecords).append(", message : ").append(message).append(", error : ").append(error);
if (data != null){
sb.append(", data : [");
for (PatientRecord pr : data){
sb.append(pr.toString()).append(", ");
}
sb.append("]");
}
return sb.toString();
}
}

View File

@@ -0,0 +1,195 @@
package ErhaAPI;
import Config.SomeCodes;
import com.google.gson.Gson;
import lombok.Getter;
import org.tinylog.Logger;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.util.Base64;
import java.util.UUID;
import static Config.SomeCodes.*;
public class ErhaAPI {
private @Getter String API_USERNAME = "erha-pb-001";
private @Getter String API_PASSWORD = "bM0tH!s";
private String auth;
private final String API_URL;
private final Gson gson = new Gson();
/**
* Create Erha API object
* @param isProduction if true will use Production URL, if false will use Staging URL
*/
public ErhaAPI(boolean isProduction){
final String API_URL_PROD = "https://connect-api.aryanoble.co.id/api";
final String API_URL_STAGING = "https://connect-api-staging.aryanoble.web.id/api";
API_URL = isProduction ? API_URL_PROD : API_URL_STAGING;
update_auth();
}
/**
* Set API Username
* @param API_USERNAME API Username
*/
@SuppressWarnings("unused")
public void setAPI_USERNAME(String API_USERNAME){
if (ValidString(API_USERNAME)){
if (!API_USERNAME.equals(this.API_USERNAME)){
this.API_USERNAME = API_USERNAME;
update_auth();
}
}
}
/**
* Set API Password
* @param API_PASSWORD API Password
*/
@SuppressWarnings("unused")
public void setAPI_PASSWORD(String API_PASSWORD){
if (ValidString(API_PASSWORD)){
if (!API_PASSWORD.equals(this.API_PASSWORD)){
this.API_PASSWORD = API_PASSWORD;
update_auth();
}
}
}
/**
* Validate Barcode data
* @param Barcode Barcode to verify
* @return BarcodeResullt object if success, or null if failed
*/
public BarcodeResullt Validate_Barcode(String Barcode, boolean printdebug){
if (ValidBarCode(Barcode)){
try (HttpClient client = HttpClient.newHttpClient()) {
int medical_record_detail_id = toInt(Barcode);
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create(API_URL+"/photobooth/photobooth/" + medical_record_detail_id))
.header("Authorization", "Basic " + auth)
.GET()
.build();
HttpResponse<String> 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 {
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;
}
/**
* Upload File
* @param patientID Patient ID
* @param filename File to upload
* @return null if failed, or response body if success
*/
public UploadResult Upload_File(String patientID, String filename, boolean printdebug) {
if (ValidMedicalRecordId(patientID)){
int medical_record_detail_id = toInt(patientID);
if (ValidFile(filename)){
File ff = new File(filename);
try (HttpClient client = HttpClient.newHttpClient()){
byte[] fileBytes = Files.readAllBytes(new java.io.File(filename).toPath());
String fn = ff.getName();
// Unique boundary for multipart data
String boundary = "----JavaHttpClientBoundary" + UUID.randomUUID();
String CRLF = "\r\n";
// Form Data (Text Field)
String formData1 = "--" + boundary + CRLF +
"Content-Disposition: form-data; name=\"medical_record_detail_id\"" + CRLF + CRLF +
medical_record_detail_id + CRLF;
// Form Data (File)
String formData2 = "--" + boundary + CRLF +
"Content-Disposition: form-data; name=\"file\"; filename=\"" + fn + "\"" + CRLF +
"Content-Type: image/jpeg" + CRLF + CRLF; // Change Content-Type accordingly
// End Boundary
String endBoundary = CRLF + "--" + boundary + "--" + CRLF;
// Combine all parts into a single byte array
byte[] multipartData = SomeCodes.Concat(
formData1.getBytes(),
formData2.getBytes(),
fileBytes,
endBoundary.getBytes()
);
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(API_URL + "/photobooth/photobooth"))
.header("Authorization", "Basic " + auth)
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
.POST(HttpRequest.BodyPublishers.ofByteArray(multipartData))
.build();
// Send request
HttpResponse<String> 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());
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());
}
}
}
return null;
}
private void update_auth(){
auth = Base64.getEncoder().encodeToString((API_USERNAME + ":" + API_PASSWORD).getBytes());
}
}

View File

@@ -0,0 +1,23 @@
package ErhaAPI;
public class PatientRecord {
public String medical_record_detail_id;
public String medical_staff_id;
public String medical_staff_name;
public String branch_id;
public String branch_code;
public String branch_name;
public String registration_id;
public String registration_date;
public String patient_id;
public String mrnl;
public String name;
public String phone;
public String birthdate;
public String service;
@Override
public String toString(){
return "medical_record_detail_id : " + medical_record_detail_id + ", medical_staff_id : " + medical_staff_id + ", medical_staff_name : " + medical_staff_name + ", branch_id : " + branch_id + ", branch_code : " + branch_code + ", branch_name : " + branch_name + ", registration_id : " + registration_id + ", registration_date : " + registration_date + ", patient_id : " + patient_id + ", mrnl : " + mrnl + ", name : " + name + ", phone : " + phone + ", birthdate : " + birthdate + ", service : " + service;
}
}

View File

@@ -0,0 +1,48 @@
package ErhaAPI;
import lombok.Getter;
import lombok.Setter;
import org.bytedeco.opencv.opencv_core.Rect;
@Getter @Setter
public class PhotoResult {
private final String cameraname;
private String fullres;
private String compressedfile;
private String fullcrop;
private String compressedcrop;
private String thumbnail;
private Rect BestROI;
private Rect ReducedROI;
private double sharpscore;
public PhotoResult(String cameraname){
this.cameraname = cameraname;
this.fullres = "";
this.compressedfile = "";
this.fullcrop = "";
this.compressedcrop = "";
this.thumbnail = "";
this.BestROI = null;
this.ReducedROI = null;
}
public PhotoResult(String cameraname,String fullres, String compressedfile, String fullcrop, String compressedcrop, String thumbnail){
this.cameraname = cameraname;
this.fullres = fullres;
this.compressedfile = compressedfile;
this.fullcrop = fullcrop;
this.compressedcrop = compressedcrop;
this.thumbnail = thumbnail;
this.BestROI = null;
this.ReducedROI = null;
}
@Override
public String toString(){
return "Camera Name: " + cameraname + "\n" +
"Full Resolution: " + fullres + "\n" +
"Compressed File: " + compressedfile + "\n" +
"Full Crop: " + fullcrop + "\n" +
"Compressed Crop: " + compressedcrop + "\n" +
"Thumbnail: " + thumbnail + "\n";
}
}

View File

@@ -0,0 +1,18 @@
package ErhaAPI;
public class UploadResult {
public int currentPage;
public int limit;
public int totalPages;
public int totalRecords;
public boolean error;
public String errorId;
public String errorMessage;
public String errorCode;
public String message;
@Override
public String toString(){
return "message : " + message + ", error : " + error + ", errorId : " + errorId + ", errorMessage : " + errorMessage + ", errorCode : " + errorCode ;
}
}

View File

@@ -0,0 +1,107 @@
package SecureDongle;
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface LibSecureDongle extends Library {
LibSecureDongle Instance = (LibSecureDongle) Native.load("SecureDongleJ", LibSecureDongle.class);
short SD_FIND=1;
short SD_FIND_NEXT=2;
short SD_OPEN=3;
short SD_CLOSE=4;
short SD_READ=5;
short SD_WRITE=6;
short SD_RANDOM=7;
short SD_SEED=8;
short SD_WRITE_USERID=9;
short SD_READ_USERID=10;
short SD_SET_MODULE=11;
short SD_CHECK_MODULE=12;
short SD_WRITE_ARITHMETIC=13;
short SD_CALCULATE1=14;
short SD_CALCULATE2=15;
short SD_CALCULATE3=16;
short SD_DECREASE=17;
short SD_SET_RSAKEY_N=29;
short SD_SET_RSAKEY_D=30;
short SD_SET_DES_KEY=41;
short SD_DES_ENC=42;
short SD_DES_DEC=43;
short SD_RSA_ENC=44;
short SD_RSA_DEC=45;
short SD_READ_EX=46;
short SD_WRITE_EX=47;
short SD_SET_COUNTER_EX=160;
short SD_GET_COUNTER_EX=161;
short SD_SET_TIMER_EX=162;
short SD_GET_TIMER_EX=163;
short SD_ADJUST_TIMER_EX=164;
short SD_UPDATE_GEN_HEADER_EX=165;
short SD_UPDATE_GEN_EX=166;
short SD_UPDATE_CHECK_EX=167;
short SD_UPDATE_EX=168;
short SD_SET_UPDATE_KEY=169;
short SD_ADD_UPDATE_HEADER=170;
short SD_ADD_UPDATE_CONTENT=171;
short SD_GET_TIME_DWORD=172;
short SD_VERSION=100;
short DES_SINGLE_MODE=0;
short DES_TRIPLE_MODE=1;
short RSA_PRIVATE_KEY=0;
short RSA_PUBLIC_KEY=1;
short RSA_SECUREDONGLE_PADDING=0;
short RSA_USER_PADDING=1;
//error code
short ERR_SUCCESS=0;
short ERR_NO_ROCKEY=3;
short ERR_INVALID_PASSWORD=4;
short ERR_INVALID_PASSWORD_OR_ID=5;
short ERR_SETID=6;
short ERR_INVALID_ADDR_OR_SIZE=7;
short ERR_UNKNOWN_COMMAND=8;
short ERR_NOTBELEVEL3=9;
short ERR_READ=10;
short ERR_WRITE=11;
short ERR_RANDOM=12;
short ERR_SEED=13;
short ERR_CALCULATE=14;
short ERR_NO_OPEN=15;
short ERR_OPEN_OVERFLOW=16;
short ERR_NOMORE=17;
short ERR_NEED_FIND=18;
short ERR_DECREASE=19;
short ERR_AR_BADCOMMAND=20;
short ERR_AR_UNKNOWN_OPCODE=21;
short ERR_AR_WRONGBEGIN=22;
short ERR_AR_WRONG_END=23;
short ERR_AR_VALUEOVERFLOW=24;
short ERR_TOOMUCHTHREAD=25;
short ERR_INVALID_SD=30;
short ERR_INVALID_PARAMETER=31;
short ERR_INVALID_TIMEVALUE=32;
short ERR_SET_DES_KEY=40;
short ERR_DES_ENCRYPT=41;
short ERR_DES_DECRYPT=42;
short ERR_SET_RSAKEY_N=43;
short ERR_SET_RSAKEY_D=44;
short ERR_RSA_ENCRYPT=45;
short ERR_RSA_DECRYPT=46;
short ERR_INVALID_LENGTH=47;
short ERR_UNKNOWN=-1;
short ERR_RECEIVE_NULL=256;
short ERR_INVALID_BUFFER=257;
short ERR_UNKNOWN_SYSTEM=258;
short ERR_UNINIT_TIME_UNIT=259;
short SecureDongle(short command, short[] handle, int[] lp1, int[] lp2, short[] p1, short[] p2, short[] p3, short[] p4, byte[] buffer);
}

View File

@@ -0,0 +1,273 @@
package SecureDongle;
import lombok.Getter;
import lombok.Setter;
import org.tinylog.Logger;
import java.util.function.Consumer;
import static Config.SomeCodes.ToShort;
public class SecureDongle {
private final int[] lp1 = new int[1];
private final int[] lp2 = new int[1];
// for Open/Close Handle
private final short[] handle = new short[1];
// P1
private final short[] p1 = new short[1];
// P2
private final short[] p2 = new short[1];
// P3
private final short[] p3 = new short[1];
// P4
private final short[] p4 = new short[1];
private final byte[] buffer = new byte[1024];
LibSecureDongle SD;
private @Getter boolean Opened = false;
private @Getter short Handle;
private @Getter int HardwareID = 0;
private @Getter int UserID = 0;
private @Setter SecureDongleEvent event;
/**
* Create SecureDongle with P1, P2, P3, P4
* @param P1 Password 1
* @param P2 Password 2
* @param P3 Password 3
* @param P4 Password 4
*/
public SecureDongle(Short P1, Short P2, Short P3, Short P4){
this.p1[0] = P1;
this.p2[0] = P2;
this.p3[0] = P3;
this.p4[0] = P4;
SD = LibSecureDongle.Instance;
}
/**
* Create SecureDongle with P1, P2, P3, P4
* @param P1 Password 1
* @param P2 Password 2
* @param P3 Password 3
* @param P4 Password 4
*/
public SecureDongle(String P1, String P2, String P3, String P4){
this.p1[0] = ToShort(P1);
this.p2[0] = ToShort(P2);
this.p3[0] = ToShort(P3);
this.p4[0] = ToShort(P4);
SD = LibSecureDongle.Instance;
}
/**
* Find SecureDongle
* This must be executed first time
* @return true if found
*/
public boolean Find(){
HardwareID = 0;
short result = SD.SecureDongle(LibSecureDongle.SD_FIND, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
HardwareID = lp1[0];
//System.out.println("SecureDongle found with HardwareID="+HardwareID);
return true;
} else {
if (event!=null) event.onDongleError("Find", result);
}
return false;
}
/**
* Open SecureDongle
* @return true if success
*/
public boolean Open(){
Handle=0;
if (HardwareID!=0){
lp1[0] = HardwareID;
short result = SD.SecureDongle(LibSecureDongle.SD_OPEN, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
Handle = handle[0];
Opened = true;
return true;
} else if (event!=null) event.onDongleError("Open", result);
} //else System.out.println("HardwareID not found, Find SecureDongle first");
return false;
}
/**
* Close SecureDongle
* @return true if success
*/
public boolean Close(){
handle[0] = Handle;
short result = SD.SecureDongle(LibSecureDongle.SD_CLOSE, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
return true;
} else if (event!=null) event.onDongleError("Close", result);
Opened = false;
return false;
}
/**
* Read from User Data Zone (UDZ)
* @param StartAddress Start Address, zero based
* @param Length Length of data to read, max 1000 bytes
* @return byte array of data, length=0 if failed
*/
public byte[] Read(short StartAddress, short Length){
if (Opened){
handle[0] = Handle;
p1[0] = StartAddress>=0 ? StartAddress : 0;
if (Length<1) Length=1;
if (Length>1000) Length=1000;
p2[0] = Length;
short result = SD.SecureDongle(LibSecureDongle.SD_READ, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" read success ");
byte[] data = new byte[Length];
System.arraycopy(buffer, 0, data, 0, Length);
return data;
} else if (event!=null) event.onDongleError("Read", result);
} //else System.out.println("SecureDongle not opened");
return new byte[0];
}
/**
* Write to User Data Zone (UDZ)
* @param StartAddress start address of UDZ, zero based
* @param length length of data to write, max 1000 bytes
* @param data data to write
* @return true if success
*/
public boolean Write(short StartAddress, short length, byte[] data){
if (Opened){
handle[0] = Handle;
p1[0] = StartAddress>=0 ? StartAddress : 0;
if (length<1) length=1;
if (length>1000) length=1000;
p2[0] = length;
System.arraycopy(data, 0, buffer, 0, length);
short result = SD.SecureDongle(LibSecureDongle.SD_WRITE, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" write success ");
return true;
} else if (event!=null) event.onDongleError("Write", result);
} //else System.out.println("SecureDongle not opened");
return false;
}
/**
* Generate Random Number
* @return short array of random number
*/
public short[] GenerateRandomNumber(){
short[] random = new short[4];
if (Opened){
handle[0] = Handle;
short result = SD.SecureDongle(LibSecureDongle.SD_RANDOM, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" generate random success ");
random[0] = p1[0];
random[1] = p2[0];
random[2] = p3[0];
random[3] = p4[0];
return random;
} else if (event!=null) event.onDongleError("GenerateRandomNumber", result);
} //else System.out.println("SecureDongle not opened");
return random;
}
/**
* Write UserID to SecureDongle
* @param UserID UserID to write
* @return true if success
*/
public boolean WriteUserID(int UserID){
if (Opened){
handle[0] = Handle;
lp1[0] = UserID;
short result = SD.SecureDongle(LibSecureDongle.SD_WRITE_USERID, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" set UserID success ");
this.UserID = UserID;
return true;
} else if (event!=null) event.onDongleError("WriteUserID", result);
} //else System.out.println("SecureDongle not opened");
return false;
}
/**
* Read UserID from SecureDongle
* @return UserID, 0 if failed
*/
public int ReadUserID(){
if (Opened){
handle[0] = Handle;
short result = SD.SecureDongle(LibSecureDongle.SD_READ_USERID, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
this.UserID = lp1[0];
//System.out.println("SecureDongle HardwareID="+HardwareID+" read UserID success, value = "+UserID);
return UserID;
} else if (event!=null) event.onDongleError("ReadUserID", result);
} //else System.out.println("SecureDongle not opened");
return 0;
}
boolean ismonitoring = false;
/**
* Stop Monitoring SecureDongle
*/
public void StopMonitor(){
ismonitoring = false;
}
/**
* Start Monitoring SecureDongle
* if dongle missing, will raise event onDongleMissing
*/
public void StartMonitor(){
new Thread(()->{
if (HardwareID==0) Find();
Open();
int firstUserID = ReadUserID();
Close();
if (firstUserID!=0){
ismonitoring = true;
Logger.info("Start Monitoring UserID="+Integer.toHexString(firstUserID));
while (ismonitoring){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Open();
int newUserID = ReadUserID();
Close();
if (newUserID!=firstUserID){
if (event!=null) event.onDongleMissing();
}
}
System.out.println("Stop Monitoring");
} else System.out.println("Canceled Monitoring, UserID not found");
}).start();
}
}

View File

@@ -0,0 +1,6 @@
package SecureDongle;
public interface SecureDongleEvent {
void onDongleMissing();
void onDongleError(String function,int errorCode);
}

View File

@@ -0,0 +1,102 @@
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;
import java.util.function.Consumer;
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
* @param onClose What to do after auto close
*/
public static void show(String title, String header, String content, int seconds, Consumer<String> onClose) {
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;
}
if (onClose!=null) onClose.accept(shownTitle);
clear();
} );
delay.play();
}
});
}
}

View File

@@ -1,9 +1,10 @@
package id.co.gtc.erhacam;
import Camera.ArducamIMX477Preset;
import Camera.CameraProperty;
import Camera.LiveCamEvent;
import Camera.ObsbotMeet2Preset;
import Config.CameraConfigEnum;
import ErhaAPI.PhotoResult;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
@@ -11,8 +12,6 @@ import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.Slider;
@@ -24,11 +23,15 @@ import javafx.scene.image.WritableImage;
import javafx.scene.layout.AnchorPane;
import lombok.Getter;
import lombok.Setter;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameGrabber;
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.*;
import org.opencv.videoio.Videoio;
import org.tinylog.Logger;
import java.awt.image.BufferedImage;
@@ -36,19 +39,31 @@ import java.awt.image.DataBufferByte;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
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"})
public class Cameradetail {
private static final boolean isCudaAvailable ;
static{
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");
}
}
private final AtomicBoolean Capturing = new AtomicBoolean(false);
private final AtomicBoolean TakingPhoto = new AtomicBoolean(false);
private final AtomicBoolean IsGrabbingLiveView = new AtomicBoolean(false);
@@ -87,11 +102,35 @@ public class Cameradetail {
@FXML
private Slider exposureSlider;
private @Getter final UMat BestMat = new UMat();
private @Getter final UMat LiveMat = new UMat();
private @Getter final UMat ReducedMat = new UMat();
private @Getter Rect BestMatROI;
private @Getter Rect ReducedMatROI;
private @Getter Rect LiveMatROI;
private boolean IsPortrait = false;
// putar portrait
private @Getter Size LiveSize = new Size(360, 640);
private @Getter Size ReducedSize = new Size(720, 1280);
private @Getter Size BestSize = new Size(2160, 3840);
//TODO ini angka dari Erha, cek apakah masih cocok atau tidak
private @Getter @Setter Size FullCropSize = new Size(1036,1036);
public int getBestWidth(){
return BestSize.width();
}
public int getBestHeight(){
return BestSize.height();
}
int[] paramjpeg = {opencv_imgcodecs.IMWRITE_JPEG_QUALITY, 100};
int[] parampng = {opencv_imgcodecs.IMWRITE_PNG_COMPRESSION, 0};
private final UMat BestMat = new UMat();
private final UMat LiveMat = new UMat();
private Size LiveSize = new Size(640, 480);
private Size PhotoSize = new Size(1920, 1080);
private void setSliderValue(Slider sld, CameraProperty prop, double value){
if (sld!=null){
@@ -121,12 +160,12 @@ public class Cameradetail {
streamanchor.widthProperty().addListener(obs -> resize_streamanchor());
Platform.runLater(()->{
setSliderValue(brightnessSlider, ArducamIMX477Preset.Brightness, config.getBrightness(cameraConfigEnum));
setSliderValue(contrastSlider, ArducamIMX477Preset.Contrast, config.getContrast(cameraConfigEnum));
setSliderValue(saturationSlider, ArducamIMX477Preset.Saturation, config.getSaturation(cameraConfigEnum));
setSliderValue(hueSlider, ArducamIMX477Preset.Hue, config.getHue(cameraConfigEnum));
setSliderValue(gainSlider, ArducamIMX477Preset.Gain, config.getGain(cameraConfigEnum));
setSliderValue(exposureSlider, ArducamIMX477Preset.ExposureTime, config.getExposure(cameraConfigEnum));
setSliderValue(brightnessSlider, ObsbotMeet2Preset.Brightness, config.getBrightness(cameraConfigEnum));
setSliderValue(contrastSlider, ObsbotMeet2Preset.Contrast, config.getContrast(cameraConfigEnum));
setSliderValue(saturationSlider, ObsbotMeet2Preset.Saturation, config.getSaturation(cameraConfigEnum));
setSliderValue(hueSlider, ObsbotMeet2Preset.Hue, config.getHue(cameraConfigEnum));
setSliderValue(gainSlider, ObsbotMeet2Preset.Gain, config.getGain(cameraConfigEnum));
setSliderValue(exposureSlider, ObsbotMeet2Preset.ExposureTime, config.getExposure(cameraConfigEnum));
});
@@ -167,12 +206,12 @@ public class Cameradetail {
@FXML
public void resetClick(){
brightnessSlider.adjustValue(ArducamIMX477Preset.Brightness.Default);
contrastSlider.adjustValue(ArducamIMX477Preset.Contrast.Default);
saturationSlider.adjustValue(ArducamIMX477Preset.Saturation.Default);
hueSlider.adjustValue(ArducamIMX477Preset.Hue.Default);
gainSlider.adjustValue(ArducamIMX477Preset.Gain.Default);
exposureSlider.adjustValue(ArducamIMX477Preset.ExposureTime.Default);
brightnessSlider.adjustValue(ObsbotMeet2Preset.Brightness.Default);
contrastSlider.adjustValue(ObsbotMeet2Preset.Contrast.Default);
saturationSlider.adjustValue(ObsbotMeet2Preset.Saturation.Default);
hueSlider.adjustValue(ObsbotMeet2Preset.Hue.Default);
gainSlider.adjustValue(ObsbotMeet2Preset.Gain.Default);
exposureSlider.adjustValue(ObsbotMeet2Preset.ExposureTime.Default);
}
@@ -310,14 +349,32 @@ public class Cameradetail {
* @param liveheight Height used on live view
* @param photowidth Width used on photo capture
* @param photoheight Height used on photo capture
* @param reducedwidth Width used on reduced resolution
* @param reducedheight Height used on reduced resolution
* @param isPotrait if true, set to portrait mode, otherwise landscape
*/
public void SetGrabber(OpenCVFrameGrabber grabber, int livewidth, int liveheight, int photowidth, int photoheight){
public void SetGrabber(OpenCVFrameGrabber grabber, int livewidth, int liveheight, int photowidth, int photoheight, int reducedwidth, int reducedheight, boolean isPotrait){
if (mGrabber!=null) {
StopLiveView();
}
IsPortrait = isPotrait;
if (IsPortrait){
// putar portrait
LiveSize = new Size(liveheight, livewidth);
BestSize = new Size(photoheight, photowidth);
ReducedSize = new Size(reducedheight, reducedwidth);
} else {
LiveSize = new Size(livewidth, liveheight);
PhotoSize = new Size(photowidth, photoheight);
BestSize = new Size(photowidth, photoheight);
ReducedSize = new Size(reducedwidth, reducedheight);
}
mGrabber = grabber;
}
//Exposure and Focus Tricks :
@@ -330,7 +387,7 @@ public class Cameradetail {
*/
public void setAutoExposure(boolean ON){
if (mGrabber!=null){
mGrabber.setOption(Videoio.CAP_PROP_AUTO_EXPOSURE, ON?ArducamIMX477Preset.AutoExposure.On:ArducamIMX477Preset.AutoExposure.Off);
mGrabber.setOption(Videoio.CAP_PROP_AUTO_EXPOSURE, ON?ObsbotMeet2Preset.AutoExposure.On:ObsbotMeet2Preset.AutoExposure.Off);
}
}
@@ -340,7 +397,7 @@ public class Cameradetail {
*/
public boolean getAutoExposure(){
if (mGrabber!=null){
return mGrabber.getOption(Videoio.CAP_PROP_AUTO_EXPOSURE)==ArducamIMX477Preset.AutoExposure.On;
return mGrabber.getOption(Videoio.CAP_PROP_AUTO_EXPOSURE)==ObsbotMeet2Preset.AutoExposure.On;
}
return false;
}
@@ -372,7 +429,7 @@ public class Cameradetail {
*/
public void setAutoFocus(boolean ON){
if (mGrabber!=null){
mGrabber.setOption(Videoio.CAP_PROP_AUTOFOCUS, ON?ArducamIMX477Preset.AutoFocus.On:ArducamIMX477Preset.AutoFocus.Off);
mGrabber.setOption(Videoio.CAP_PROP_AUTOFOCUS, ON?ObsbotMeet2Preset.AutoFocus.On:ObsbotMeet2Preset.AutoFocus.Off);
}
}
@@ -382,20 +439,20 @@ public class Cameradetail {
*/
public boolean getAutoFocus(){
if (mGrabber!=null){
return mGrabber.getOption(Videoio.CAP_PROP_AUTOFOCUS)==ArducamIMX477Preset.AutoFocus.On;
return mGrabber.getOption(Videoio.CAP_PROP_AUTOFOCUS)==ObsbotMeet2Preset.AutoFocus.On;
}
return false;
}
public void setAutoWB(boolean ON){
if (mGrabber!=null){
mGrabber.setOption(Videoio.CAP_PROP_AUTO_WB, ON?ArducamIMX477Preset.AutoWhiteBalance.On:ArducamIMX477Preset.AutoWhiteBalance.Off);
mGrabber.setOption(Videoio.CAP_PROP_AUTO_WB, ON?ObsbotMeet2Preset.AutoWhiteBalance.On:ObsbotMeet2Preset.AutoWhiteBalance.Off);
}
}
public boolean getAutoWB(){
if (mGrabber!=null){
return mGrabber.getOption(Videoio.CAP_PROP_AUTO_WB)==ArducamIMX477Preset.AutoWhiteBalance.On;
return mGrabber.getOption(Videoio.CAP_PROP_AUTO_WB)==ObsbotMeet2Preset.AutoWhiteBalance.On;
}
return false;
}
@@ -499,7 +556,81 @@ public class Cameradetail {
return 0;
}
public boolean PutText(String filename, String text, double fontScale, Scalar textColor, int thickness){
if (ValidString(filename)){
Mat mat = opencv_imgcodecs.imread(filename);
if (PutText(mat, text, fontScale, textColor, thickness)){
return opencv_imgcodecs.imwrite(filename, mat);
}
}
return false;
}
public boolean PutText(UMat Mat, String text, double fontScale, Scalar textColor, int thickness){
if (!Mat.empty()){
if (text!=null && !text.isEmpty()){
//String timestamp = prefix+" "+SomeCodes.GetDateTimeString();
int fontFace = FONT_HERSHEY_SIMPLEX;
//double fontScale = 4.0;
//int thickness = 2;
//Scalar textColor = new Scalar(255, 255, 255, 0); // white color in BGR format
int[] baseline = {0};
Size textSize = getTextSize(text, fontFace, fontScale, thickness, baseline);
// position of the text in the bottom right corner
int textX = Mat.cols() - textSize.width() - 10; // 10 pixels from the right
int textY = Mat.rows() - 10; // 10 pixels from the bottom
opencv_imgproc.putText(Mat, text, new Point(textX, textY), fontFace, fontScale, textColor, thickness, LINE_8, false);
return true;
}
}
return false;
}
public boolean PutText(Mat Mat, String text, double fontScale, Scalar textColor, int thickness){
if (!Mat.empty()){
if (text!=null && !text.isEmpty()){
//String timestamp = prefix+" "+SomeCodes.GetDateTimeString();
int fontFace = FONT_HERSHEY_SIMPLEX;
//double fontScale = 4.0;
//int thickness = 2;
//Scalar textColor = new Scalar(255, 255, 255, 0); // white color in BGR format
int[] baseline = {0};
Size textSize = getTextSize(text, fontFace, fontScale, thickness, baseline);
// position of the text in the bottom right corner
int textX = Mat.cols() - textSize.width() - 10; // 10 pixels from the right
int textY = Mat.rows() - 10; // 10 pixels from the bottom
opencv_imgproc.putText(Mat, text, new Point(textX, textY), fontFace, fontScale, textColor, thickness, LINE_8, false);
return true;
}
}
return false;
}
public String GetFullQualityPhotoPath(String directory, String prefix){
//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();
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();
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();
return Path.of(config.getCompressedCropDirectory(), makeFileName(prefix,".jpg")).toString();
}
/**
* Take Photo from Camera
@@ -507,23 +638,44 @@ public class Cameradetail {
* @param prefix filename prefix
* @return filename path of the saved photo, or null if failed
*/
@SuppressWarnings("BusyWait")
public String TakePhoto(String directory, String prefix) throws InterruptedException {
String result = null;
public PhotoResult TakePhoto(String directory, String prefix) throws InterruptedException {
PhotoResult result = new PhotoResult(cameratitle.getText());
if (!ValidDirectory(directory)) directory = currentDirectory;
if (mGrabber!=null){
while(IsGrabbingLiveView.get()){
Thread.sleep(10);
}
TakingPhoto.set(true);
if (!BestMat.empty()){
Size sz = BestMat.size();
raise_log("TakePhoto got frame with width: " + sz.width() + " and height: " + sz.height());
String filename = Path.of(directory, makeFileName(prefix)).toString();
if (imwrite(filename, BestMat)){
raise_log("TakePhoto success, Photo saved to " + filename);
result = filename;
} else raise_log("TakePhoto failed, Unable to Save Photo");
// save BestMat at quality 9 PNG
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());
String xx = CropBestMat(directory, prefix, BestMatROI);
if (ValidFile(xx)) {
result.setFullcrop(xx);
result.setBestROI(new Rect(BestMatROI.x(), BestMatROI.y(), BestMatROI.width(), BestMatROI.height()));
}
// save ReducedMat at 100% JPEG
String reducedfilename = GetReducedPhotoPath(directory, prefix);
opencv_imgproc.resize(BestMat, 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);
String xy = CropReducedMat(directory, prefix, ReducedMatROI);
if (ValidFile(xy)){
result.setCompressedcrop(xy);
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");
TakingPhoto.set(false);
@@ -531,21 +683,68 @@ public class Cameradetail {
}
//TODO Revisi nama file
private String makeFileName(String prefix){
//make filename with prefix_POSITION_YYYY-MM-DD_HH-MM-SS
public String CropBestMat(String directory, String prefix, Rect ROI){
UMat cloned = new UMat();
BestMat.copyTo(cloned);
if (!cloned.empty()) {
if (ValidROI(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)) {
Logger.info("CropBestMat success, saved as " + filename);
return filename;
} 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;
}
public String CropReducedMat(String directory, String prefix, Rect ROI){
if (!ReducedMat.empty()){
if (ValidROI(ROI)){
if (ROIInsideUMat(ROI,ReducedMat)){
UMat cropped = CropUMat(ReducedMat, ROI);
if (cropped!=null){
String filename = GetReducedCropPhotoPath(directory, prefix);
if (opencv_imgcodecs.imwrite(filename, cropped, paramjpeg)){
Logger.info("CropReducedMat success, saved as ",filename);
return filename;
} 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;
}
@SuppressWarnings("SameParameterValue")
private String makeFileName(String prefix, String extension){
LocalDateTime ldt = LocalDateTime.now();
String timetag = ldt.getYear() + "-" + ldt.getMonthValue() + "-" + ldt.getDayOfMonth() + "_" + ldt.getHour() + "-" + ldt.getMinute() + "-" + ldt.getSecond();
return prefix+" "+timetag+" "+cameratitle.getText() + ".jpg";
return prefix+" "+timetag+" "+cameratitle.getText() + extension;
}
@SuppressWarnings("SameParameterValue")
private String makeReducedFileName(String prefix, String extension){
LocalDateTime ldt = LocalDateTime.now();
String timetag = ldt.getYear() + "-" + ldt.getMonthValue() + "-" + ldt.getDayOfMonth() + "_" + ldt.getHour() + "-" + ldt.getMinute() + "-" + ldt.getSecond();
return prefix+" "+timetag+" "+cameratitle.getText() + "_reduced" + extension;
}
public void StopLiveView(){
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());
@@ -556,6 +755,33 @@ public class Cameradetail {
IsGrabbingLiveView.set(false);
}
public Rect GetFace(UMat mat, boolean isfrontal){
if (!mat.empty()){
Mat originalmat = new Mat();
mat.copyTo(originalmat);
Mat graymat = new Mat();
opencv_imgproc.cvtColor(originalmat,graymat, COLOR_BGR2GRAY); // convert to grayscale
int size = Math.min(graymat.cols(), graymat.rows());
int minsize = (int) (size * 0.4);
int maxsize = (int) (size * 0.9);
System.out.println("GetFace size = "+size+" minsize = "+minsize+" maxsize = "+maxsize);
RectVector faces = isfrontal ? Detectors.DetectFrontalFace(graymat, minsize, maxsize) : Detectors.DetectProfileFace(graymat, minsize, maxsize);
if (faces.size()>0){
Rect result = null;
for(Rect xx : faces.get()){
if (result==null){
result = xx;
} else {
if (xx.area()>result.area()){
result = xx;
}
}
}
return result;
}
} else raise_log("GetFace failed, Mat is empty");
return null;
}
public boolean StartLiveView(LiveCamEvent event, String cameratitle, final boolean use_qr , final boolean use_face) {
this.event = event;
@@ -565,15 +791,22 @@ public class Cameradetail {
if (use_qr) raise_log("QR Reader loaded");
if (use_face) raise_log("Face detector loaded");
// capture with best resolution
setFrameHeight(PhotoSize.height());
setFrameWidth(PhotoSize.width());
if (IsPortrait){
setFrameHeight(BestSize.width());
setFrameWidth(BestSize.height());
} else {
setFrameHeight(BestSize.height());
setFrameWidth(BestSize.width());
}
LiveFPS = 0;
mGrabber.start();
mGrabber.flush();
System.out.println("Camera "+cameratitle+" started");
Capturing.set(true);
// just information
String ss = String.format("Camera Started with resolution %dx%d@%d", PhotoSize.width(), PhotoSize.height(),LiveFPS);
String ss = String.format("Camera Started with resolution %dx%d@%d", BestSize.width(), BestSize.height(),LiveFPS);
Platform.runLater(()->setCameraStatus(ss));
raise_log(ss);
@@ -585,14 +818,37 @@ public class Cameradetail {
protected Image call() {
// repeat until capturing is false
AtomicInteger fps = new AtomicInteger(0);
TimerTask timerTask = new TimerTask() {
// eye state = -1 means unknown, 0 means closed, 1 means open
int eye_state = -1;
boolean waiting_for_second_blink = false;
long last_blink = 0;
TimerTask fpsTask = new TimerTask() {
@Override
public void run() {
LiveFPS = fps.getAndSet(0);
}
};
Timer timer = new java.util.Timer();
timer.scheduleAtFixedRate(timerTask, 1000, 1000);
timer.scheduleAtFixedRate(fpsTask, 1000, 1000);
boolean have_frontal_face;
boolean have_left_45_face;
int _face_width;
int _face_height;
boolean have_palm = false;
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 {
// selama proses pengambilan foto, jangan ambil frame
@@ -602,41 +858,190 @@ public class Cameradetail {
if (!Capturing.get()) return null;
IsGrabbingLiveView.set(true);
Frame frame = mGrabber.grab(); // grab frame
Mat mat = matconverter.convert(frame); // convert to Mat
if (mat.empty()) continue; // kalau gak ada data, continue
int counter = fps.incrementAndGet();
if (counter % 5 != 0) continue; // frame skip to 6 fps
Frame frame;
try{
frame = mGrabber.grab(); // grab frame
} catch (Exception e){
frame = null;
mat.copyTo(BestMat); // copy to BestMat for using OpenCL
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
fps.incrementAndGet();
UMat originalmat = new UMat();
mat.copyTo(originalmat); // copy to BestMat for using OpenCL
// 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 (frame != null) {
if (!BestMat.empty()) {
opencv_imgproc.resize(BestMat, LiveMat, LiveSize); // resize to LiveSize
UMat graymat = new UMat(); // use OpenCL for grayscale
opencv_imgproc.cvtColor(LiveMat,graymat, COLOR_BGR2GRAY); // convert to grayscale
if (use_qr){
String qr = DetectQRFromMat(graymat);
if (qr!=null) {
if (!qr.equals(qrtext)){
if (ValidBarCode(qr)){
qrtext = qr;
raise_log("QR Detected: " + qr);
if (event!=null) event.onDetectedQRCode(qr);
}
if (event!=null) event.onDetectedQRCode(qrtext);
}
}
if (use_face){
RectVector face = DetectFace(graymat);
if (face!=null && face.size()>0){
if (event!=null) event.onFaceDetector(true, PhotoSize.width(), PhotoSize.height());
for(int i=0; i<face.size(); i++){
Rect rect = face.get(i);
rectangle(LiveMat, rect, Scalar.GREEN);
DetectorResult theface = null;
have_frontal_face = false;
have_left_45_face = false;
_face_width = 0;
_face_height = 0;
List<DetectorResult> frontalfaces = HaveFrontalFace(graymat);
if (!frontalfaces.isEmpty()){
for(DetectorResult rect : frontalfaces){
if (rect.haveFace() ){
rect.FaceRectangle(LiveMat);
rect.EyesRectangle(LiveMat);
if (rect.getFaceWidth()>_face_width) _face_width = rect.getFaceWidth();
if (rect.getFaceHeight()>_face_height) _face_height = rect.getFaceHeight();
theface = rect;
have_frontal_face = true;
}
} else if (event!=null) event.onFaceDetector(false, PhotoSize.width(), PhotoSize.height());
}
} else {
// gak punya frontal face
// coba cek punya profile left face 45 gak
List<DetectorResult> Left45Faces = HaveLeft45Face(graymat);
if (!Left45Faces.isEmpty()){
for(DetectorResult rect : Left45Faces){
if (rect.haveFace()){
rect.FaceRectangle(LiveMat);
rect.EyesRectangle(LiveMat);
if (rect.getFaceWidth()>_face_width) _face_width = rect.getFaceWidth();
if (rect.getFaceHeight()>_face_height) _face_height = rect.getFaceHeight();
have_left_45_face = true;
}
}
}
}
if (have_frontal_face){
if (face_counter<5){
face_counter++;
//System.out.println("Frontal Face Counter = "+face_counter+ " from camera "+cameratitle+" eye count = "+theface.getEyesCount());
continue;
}
no_face_counter = 0;
if (event!=null) event.onFrontalFaceDetector(true, _face_width, _face_height);
if (theface.getFace()!=null){
LiveMatROI = new Rect(theface.getFace().x(), theface.getFace().y(), theface.getFace().width(), theface.getFace().height());
//System.out.println("Frontal Face Detected from camera "+cameratitle+" "+RectToString(LiveMatROI));
}
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("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);
if (event!=null) event.onBlink((int)diff);
}
} else {
waiting_for_second_blink = true;
System.out.println("First Blink Detected from camera "+cameratitle);
}
last_blink = now;
}
eye_state = 1;
} 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("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>30){
// kalau tidak ada face selama 30 frame, reset state
// 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);
}
} else no_face_counter++;
}
}
// if (HavePalm(graymat)) {
// if (!have_palm){
// have_fist = false;
// have_palm = true;
// System.out.println("Palm Detected from camera " + cameratitle);
// }
// }
// if (HaveFist(graymat)) {
// if (!have_fist) {
// have_palm = false;
// have_fist = true;
// System.out.println("Fist Detected from camera "+cameratitle);
// }
// }
UMat rgbmat = new UMat(LiveMat.size(), CV_8UC3);
cvtColor(LiveMat, rgbmat, COLOR_BGR2RGB);
@@ -647,7 +1052,9 @@ public class Cameradetail {
updateValue(matToWritableImage(imgmat, imgmat.cols(), imgmat.rows()));
}
} catch (Exception e) {
if (ValidString(e.getMessage())){
raise_log("Unable to Grab Frame, Error: " + e.getMessage());
}
//if (!Capturing.get()) Platform.runLater(this::StopLiveView);
}
}
@@ -674,6 +1081,73 @@ 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, boolean printdebug){
BestMatROI = null;
ReducedMatROI = null;
if (ValidROI(LiveMatROI)){
if (ROIInsideUMat(LiveMatROI, LiveMat)){
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();
int XBest = (int) (LiveMatROI.x()*scaleXBest);
int YBest = (int) (LiveMatROI.y()*scaleYBest);
int WBest = (int) (LiveMatROI.width()*scaleXBest);
int HBest = (int) (LiveMatROI.height()*scaleYBest);
int deltaWBest = (int) (BestSize.width() * scaleX);
int deltaHBest = (int) (BestSize.height() * scaleY);
XBest = XBest - deltaWBest/2;
if (XBest<0) XBest = 0;
YBest = YBest - deltaHBest/2;
if (YBest<0) YBest = 0;
WBest = WBest + deltaWBest;
if (WBest>BestSize.width()) WBest = BestSize.width();
HBest = HBest + deltaHBest;
if (HBest>BestSize.height()) HBest = BestSize.height();
BestMatROI = new Rect(XBest, YBest, WBest, HBest);
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();
int XReduced = (int) (LiveMatROI.x()*scaleXReduced);
int YReduced = (int) (LiveMatROI.y()*scaleYReduced);
int WReduced = (int) (LiveMatROI.width()*scaleXReduced);
int HReduced = (int) (LiveMatROI.height()*scaleYReduced);
int deltaWReduced = (int) (ReducedSize.width() * scaleX);
int deltaHReduced = (int) (ReducedSize.height() * scaleY);
XReduced = XReduced - deltaWReduced/2;
if (XReduced<0) XReduced = 0;
YReduced = YReduced - deltaHReduced/2;
if (YReduced<0) YReduced = 0;
WReduced = WReduced + deltaWReduced;
if (WReduced>ReducedSize.width()) WReduced = ReducedSize.width();
HReduced = HReduced + deltaHReduced;
if (HReduced>ReducedSize.height()) HReduced = ReducedSize.height();
ReducedMatROI = new Rect(XReduced, YReduced, WReduced, HReduced);
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());
}
/**
* Detect QR Code from Mat
* @param graymat Mat in Gray Scale
@@ -697,19 +1171,9 @@ public class Cameradetail {
return null;
}
/**
* Detect Face from Mat
* @param graymat Mat in Gray Scale
* @return RectVector if face detected, otherwise false
*/
private RectVector DetectFace(UMat graymat){
if (faceDetector!=null){
RectVector face = new RectVector();
faceDetector.detectMultiScale(graymat, face);
return face;
}
return null;
}
private double getBrightnessFromGrayMat(Mat graymat){
Scalar mean = mean(graymat);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
package id.co.gtc.erhacam;
import lombok.Getter;
import lombok.Setter;
import org.bytedeco.opencv.opencv_core.Rect;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.bytedeco.opencv.opencv_core.UMat;
import java.util.List;
import static org.bytedeco.opencv.global.opencv_imgproc.rectangle;
@Getter
public class DetectorResult {
private @Setter Rect Face;
private List<Rect> Eyes;
public void AddEye(Rect eye){
if (Eyes == null) Eyes = new java.util.ArrayList<>();
Eyes.add(eye);
}
public void FaceRectangle(UMat mat){
if (haveFace()){
rectangle(mat, Face, Scalar.GREEN);
}
}
public void EyesRectangle(UMat mat){
if (haveEyes()){
for(Rect eye : Eyes){
rectangle(mat, eye, Scalar.BLUE);
}
}
}
public boolean haveFace(){
return Face != null && Face.width() > 0 && Face.height() > 0;
}
public int getFaceWidth(){
if (!haveFace()) return 0;
return Face.width();
}
public int getFaceHeight(){
if (!haveFace()) return 0;
return Face.height();
}
public boolean haveEyes(){
return Eyes != null && !Eyes.isEmpty();
}
public int getEyesCount(){
if (!haveEyes()) return 0;
return Eyes.size();
}
}

View File

@@ -0,0 +1,313 @@
package id.co.gtc.erhacam;
import Config.SomeCodes;
import lombok.NonNull;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import org.tinylog.Logger;
import java.util.ArrayList;
import java.util.List;
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 double scaleFactor = 1.1;
private final static int minNeighbors = 3;
private final static int flags = 0;
private static Size FaceminSize;
private static Size FacemaxSize;
private static final int EyetoFaceRatio = 6;
private static Size EyeminSize;
private static Size EyemaxSize;
public static void LoadAllDetectors(){
LoadFrontalFaceDetector();
LoadEyeDetector();
LoadProfileFaceDetector();
//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{
//
// 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 LoadFrontalFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
if (filename!=null) {
Logger.info("Face Detector file : " + filename);
if (frontalfaceDetector==null) {
try{
frontalfaceDetector = new CascadeClassifier(filename);
Logger.info("FaceDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading FaceDetector : " + e.getMessage());
}
} else Logger.info("FaceDetector already loaded");
} else Logger.error("Unable to extract face detector file");
}
private static void LoadProfileFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml");
if (filename!=null) {
Logger.info("Profile Face Detector file : " + filename);
if (profilefaceDetector==null) {
try{
profilefaceDetector = new CascadeClassifier(filename);
Logger.info("ProfileFaceDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading ProfileFaceDetector : " + e.getMessage());
}
} else Logger.info("ProfileFaceDetector already loaded");
} else Logger.error("Unable to extract profile face detector file");
}
private static void LoadEyeDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_eye.xml");
if (filename!=null) {
Logger.info("Eye Detector file : " + filename);
if (eyeDetector==null) {
try{
eyeDetector = new CascadeClassifier(filename);
Logger.info("EyeDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading EyeDetector : " + e.getMessage());
}
} else Logger.info("EyeDetector already loaded");
} else Logger.error("Unable to extract eye detector file");
}
// 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;
// }
/**
* Detect if there is a frontal face, containing 2 eyes
* @param graymat Mat in Gray Scale
* @return List of Rect if face detected, otherwise empty list
*/
public static @NonNull List<DetectorResult> HaveFrontalFace(UMat graymat){
List<DetectorResult> result = new ArrayList<>();
RectVector faces = DetectFrontalFace(graymat);
if (faces!=null && faces.size()>0){
for(Rect face : faces.get()){
RectVector eyes = DetectEye(graymat);
DetectorResult dr = new DetectorResult();
dr.setFace(face);
if (eyes!=null && eyes.size()>=2){
for(Rect eye : eyes.get()){
if (IsInsideRect(eye, face)) dr.AddEye(eye);
}
}
result.add(dr);
}
}
return result;
}
public static @NonNull List<DetectorResult> HaveLeft45Face(UMat graymat){
List<DetectorResult> result = new ArrayList<>();
RectVector faces = DetectProfileFace(graymat);
if (faces!=null && faces.size()>0){
for(Rect face : faces.get()){
RectVector eyes = DetectEye(graymat);
DetectorResult dr = new DetectorResult();
dr.setFace(face);
if (eyes!=null && eyes.size()>0){
for(Rect eye : eyes.get()){
if (IsInsideRect(eye, face)) dr.AddEye(eye);
}
}
result.add(dr);
}
}
return result;
}
public static void setScaleFactor(double value){
if (scaleFactor!=value) scaleFactor = value;
}
public static void setFaceMinSize(int value){
if (FaceminSize!=null){
if (FaceminSize.width()!=value || FaceminSize.height()!=value) {
FaceminSize = new Size(value, value);
EyeminSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
Logger.info("FaceMinSize changed to : " + FaceminSize.width());
Logger.info("EyeMinSize changed to : " + EyeminSize.width());
}
} else {
FaceminSize = new Size(value, value);
EyeminSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
Logger.info("FaceMinSize created with value : " + FaceminSize.width());
Logger.info("EyeMinSize created with value : " + EyeminSize.width());
}
}
public static void setFaceMaxSize(int value){
if (FacemaxSize!=null){
if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) {
FacemaxSize = new Size(value, value);
EyemaxSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
Logger.info("FaceMaxSize changed to : " + FacemaxSize.width());
Logger.info("EyeMaxSize changed to : " + EyemaxSize.width());
}
} else {
FacemaxSize = new Size(value, value);
EyemaxSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
Logger.info("FaceMaxSize created with value : " + FacemaxSize.width());
Logger.info("EyeMaxSize created with value : " + EyemaxSize.width());
}
}
public static RectVector DetectProfileFace(UMat graymat){
return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
}
public static RectVector DetectFrontalFace(Mat graymat, int minsize, int maxsize){
Size min = new Size(minsize, minsize);
Size max = new Size(maxsize, maxsize);
RectVector rect = new RectVector();
frontalfaceDetector.detectMultiScale(graymat, rect,scaleFactor, minNeighbors, flags, min, max);
return rect;
}
public static RectVector DetectProfileFace(Mat graymat, int minsize, int maxsize){
Size min = new Size(minsize, minsize);
Size max = new Size(maxsize, maxsize);
RectVector rect = new RectVector();
profilefaceDetector.detectMultiScale(graymat, rect,scaleFactor, minNeighbors, flags, min, max);
return rect;
}
/**
* Detect Face from Mat
* @param graymat Mat in Gray Scale
* @return RectVector if face detected, otherwise null
*/
public static RectVector DetectFrontalFace(UMat graymat){
return Detect(graymat, frontalfaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
}
/**
* Detect Eye from Mat
* If Eye detected, it will return RectVector with size is number of eyes detected
* @param graymat Mat in Gray Scale
* @return RectVector if eye detected, otherwise null
*/
public static RectVector DetectEye(UMat graymat){
//return Detect(graymat, eyeDetector, scaleFactor, minNeighbors, flags, EyeminSize, EyemaxSize);
return Detect(graymat, eyeDetector);
}
@SuppressWarnings("unused")
private static RectVector Detect(UMat graymat, CascadeClassifier detector){
if (detector!=null){
if (graymat!=null){
if (!graymat.empty()){
RectVector detected = new RectVector();
detector.detectMultiScale(graymat, detected);
return detected;
}
}
}
return null;
}
@SuppressWarnings("SameParameterValue")
private static RectVector Detect(UMat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){
if (detector!=null){
if (graymat!=null){
if (!graymat.empty()){
if (minSize!=null){
if (maxSize!=null){
RectVector detected = new RectVector();
detector.detectMultiScale(graymat, detected, scaleFactor, minNeighbors, flags, minSize, maxSize);
return detected;
}
}
}
}
}
return null;
}
}

View File

@@ -1,45 +1,97 @@
package id.co.gtc.erhacam;
import Config.SomeCodes;
import SecureDongle.SecureDongle;
import SecureDongle.SecureDongleEvent;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.stage.Screen;
import javafx.stage.Stage;
import org.tinylog.Logger;
import java.io.IOException;
import static Config.SomeCodes.ShowAlert;
import static Config.SomeCodes.config;
public class MainApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
SecureDongle sd = new SecureDongle((short)0x4B30, (short)0xA66C, (short)0x3109, (short)0x37B1);
if (sd.Find()){
if (sd.Open()){
String UserID = Integer.toHexString(sd.ReadUserID()) ;
sd.Close();
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");
stage.setTitle("MultiCam Capture App for ERHA 11032025-006");
stage.setScene(scene);
stage.setResizable(true);
stage.setMaximized(true);
stage.setOnCloseRequest(e->{
sd.StopMonitor();
config.Save();
MainView mainView = fxmlLoader.getController();
mainView.Unload();
Logger.info("Application closed");
});
SomeCodes.LoadQRReader();
SomeCodes.LoadFaceDetector();
Detectors.LoadAllDetectors();
stage.show();
Logger.info("Application started");
sd.setEvent(new SecureDongleEvent() {
@Override
public void onDongleMissing() {
Logger.error("Secure Dongle Missing");
Platform.runLater(()->{
ShowAlert(Alert.AlertType.ERROR, "Secure Dongle Missing", "Secure Dongle Missing", "Secure Dongle Missing");
Platform.exit();
});
}
@Override
public void onDongleError(String function, int errorCode) {
}
});
sd.StartMonitor();
} else {
ShowAlert(Alert.AlertType.ERROR, "Secure Dongle UserID not valid", "Secure Dongle UserID not valid", "Secure Dongle UserID not valid");
Logger.error("Secure Dongle UserID not valid");
Platform.exit();
}
} else {
ShowAlert(Alert.AlertType.ERROR, "Secure Dongle cannot be opened", "Secure Dongle cannot be opened", "Secure Dongle cannot be opened");
Logger.error("Secure Dongle cannot be opened");
Platform.exit();
}
} else {
ShowAlert(Alert.AlertType.ERROR, "Secure Dongle not found", "Secure Dongle not found", "Secure Dongle not found");
Logger.error("Secure Dongle not found");
Platform.exit();
}
}
public static void main(String[] args) {
SomeCodes.ExtractResource("/tinylog.properties");
launch();
}
}

View File

@@ -59,7 +59,7 @@ public class MainView {
@FXML
private void initialize(){
ReviewClick(null);
CaptureClick(null);
}
public void Unload(){
@@ -92,8 +92,8 @@ public class MainView {
currentcontroller = loader.getController();
} catch (Exception e) {
Logger.error("Unable to load " + fxmlfile + ", exception : " + e.getMessage());
Logger.error("Unable to load " ,fxmlfile, ", exception : ", e.getMessage());
}
} else Logger.info("Not loading empty fxml file");
} else Logger.error("loadContent Not loading empty fxml file");
}
}

View File

@@ -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();
}
});

View File

@@ -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,20 +14,9 @@ import org.tinylog.Logger;
import java.io.File;
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<String> CameraLeft90;
@FXML
@@ -49,10 +39,77 @@ public class SettingView {
@FXML
private TextField FTPPath;
@FXML
private TextField PhotoDirectoryPath;
final FileChooser jfc = new FileChooser();
String[] cameranames = null;
@FXML
private TextField cascadeMinSize;
@FXML
private TextField cascadeScaleFactor;
@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();
String scalefactor = cascadeScaleFactor.getText();
String maxsize = cascadeMaxSize.getText();
if (ValidString(minsize)){
if (ValidString(maxsize)){
if (ValidString(scalefactor)){
try{
int min = Integer.parseInt(minsize);
double scale = Double.parseDouble(scalefactor);
int max = Integer.parseInt(maxsize);
if (scale> 1.0){
if (min>0){
if (max>min){
config.setCascadeMaxSize(max);
config.setCascadeMinSize(min);
config.setCascadeScaleFactor(scale);
config.Save();
Detectors.setFaceMaxSize(max);
Detectors.setFaceMinSize(min);
Detectors.setScaleFactor(scale);
ShowAlert(Alert.AlertType.INFORMATION, "Cascade Setting", "Cascade Setting Saved", "Cascade Setting Saved Successfully");
} else show_cascade_alert("Max Size must be greater than Min Size");
} else show_cascade_alert("Min Size must be greater than 0");
} else show_cascade_alert("Scale Factor must be greater than 1.0");
} catch (NumberFormatException e){
show_cascade_alert("Min Size, Scale Factor, and Max Size must be a number");
}
} else show_cascade_alert("Scale Factor must not empty");
} else show_cascade_alert("Max Size must not empty");
} else show_cascade_alert("Min Size must not empty");
}
private void show_cascade_alert(String content){
ShowAlert(Alert.AlertType.ERROR, "Cascade Setting Error", "Cascade Setting Error", content);
}
@FXML
public void initialize(){
FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("Audio File", "wav","mp3");
@@ -70,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();
@@ -108,6 +160,12 @@ public class SettingView {
FTPUser.setText(config.getFTPUser());
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()));
});
}
@@ -115,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());
@@ -198,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");
}
}

View File

@@ -15,11 +15,14 @@ module id.co.gtc.erhacam {
requires org.tinylog.api;
requires java.sql;
requires javafx.graphics;
requires java.net.http;
opens id.co.gtc.erhacam to javafx.fxml;
opens BASS to com.sun.jna;
opens Config to com.google.gson;
opens Database to javafx.base;
opens ErhaAPI to com.google.gson;
exports id.co.gtc.erhacam;
}

View File

@@ -39,6 +39,7 @@ import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicBoolean;
import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.frontalfaceDetector;
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;
@@ -638,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());
@@ -705,12 +706,12 @@ public class Cameradetail_Arducam {
if (use_face){
RectVector face = DetectFace(graymat);
if (face!=null && face.size()>0){
if (event!=null) event.onFaceDetector(true,photoWidth, photoHeight);
if (event!=null) event.onFrontalFaceDetector(true,photoWidth, photoHeight);
for(int i=0; i<face.size(); i++){
val rect = face.get(i);
rectangle(umat, rect, Scalar.GREEN);
}
} else if (event!=null) event.onFaceDetector(false, photoWidth, photoHeight);
} else if (event!=null) event.onFrontalFaceDetector(false, photoWidth, photoHeight);
}
@@ -782,9 +783,9 @@ public class Cameradetail_Arducam {
* @return true if face detected, otherwise false
*/
private RectVector DetectFace(UMat graymat){
if (faceDetector!=null){
if (frontalfaceDetector!=null){
val face = new RectVector();
faceDetector.detectMultiScale(graymat, face);
frontalfaceDetector.detectMultiScale(graymat, face);
return face;
}
return null;

View File

@@ -5,7 +5,7 @@
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="280.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.Cameradetail">
<AnchorPane prefHeight="720.0" prefWidth="360.0" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.Cameradetail">
<children>
<GridPane layoutX="5.0" layoutY="5.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
@@ -46,15 +46,31 @@
<GridPane layoutX="-28.0" layoutY="-29.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints fillWidth="false" minWidth="10.0" percentWidth="20.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" minHeight="10.0" prefHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane GridPane.columnIndex="1">
<AnchorPane fx:id="streamanchor">
<children>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="240.0" prefWidth="140.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<StackPane layoutY="5.0" prefHeight="669.6" prefWidth="350.4" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<ImageView fx:id="camerastream" fitWidth="340.0" pickOnBounds="true" preserveRatio="true" smooth="false" StackPane.alignment="CENTER">
<viewport>
<Rectangle2D height="640.0" width="360.0" />
</viewport>
</ImageView>
</children>
</StackPane>
</children>
<GridPane.margin>
<Insets />
</GridPane.margin>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="240.0" prefWidth="140.0" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label text="Brightness" />
<Slider fx:id="brightnessSlider" min="-100.0">
@@ -101,19 +117,6 @@
</VBox>
</children>
</AnchorPane>
<AnchorPane fx:id="streamanchor">
<children>
<StackPane prefHeight="240.0" prefWidth="351.2" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<ImageView fx:id="camerastream" fitHeight="240.0" pickOnBounds="true">
<image>
<Image url="@gtcbackground.png" />
</image>
</ImageView>
</children>
</StackPane>
</children>
</AnchorPane>
</children>
</GridPane>
</children>

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="280.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.Cameradetail">
<children>
<GridPane layoutX="5.0" layoutY="5.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane minHeight="30.0" GridPane.rowIndex="1">
<children>
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane>
<children>
<Label fx:id="cameratitle" alignment="CENTER" style="-fx-border-color: black;" text="Camera Title" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1">
<children>
<Label fx:id="camerastatus" alignment="CENTER" style="-fx-border-color: black;" text="Camera Status" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<GridPane layoutX="-28.0" layoutY="-29.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints fillWidth="false" minWidth="10.0" percentWidth="20.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane GridPane.columnIndex="1">
<children>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="240.0" prefWidth="140.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label text="Brightness" />
<Slider fx:id="brightnessSlider" min="-100.0">
<VBox.margin>
<Insets />
</VBox.margin>
</Slider>
<Label text="Contrast" />
<Slider fx:id="contrastSlider" layoutX="10.0" layoutY="28.0" min="-100.0">
<VBox.margin>
<Insets />
</VBox.margin>
</Slider>
<Label layoutX="10.0" layoutY="42.0" text="Saturation" />
<Slider fx:id="saturationSlider" layoutX="10.0" layoutY="60.0" min="-100.0">
<VBox.margin>
<Insets />
</VBox.margin>
</Slider>
<Label layoutX="10.0" layoutY="74.0" text="Hue" />
<Slider fx:id="hueSlider" layoutX="10.0" layoutY="92.0" min="-100.0" prefHeight="14.0" prefWidth="63.0">
<VBox.margin>
<Insets />
</VBox.margin>
</Slider>
<Label layoutX="10.0" layoutY="106.0" text="Gain" />
<Slider fx:id="gainSlider" layoutX="10.0" layoutY="124.0" min="-100.0">
<VBox.margin>
<Insets />
</VBox.margin>
</Slider>
<Label layoutX="10.0" layoutY="138.0" text="Exposure" />
<Slider fx:id="exposureSlider" layoutX="10.0" layoutY="156.0" min="-100.0">
<VBox.margin>
<Insets />
</VBox.margin>
</Slider>
<Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#resetClick" text="Reset">
<VBox.margin>
<Insets left="5.0" right="5.0" top="5.0" />
</VBox.margin>
</Button>
</children>
</VBox>
</children>
</AnchorPane>
<AnchorPane fx:id="streamanchor">
<children>
<StackPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<ImageView fx:id="camerastream" fitWidth="240.0" pickOnBounds="true">
<image>
<Image url="@gtcbackground.png" />
</image>
</ImageView>
</children>
</StackPane>
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
</children>
</GridPane>
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</AnchorPane>

View File

@@ -3,108 +3,112 @@
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane fx:id="CaptureViewAnchor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.CaptureView">
<children>
<GridPane layoutX="99.0" layoutY="147.0" style="-fx-grid-lines-visible: true;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<GridPane layoutX="147.0" layoutY="239.0" AnchorPane.bottomAnchor="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane fx:id="cam1" prefHeight="200.0" prefWidth="200.0" />
<AnchorPane fx:id="cam3" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1" />
<AnchorPane fx:id="cam5" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2" />
<AnchorPane fx:id="cam2" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" />
<AnchorPane fx:id="cam4" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<AnchorPane fx:id="controlpane" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
<AnchorPane fx:id="cam3" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" />
<AnchorPane fx:id="cam4" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3" />
<AnchorPane fx:id="cam5" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="4" />
</children>
</GridPane>
<GridPane layoutX="99.0" layoutY="147.0" style="-fx-grid-lines-visible: true;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="10.0" prefHeight="175.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<VBox layoutX="108.0" layoutY="14.0" prefHeight="256.0" prefWidth="512.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<AnchorPane fx:id="controlpane" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<padding>
<Insets top="5.0" />
</padding></AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<GridPane>
<GridPane layoutX="68.0" layoutY="14.0" prefHeight="175.2" prefWidth="512.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Label layoutX="28.0" layoutY="8.0" prefHeight="30.0" prefWidth="154.0" text="Save Directory" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
<Label layoutX="31.0" layoutY="6.0" prefHeight="30.0" prefWidth="154.0" text="Nomor Barcode" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="14.0" />
</font>
</Label>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<Label layoutX="31.0" layoutY="6.0" prefHeight="30.0" prefWidth="154.0" text="Patient ID" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
<Label layoutX="63.0" layoutY="6.0" prefHeight="30.4" prefWidth="154.4" text="Medical Record ID" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="14.0" />
</font>
</Label>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
<children>
<Label layoutX="63.0" layoutY="5.0" prefHeight="30.4" prefWidth="154.4" text="Patient Name" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="14.0" />
</font>
</Label>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextArea fx:id="directorypath" editable="false" layoutX="14.0" layoutY="-86.0" prefHeight="114.0" prefWidth="358.0" promptText="Directory to save Photos" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
<TextArea fx:id="barcodeData" editable="false" layoutX="-21.0" layoutY="-85.0" prefHeight="115.0" prefWidth="358.0" promptText="barcode read result" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="18.0" />
</font>
</TextArea>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextArea fx:id="prefixfile" layoutX="-21.0" layoutY="-85.0" prefHeight="115.0" prefWidth="358.0" promptText="Some identification for easy find" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
<TextArea fx:id="medicalRecordID" editable="false" layoutX="14.0" layoutY="-84.0" prefHeight="116.0" prefWidth="358.4" promptText="medical record ID" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="18.0" />
</font>
</TextArea>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<TextArea fx:id="PatientName" editable="false" layoutX="-21.0" layoutY="-84.0" prefHeight="116.0" prefWidth="358.4" promptText="patient name" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0">
<font>
<Font size="18.0" />
</font>
</TextArea>
</children>
</AnchorPane>
</children>
<VBox.margin>
<Insets bottom="5.0" top="5.0" />
</VBox.margin>
</GridPane>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="42.0" layoutY="14.0" mnemonicParsing="false" onAction="#ChangeDirectory" prefHeight="70.0" prefWidth="171.0" text="Change Directory" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<Button layoutX="72.0" layoutY="35.0" mnemonicParsing="false" onAction="#AutoFocus" prefHeight="70.0" prefWidth="171.0" text="Auto Focus" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<Button fx:id="btnTakePhoto" layoutX="59.0" layoutY="23.0" mnemonicParsing="false" onAction="#TakePhotos" prefHeight="70.0" prefWidth="170.0" text="Take Photos" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</children>
<VBox.margin>
<Insets top="5.0" />
</VBox.margin>
</GridPane>
<ScrollPane prefHeight="200.0" prefWidth="200.0">
<content>
<AnchorPane fx:id="progressanchor" />
</content>
<VBox.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</VBox.margin>
</ScrollPane>
</children>
</VBox>
</children>
<padding>
<Insets top="5.0" />
</padding></AnchorPane>
</children></AnchorPane>
</children>
</GridPane>
</children>

View File

@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="CaptureViewAnchor" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.CaptureView">
<children>
<GridPane layoutX="99.0" layoutY="147.0" style="-fx-grid-lines-visible: true;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane fx:id="cam1" prefHeight="200.0" prefWidth="200.0" />
<AnchorPane fx:id="cam3" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1" />
<AnchorPane fx:id="cam5" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2" />
<AnchorPane fx:id="cam2" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" />
<AnchorPane fx:id="cam4" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<AnchorPane fx:id="controlpane" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<VBox layoutX="108.0" layoutY="14.0" prefHeight="256.0" prefWidth="512.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="30.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Label layoutX="28.0" layoutY="8.0" prefHeight="30.0" prefWidth="154.0" text="Save Directory" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<Label layoutX="31.0" layoutY="6.0" prefHeight="30.0" prefWidth="154.0" text="Patient ID" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextArea fx:id="directorypath" editable="false" layoutX="14.0" layoutY="-86.0" prefHeight="114.0" prefWidth="358.0" promptText="Directory to save Photos" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextArea fx:id="prefixfile" layoutX="-21.0" layoutY="-85.0" prefHeight="115.0" prefWidth="358.0" promptText="Some identification for easy find" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
</children>
</AnchorPane>
</children>
<VBox.margin>
<Insets bottom="5.0" top="5.0" />
</VBox.margin>
</GridPane>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Button layoutX="42.0" layoutY="14.0" mnemonicParsing="false" onAction="#ChangeDirectory" prefHeight="70.0" prefWidth="171.0" text="Change Directory" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<Button fx:id="btnAutoFocus" layoutX="72.0" layoutY="35.0" mnemonicParsing="false" onAction="#AutoFocus" prefHeight="70.0" prefWidth="171.0" text="Auto Focus" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<Button fx:id="btnTakePhoto" layoutX="59.0" layoutY="23.0" mnemonicParsing="false" onAction="#TakePhotos" prefHeight="70.0" prefWidth="170.0" text="Take Photos" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</children>
<VBox.margin>
<Insets top="5.0" />
</VBox.margin>
</GridPane>
<ScrollPane prefHeight="200.0" prefWidth="200.0">
<content>
<AnchorPane fx:id="progressanchor" />
</content>
<VBox.margin>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</VBox.margin>
</ScrollPane>
</children>
</VBox>
</children>
<padding>
<Insets top="5.0" />
</padding></AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>

View File

@@ -19,16 +19,19 @@
<RowConstraints minHeight="36.0" prefHeight="36.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Button fx:id="ReviewButton" layoutX="99.0" layoutY="2.0" mnemonicParsing="false" onAction="#ReviewClick" text="Review" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<Button fx:id="CaptureButton" layoutX="103.0" layoutY="6.0" mnemonicParsing="false" onAction="#CaptureClick" text="Capture" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<Button fx:id="SettingButton" layoutX="64.0" layoutY="2.0" mnemonicParsing="false" onAction="#SettingClick" text="Setting" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="0.0" />

View File

@@ -1,16 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefWidth="1024.0" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.SettingView">
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefWidth="1024.0" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.SettingView">
<children>
<GridPane layoutX="70.0" layoutY="78.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
@@ -22,122 +15,31 @@
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="200.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="200.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="40.0" prefHeight="40.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Label alignment="CENTER" layoutX="44.0" layoutY="7.0" text="Audio Setting" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
<children>
<Label alignment="CENTER" layoutX="195.0" layoutY="7.0" text="Camera Setting" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="4">
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
<children>
<Label alignment="CENTER" layoutX="239.0" layoutY="8.0" text="FTP Setting" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<GridPane layoutX="149.0" layoutY="-29.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="40.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Label layoutX="62.0" layoutY="8.0" text="Phase 1 File" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<Label layoutX="49.0" layoutY="8.0" prefHeight="30.4" prefWidth="180.0" text="Phase 2 File" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
<children>
<Label layoutX="62.0" layoutY="5.0" prefHeight="30.4" prefWidth="180.0" text="Phase 3 File" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="3">
<children>
<Label layoutX="22.0" layoutY="6.0" prefHeight="30.4" prefWidth="180.0" text="Phase 4 File" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="4">
<children>
<Label layoutX="34.0" layoutY="6.0" prefHeight="30.4" prefWidth="180.0" text="Phase 5 File" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<TextField fx:id="AudioPhase1" layoutX="14.0" layoutY="4.0" prefHeight="30.4" prefWidth="329.6" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextField fx:id="AudioPhase2" layoutX="-32.0" layoutY="1.0" prefHeight="30.4" prefWidth="329.6" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<TextField fx:id="AudioPhase3" layoutY="2.0" prefHeight="30.4" prefWidth="329.6" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="3">
<children>
<TextField fx:id="AudioPhase4" layoutX="51.0" layoutY="2.0" prefHeight="30.4" prefWidth="329.6" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="4">
<children>
<TextField fx:id="AudioPhase5" layoutX="14.0" layoutY="2.0" prefHeight="30.4" prefWidth="329.6" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
<children>
<Button layoutX="14.0" layoutY="3.0" mnemonicParsing="false" onAction="#BrowseAudioPhase1" prefHeight="30.4" prefWidth="90.4" text="Browse" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="1">
<children>
<Button layoutX="19.0" layoutY="4.0" mnemonicParsing="false" onAction="#BrowseAudioPhase2" prefHeight="30.4" prefWidth="90.4" text="Browse" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="2">
<children>
<Button layoutX="19.0" layoutY="4.0" mnemonicParsing="false" onAction="#BrowseAudioPhase3" prefHeight="30.4" prefWidth="90.4" text="Browse" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="3">
<children>
<Button layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onAction="#BrowseAudioPhase4" prefHeight="40.0" prefWidth="90.4" text="Browse" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="4">
<children>
<Button layoutY="4.0" mnemonicParsing="false" onAction="#BrowseAudioPhase5" prefHeight="30.4" prefWidth="90.4" text="Browse" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="3">
<children>
<GridPane layoutX="166.0" layoutY="-29.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
@@ -228,9 +130,88 @@
</AnchorPane>
</children>
</GridPane>
<GridPane GridPane.columnIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane GridPane.rowIndex="2">
<children>
<Button mnemonicParsing="false" onAction="#CascadeSettingApply" prefHeight="40.0" prefWidth="410.4" text="Apply" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="5">
<AnchorPane>
<children>
<Label alignment="CENTER" prefHeight="30.4" prefWidth="410.4" text="Detection Parameters" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="1">
<children>
<ScrollPane layoutY="0.7999992370605469" prefHeight="200.8" prefWidth="410.4" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="200.0" minWidth="0.0" prefWidth="350.0">
<children>
<GridPane prefHeight="200.0" prefWidth="300.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane>
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Scale Factor" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="1">
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Minimum Size" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="2">
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Maximum Size" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1">
<children>
<TextField fx:id="cascadeScaleFactor" alignment="CENTER" prefHeight="40.0" prefWidth="175.2" text="1.2" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextField fx:id="cascadeMinSize" alignment="CENTER" prefHeight="40.0" prefWidth="175.2" text="200" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<TextField fx:id="cascadeMaxSize" alignment="CENTER" prefHeight="40.0" prefWidth="175.2" text="400" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
</content>
</ScrollPane>
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</GridPane>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="3">
<children>
<HBox prefHeight="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
@@ -308,6 +289,42 @@
</HBox>
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="4">
<children>
<Label alignment="CENTER" layoutX="287.0" prefHeight="30.4" prefWidth="1024.0" text="Directory Setting" textAlignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="5">
<children>
<GridPane layoutX="75.0" layoutY="-31.0" prefHeight="40.0" prefWidth="1024.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane>
<children>
<Label text="Photo Save" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1">
<children>
<TextField fx:id="PhotoDirectoryPath" editable="false" prefHeight="40.0" prefWidth="870.4" promptText="directory to save photo" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="2">
<children>
<Button mnemonicParsing="false" onAction="#ChangePhotoDirectoryPath" prefHeight="40.0" prefWidth="102.4" text="Browse" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>
</children>
</GridPane>
</children>

BIN
tahan_posisi.wav Normal file

Binary file not shown.

BIN
tiga.wav

Binary file not shown.

View File

@@ -1,4 +1,5 @@
writer = rolling file
#writer = rolling file
writer = console
writer.file = logs/{date:yyyy-MM-dd}.log
writer.format = {date:yyyy-MM-dd HH:mm:ss} {level}: {class}.{method}() {message}
//writer.format = {date:yyyy-MM-dd HH:mm:ss} {level}: {message}

BIN
upload_berhasil.wav Normal file

Binary file not shown.

BIN
upload_gagal.wav Normal file

Binary file not shown.

BIN
voices/countdown321.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
voices/kesalahan_server.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
voices/posisikan_wajah.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
voices/scan_barcode.wav Normal file

Binary file not shown.

BIN
voices/tahan_posisi.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
voices/upload_berhasil.wav Normal file

Binary file not shown.

BIN
voices/upload_gagal.wav Normal file

Binary file not shown.