Compare commits
28 Commits
ca3fa0ed08
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 668a477289 | |||
| 8f85e3fccd | |||
| f7c74304f5 | |||
| d566e4bc4f | |||
| 49ac4353b3 | |||
| 3539fb7d65 | |||
| e4d2bfa00e | |||
| 0728ae3ca2 | |||
| 957d642f5d | |||
| 3d02641479 | |||
| d0fe8123e9 | |||
| 9e69714ae1 | |||
| 9effe8a7a9 | |||
|
|
1fcd905b07 | ||
|
|
ee0a82aa32 | ||
|
|
d1a6dd9f98 | ||
|
|
e47e1252fb | ||
|
|
ef94f87d8a | ||
| 5f2093a572 | |||
| 2dfd149990 | |||
|
|
4e3381edc4 | ||
|
|
1d617a0559 | ||
| bc6821a33e | |||
|
|
d2e7d1155d | ||
|
|
52360dde5f | ||
|
|
02a213f17b | ||
| 2cf206b306 | |||
| 257eb50640 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,6 +2,9 @@ target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
logs/
|
||||
out/
|
||||
hs_err*.log
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
|
||||
4
.idea/inspectionProfiles/Project_Default.xml
generated
4
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,9 +1,10 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<inspection_tool class="AutoCloseableResource" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.lang.foreign.Arena,ofAuto,java.lang.foreign.Arena,global,java.util.concurrent.Executors,newFixedThreadPool" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ClassEscapesItsScope" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="CommentedOutCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="minLines" value="3" />
|
||||
</inspection_tool>
|
||||
@@ -15,5 +16,6 @@
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SqlNoDataSourceInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="UnusedReturnValue" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
</profile>
|
||||
</component>
|
||||
BIN
IU photoboth-01.jpg
Normal file
BIN
IU photoboth-01.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
IU photoboth-02.jpg
Normal file
BIN
IU photoboth-02.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 253 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 452 KiB After Width: | Height: | Size: 1.1 MiB |
BIN
banners/IU photoboth-01_old.jpg
Normal file
BIN
banners/IU photoboth-01_old.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 452 KiB |
@@ -1,9 +1,29 @@
|
||||
#Thu Apr 10 16:17:13 ICT 2025
|
||||
AudioPhase1=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase1.mp3
|
||||
AudioPhase2=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase2.mp3
|
||||
AudioPhase3=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase3.mp3
|
||||
AudioPhase4=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase4.mp3
|
||||
AudioPhase5=C\:\\Users\\Erha\\IdeaProjects\\ErhaCam\\audio\\phase5.mp3
|
||||
#Wed Aug 27 11:07:31 WIB 2025
|
||||
AudioPhase1=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase1.mp3
|
||||
AudioPhase2=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase2.mp3
|
||||
AudioPhase3=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase3.mp3
|
||||
AudioPhase4=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase4.mp3
|
||||
AudioPhase5=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase5.mp3
|
||||
Cam1BottomCrop=20.0
|
||||
Cam1LeftCrop=8.0
|
||||
Cam1RightCrop=8.0
|
||||
Cam1TopCrop=10.0
|
||||
Cam2BottomCrop=20.0
|
||||
Cam2LeftCrop=8.0
|
||||
Cam2RightCrop=8.0
|
||||
Cam2TopCrop=10.0
|
||||
Cam3BottomCrop=20.0
|
||||
Cam3LeftCrop=8.0
|
||||
Cam3RightCrop=8.0
|
||||
Cam3TopCrop=10.0
|
||||
Cam4BottomCrop=20.0
|
||||
Cam4LeftCrop=8.0
|
||||
Cam4RightCrop=8.0
|
||||
Cam4TopCrop=10.0
|
||||
Cam5BottomCrop=20.0
|
||||
Cam5LeftCrop=8.0
|
||||
Cam5RightCrop=8.0
|
||||
Cam5TopCrop=10.0
|
||||
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}
|
||||
@@ -19,11 +39,12 @@ FTPPass=password
|
||||
FTPPath=/
|
||||
FTPPort=21
|
||||
FTPUser=user
|
||||
FlipCamera=true
|
||||
MirrorCamera=true
|
||||
PhotoDirectory=C\:\\Users\\Erha\\Desktop\\ErhaCapture
|
||||
SharpnessThreshold=1000.0
|
||||
cascadeMaxSize=500
|
||||
FlipCamera=false
|
||||
MirrorCamera=false
|
||||
PhotoDirectory=D\:\\Capture
|
||||
Production=false
|
||||
SharpnessThreshold=850.0
|
||||
cascadeMaxSize=360
|
||||
cascadeMinNeighbors=3
|
||||
cascadeMinSize=250
|
||||
cascadeScaleFactor=1.1
|
||||
cascadeScaleFactor=1.05
|
||||
|
||||
BIN
database.db
BIN
database.db
Binary file not shown.
12213
haarcascade_eye.xml
Normal file
12213
haarcascade_eye.xml
Normal file
File diff suppressed because it is too large
Load Diff
24350
haarcascade_frontalface_alt.xml
Normal file
24350
haarcascade_frontalface_alt.xml
Normal file
File diff suppressed because it is too large
Load Diff
29690
haarcascade_profileface.xml
Normal file
29690
haarcascade_profileface.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
hubungistafkami.wav
Normal file
BIN
hubungistafkami.wav
Normal file
Binary file not shown.
@@ -47,6 +47,16 @@
|
||||
2024-10-21 15:28:21 INFO: GetAll success, result count: 36
|
||||
2024-10-21 15:28:25 INFO: Not loading empty fxml file
|
||||
2024-10-21 15:28:25 INFO: Application closed
|
||||
2025-03-24 16:03:28 INFO: Config.ConfigFile.<init>() Current working directory in Java : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam
|
||||
2025-03-24 16:03:28 INFO: Config.ConfigFile.Load() Load config file at C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\config.properties
|
||||
2025-03-24 16:03:28 INFO: Config.ConfigFile.Load() Config Loaded
|
||||
2025-03-24 16:03:29 INFO: Config.SomeCodes.LoadQRReader() QRReader loaded
|
||||
2025-03-24 16:03:30 INFO: Config.SomeCodes.LoadFaceDetector() FaceDetector loaded
|
||||
2025-03-24 16:03:30 INFO: id.co.gtc.erhacam.MainApplication.start() Application started
|
||||
2025-03-24 16:03:31 INFO: Database.Sqlite.CreateDatabase() Database created successfully
|
||||
2025-03-24 16:03:31 INFO: Database.Sqlite.GetAll() GetAll success, result count: 55
|
||||
2025-03-24 16:04:08 INFO: id.co.gtc.erhacam.MainView.loadContent() Not loading empty fxml file
|
||||
2025-03-24 16:04:08 INFO: id.co.gtc.erhacam.MainApplication.lambda$start$0() Application closed
|
||||
2025-03-21 14:43:56 INFO: Config.ConfigFile.<init>() Current working directory in Java : C:\Users\Erha\IdeaProjects\ErhaCam
|
||||
2025-03-21 14:43:56 INFO: Config.ConfigFile.Load() Load config file at C:\Users\Erha\IdeaProjects\ErhaCam\config.properties
|
||||
2025-03-21 14:43:56 INFO: id.co.gtc.erhacam.Detectors.setFaceMaxSize() FaceMaxSize created with value : 500
|
||||
@@ -426,3 +436,59 @@
|
||||
2025-03-21 16:08:12 ERROR: id.co.gtc.erhacam.CaptureView.call() Record associated with barcode
|
||||
2025-03-21 16:08:33 INFO: id.co.gtc.erhacam.CaptureView.onPlaybackStarted() Audio Positikan Muka Started
|
||||
2025-03-21 16:08:40 INFO: id.co.gtc.erhacam.CaptureView.onPlaybackFinished() Audio Positikan Muka Finished
|
||||
2025-03-24 16:05:16 INFO: Config.ConfigFile.<init>() Current working directory in Java : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam
|
||||
2025-03-24 16:05:16 INFO: Config.ConfigFile.Load() Load config file at C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\config.properties
|
||||
2025-03-24 16:05:16 INFO: id.co.gtc.erhacam.Detectors.setFaceMaxSize() FaceMaxSize created with value : 500
|
||||
2025-03-24 16:05:16 INFO: id.co.gtc.erhacam.Detectors.setFaceMaxSize() EyeMaxSize created with value : 83
|
||||
2025-03-24 16:05:16 INFO: id.co.gtc.erhacam.Detectors.setFaceMinSize() FaceMinSize created with value : 250
|
||||
2025-03-24 16:05:16 INFO: id.co.gtc.erhacam.Detectors.setFaceMinSize() EyeMinSize created with value : 41
|
||||
2025-03-24 16:05:16 INFO: Config.ConfigFile.Load() Config Loaded
|
||||
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\FullQuality, Msg : C:\Users\Erha
|
||||
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\FullQualityCrop, Msg : C:\Users\Erha
|
||||
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\Compressed, Msg : C:\Users\Erha
|
||||
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\CompressedCrop, Msg : C:\Users\Erha
|
||||
2025-03-24 16:05:16 INFO: Config.SomeCodes.MakeDirectory() Error creating directory: C:\Users\Erha\Desktop\ErhaCapture\thumbs, Msg : C:\Users\Erha
|
||||
2025-03-24 16:05:17 INFO: id.co.gtc.erhacam.MainApplication.start() Secure Dongle UserID valid
|
||||
2025-03-24 16:05:18 INFO: id.co.gtc.erhacam.CaptureView.initialize() Audio Player : Inited
|
||||
2025-03-24 16:05:19 INFO: Config.SomeCodes.LoadQRReader() QRReader loaded
|
||||
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadFrontalFaceDetector() Face Detector file : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\haarcascade_frontalface_alt.xml
|
||||
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadFrontalFaceDetector() FaceDetector loaded
|
||||
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadEyeDetector() Eye Detector file : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\haarcascade_eye.xml
|
||||
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadEyeDetector() EyeDetector loaded
|
||||
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadProfileFaceDetector() Profile Face Detector file : C:\Users\rdkar\OneDrive\Documents\IntelliJ Project\ErhaCam\haarcascade_profileface.xml
|
||||
2025-03-24 16:05:19 INFO: id.co.gtc.erhacam.Detectors.LoadProfileFaceDetector() ProfileFaceDetector loaded
|
||||
2025-03-24 16:05:20 INFO: id.co.gtc.erhacam.MainApplication.start() Application started
|
||||
2025-03-24 16:05:20 INFO: id.co.gtc.erhacam.CaptureView.lambda$initialize$13() Left90 Index: 1
|
||||
2025-03-24 16:05:20 INFO: SecureDongle.SecureDongle.lambda$StartMonitor$0() Start Monitoring UserID=14022025
|
||||
2025-03-24 16:05:20 INFO: id.co.gtc.erhacam.CaptureView.onLog() [01] : QR Reader loaded
|
||||
2025-03-24 16:05:20 INFO: id.co.gtc.erhacam.CaptureView.onLog() [01] : Face detector loaded
|
||||
2025-03-24 16:05:24 INFO: id.co.gtc.erhacam.SettingView.initialize() Found 3 Cameras
|
||||
2025-03-24 16:05:24 INFO: id.co.gtc.erhacam.SettingView.lambda$initialize$2() adding camera : ACER QHD User Facing to camera list
|
||||
2025-03-24 16:05:24 INFO: id.co.gtc.erhacam.SettingView.lambda$initialize$2() adding camera : OBSBOT Meet 2 StreamCamera to camera list
|
||||
2025-03-24 16:05:24 INFO: id.co.gtc.erhacam.SettingView.lambda$initialize$2() adding camera : OBSBOT Virtual Camera to camera list
|
||||
2025-03-24 16:05:31 INFO: Database.Sqlite.CreateDatabase() Database created successfully
|
||||
2025-03-24 16:05:31 INFO: Database.Sqlite.GetAll() GetAll success, result count: 90
|
||||
2025-03-24 16:05:32 INFO: id.co.gtc.erhacam.CaptureView.initialize() Audio Player : Inited
|
||||
2025-03-24 16:05:32 INFO: id.co.gtc.erhacam.CaptureView.lambda$initialize$13() Left90 Index: 1
|
||||
2025-03-24 16:05:32 INFO: id.co.gtc.erhacam.CaptureView.onLog() [01] : QR Reader loaded
|
||||
2025-03-24 16:05:32 INFO: id.co.gtc.erhacam.CaptureView.onLog() [01] : Face detector loaded
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\IdeaProjects\ErhaCam\thumbs\240980 2025-3-24_12-38-45 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_13-50-34 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_14-41-17 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_14-49-11 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_14-50-41 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_15-12-36 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_15-26-18 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_15-36-34 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:05:33 ERROR: id.co.gtc.erhacam.PhotoRow.loadImage() Error loading image: C:\Users\Erha\Desktop\ErhaCapture\thumbs\240980 2025-3-24_15-37-53 01.png, Msg : OpenCV(4.9.0) D:\a\javacpp-presets\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.9.0\modules\imgproc\src\resize.cpp:4152: error: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
|
||||
|
||||
2025-03-24 16:07:13 ERROR: id.co.gtc.erhacam.MainView.loadContent() loadContent Not loading empty fxml file
|
||||
2025-03-24 16:07:13 INFO: id.co.gtc.erhacam.MainApplication.lambda$start$0() Application closed
|
||||
|
||||
Binary file not shown.
BIN
pengambilan_berhasil_tunggu_lobby.wav
Normal file
BIN
pengambilan_berhasil_tunggu_lobby.wav
Normal file
Binary file not shown.
@@ -3,6 +3,8 @@ package BASS;
|
||||
import lombok.Getter;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static Config.SomeCodes.Wait;
|
||||
|
||||
|
||||
@@ -121,7 +123,7 @@ public class AudioPlayer {
|
||||
iscontinue = false;
|
||||
break;
|
||||
default : {
|
||||
Wait(100);
|
||||
Wait(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,6 +131,7 @@ public class AudioPlayer {
|
||||
currentFile = "";
|
||||
currentFileHandle = 0;
|
||||
});
|
||||
pl.setName("PlaybackStatus Monitor Thread");
|
||||
pl.setDaemon(true);
|
||||
pl.start();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package Config;
|
||||
|
||||
import id.co.gtc.erhacam.Detectors;
|
||||
import id.co.gtc.erhacam.MainApplication;
|
||||
import lombok.Getter;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
@@ -47,9 +47,35 @@ public class ConfigFile {
|
||||
|
||||
private @Getter boolean MirrorCamera = false;
|
||||
private @Getter boolean FlipCamera = false;
|
||||
private @Getter boolean isProduction = true;
|
||||
|
||||
private @Getter double SharpnessThreshold;
|
||||
|
||||
private @Getter final double topcropmax = 30.0;
|
||||
private @Getter final double bottomcropmax = 30.0;
|
||||
private @Getter final double leftcropmax = 30.0;
|
||||
private @Getter final double rightcropmax = 30.0;
|
||||
private @Getter double Cam1TopCrop = 10.0;
|
||||
private @Getter double Cam1BottomCrop = 20.0;
|
||||
private @Getter double Cam1LeftCrop = 8.0;
|
||||
private @Getter double Cam1RightCrop = 8.0;
|
||||
private @Getter double Cam2TopCrop = 10.0;
|
||||
private @Getter double Cam2BottomCrop = 20.0;
|
||||
private @Getter double Cam2LeftCrop = 8.0;
|
||||
private @Getter double Cam2RightCrop = 8.0;
|
||||
private @Getter double Cam3TopCrop = 10.0;
|
||||
private @Getter double Cam3BottomCrop = 20.0;
|
||||
private @Getter double Cam3LeftCrop = 8.0;
|
||||
private @Getter double Cam3RightCrop = 8.0;
|
||||
private @Getter double Cam4TopCrop = 10.0;
|
||||
private @Getter double Cam4BottomCrop = 20.0;
|
||||
private @Getter double Cam4LeftCrop = 8.0;
|
||||
private @Getter double Cam4RightCrop = 8.0;
|
||||
private @Getter double Cam5TopCrop = 10.0;
|
||||
private @Getter double Cam5BottomCrop = 20.0;
|
||||
private @Getter double Cam5LeftCrop = 10.0;
|
||||
private @Getter double Cam5RightCrop = 10.0;
|
||||
|
||||
private boolean needsave = false;
|
||||
|
||||
public ConfigFile(){
|
||||
@@ -58,6 +84,195 @@ public class ConfigFile {
|
||||
Load();
|
||||
}
|
||||
|
||||
public void setAPI(boolean isProduction){
|
||||
if (this.isProduction != isProduction){
|
||||
this.isProduction = isProduction;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCam1TopCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam1TopCrop && v <= topcropmax && v >= 0.0){
|
||||
Cam1TopCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCam1BottomCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam1BottomCrop && v <= bottomcropmax && v >= 0.0){
|
||||
Cam1BottomCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam1LeftCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam1LeftCrop && v <= leftcropmax && v >= 0.0){
|
||||
Cam1LeftCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam1RightCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam1RightCrop && v <= rightcropmax && v >= 0.0){
|
||||
Cam1RightCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam2TopCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam2TopCrop && v <= topcropmax && v >= 0.0){
|
||||
Cam2TopCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam2BottomCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam2BottomCrop && v <= bottomcropmax && v >= 0.0){
|
||||
Cam2BottomCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam2LeftCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam2LeftCrop && v <= leftcropmax && v >= 0.0){
|
||||
Cam2LeftCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam2RightCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam2RightCrop && v <= rightcropmax && v >= 0.0){
|
||||
Cam2RightCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam3TopCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam3TopCrop && v <= topcropmax && v >= 0.0){
|
||||
Cam3TopCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam3BottomCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam3BottomCrop && v <= bottomcropmax && v >= 0.0){
|
||||
Cam3BottomCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam3LeftCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam3LeftCrop && v <= leftcropmax && v >= 0.0){
|
||||
Cam3LeftCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam3RightCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam3RightCrop && v <= rightcropmax && v >= 0.0){
|
||||
Cam3RightCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam4TopCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam4TopCrop && v <= topcropmax && v >= 0.0){
|
||||
Cam4TopCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam4BottomCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam4BottomCrop && v <= bottomcropmax && v >= 0.0){
|
||||
Cam4BottomCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam4LeftCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam4LeftCrop && v <= leftcropmax && v >= 0.0){
|
||||
Cam4LeftCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam4RightCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam4RightCrop && v <= rightcropmax && v >= 0.0){
|
||||
Cam4RightCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam5TopCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam5TopCrop && v <= topcropmax && v >= 0.0){
|
||||
Cam5TopCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam5BottomCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam5BottomCrop && v <= bottomcropmax && v >= 0.0){
|
||||
Cam5BottomCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam5LeftCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam5LeftCrop && v <= leftcropmax && v >= 0.0){
|
||||
Cam5LeftCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setCam5RightCrop(String value){
|
||||
if (ValidDouble(value)){
|
||||
double v = toDouble(value);
|
||||
if (v != Cam5RightCrop && v <= rightcropmax && v >= 0.0){
|
||||
Cam5RightCrop = v;
|
||||
needsave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setMirrorCamera(boolean value){
|
||||
if (MirrorCamera != value){
|
||||
MirrorCamera = value;
|
||||
@@ -583,6 +798,7 @@ public class ConfigFile {
|
||||
if (prop.getProperty("MirrorCamera") == null) allcorrect = false;
|
||||
if (prop.getProperty("FlipCamera") == null) allcorrect = false;
|
||||
if (prop.getProperty("SharpnessThreshold") == null) allcorrect = false;
|
||||
if (prop.getProperty("Production") == null) allcorrect = false;
|
||||
|
||||
|
||||
if (prop.getProperty(CameraConfigEnum.CameraConfigLeft90.toString()) == null) allcorrect = false;
|
||||
@@ -596,6 +812,28 @@ public class ConfigFile {
|
||||
if (prop.getProperty("cascadeMinSize") == null) allcorrect = false;
|
||||
if (prop.getProperty("cascadeMaxSize") == null) allcorrect = false;
|
||||
|
||||
if (prop.getProperty("Cam1TopCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam1BottomCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam1LeftCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam1RightCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam2TopCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam2BottomCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam2LeftCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam2RightCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam3TopCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam3BottomCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam3LeftCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam3RightCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam4TopCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam4BottomCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam4LeftCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam4RightCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam5TopCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam5BottomCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam5LeftCrop") == null) allcorrect = false;
|
||||
if (prop.getProperty("Cam5RightCrop") == null) allcorrect = false;
|
||||
|
||||
|
||||
if (allcorrect){
|
||||
AudioPhase1 = prop.getProperty("AudioPhase1");
|
||||
AudioPhase2 = prop.getProperty("AudioPhase2");
|
||||
@@ -622,20 +860,55 @@ 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"));
|
||||
cascadeScaleFactor = cascadetoDouble(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);
|
||||
if (MainApplication.detectorsList!=null){
|
||||
MainApplication.detectorsList.forEach((i, d) -> {
|
||||
if (d != null) {
|
||||
System.out.println("Setting face detection parameters for detector: " + i);
|
||||
d.setFaceMaxSize(cascadeMaxSize);
|
||||
d.setFaceMinSize(cascadeMinSize);
|
||||
d.setScaleFactor(cascadeScaleFactor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Detectors.setFaceMaxSize(cascadeMaxSize);
|
||||
// Detectors.setFaceMinSize(cascadeMinSize);
|
||||
// Detectors.setScaleFactor(cascadeScaleFactor);
|
||||
|
||||
MirrorCamera = toBoolean(prop.getProperty("MirrorCamera"));
|
||||
FlipCamera = toBoolean(prop.getProperty("FlipCamera"));
|
||||
isProduction = toBoolean(prop.getProperty("Production"));
|
||||
|
||||
SharpnessThreshold = toDouble(prop.getProperty("SharpnessThreshold"));
|
||||
|
||||
Cam1TopCrop = toDouble(prop.getProperty("Cam1TopCrop"));
|
||||
Cam1BottomCrop = toDouble(prop.getProperty("Cam1BottomCrop"));
|
||||
Cam1LeftCrop = toDouble(prop.getProperty("Cam1LeftCrop"));
|
||||
Cam1RightCrop = toDouble(prop.getProperty("Cam1RightCrop"));
|
||||
Cam2TopCrop = toDouble(prop.getProperty("Cam2TopCrop"));
|
||||
Cam2BottomCrop = toDouble(prop.getProperty("Cam2BottomCrop"));
|
||||
Cam2LeftCrop = toDouble(prop.getProperty("Cam2LeftCrop"));
|
||||
Cam2RightCrop = toDouble(prop.getProperty("Cam2RightCrop"));
|
||||
Cam3TopCrop = toDouble(prop.getProperty("Cam3TopCrop"));
|
||||
Cam3BottomCrop = toDouble(prop.getProperty("Cam3BottomCrop"));
|
||||
Cam3LeftCrop = toDouble(prop.getProperty("Cam3LeftCrop"));
|
||||
Cam3RightCrop = toDouble(prop.getProperty("Cam3RightCrop"));
|
||||
Cam4TopCrop = toDouble(prop.getProperty("Cam4TopCrop"));
|
||||
Cam4BottomCrop = toDouble(prop.getProperty("Cam4BottomCrop"));
|
||||
Cam4LeftCrop = toDouble(prop.getProperty("Cam4LeftCrop"));
|
||||
Cam4RightCrop = toDouble(prop.getProperty("Cam4RightCrop"));
|
||||
Cam5TopCrop = toDouble(prop.getProperty("Cam5TopCrop"));
|
||||
Cam5BottomCrop = toDouble(prop.getProperty("Cam5BottomCrop"));
|
||||
Cam5LeftCrop = toDouble(prop.getProperty("Cam5LeftCrop"));
|
||||
Cam5RightCrop = toDouble(prop.getProperty("Cam5RightCrop"));
|
||||
|
||||
|
||||
Logger.info("Config Loaded");
|
||||
MakeDirectories();
|
||||
return;
|
||||
@@ -651,7 +924,7 @@ public class ConfigFile {
|
||||
CreateDefault();
|
||||
}
|
||||
|
||||
private double toDouble(String cascadeScaleFactor) {
|
||||
private double cascadetoDouble(String cascadeScaleFactor) {
|
||||
try{
|
||||
return Double.parseDouble(cascadeScaleFactor);
|
||||
} catch (Exception e){
|
||||
@@ -659,6 +932,14 @@ public class ConfigFile {
|
||||
}
|
||||
}
|
||||
|
||||
private double toDouble(String value) {
|
||||
try{
|
||||
return Double.parseDouble(value);
|
||||
} catch (Exception e){
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateDefault(){
|
||||
AudioPhase1 = Path.of(currentDirectory, "audio", "phase1.mp3").toString();
|
||||
AudioPhase2 = Path.of(currentDirectory, "audio", "phase2.mp3").toString();
|
||||
@@ -675,22 +956,56 @@ public class ConfigFile {
|
||||
FTPUser = "user";
|
||||
FTPPass = "password";
|
||||
FTPPath = "/";
|
||||
PhotoDirectory = currentDirectory;
|
||||
PhotoDirectory = "D:\\Capture";
|
||||
SetDefaultCameraConfig(ConfigLeft90);
|
||||
SetDefaultCameraConfig(ConfigLeft45);
|
||||
SetDefaultCameraConfig(ConfigCenter);
|
||||
SetDefaultCameraConfig(ConfigRight45);
|
||||
SetDefaultCameraConfig(ConfigRight90);
|
||||
cascadeScaleFactor = 1.1;
|
||||
cascadeScaleFactor = 1.05;
|
||||
cascadeMinNeighbors = 3;
|
||||
cascadeMinSize = 250;
|
||||
cascadeMaxSize = 500;
|
||||
Detectors.setFaceMaxSize(cascadeMaxSize);
|
||||
Detectors.setFaceMinSize(cascadeMinSize);
|
||||
Detectors.setScaleFactor(cascadeScaleFactor);
|
||||
cascadeMaxSize = 360;
|
||||
if (MainApplication.detectorsList!= null) MainApplication.detectorsList.forEach((i, d) -> {
|
||||
if (d != null) {
|
||||
d.setFaceMaxSize(cascadeMaxSize);
|
||||
d.setFaceMinSize(cascadeMinSize);
|
||||
d.setScaleFactor(cascadeScaleFactor);
|
||||
}
|
||||
});
|
||||
// Detectors.setFaceMaxSize(cascadeMaxSize);
|
||||
// Detectors.setFaceMinSize(cascadeMinSize);
|
||||
// Detectors.setScaleFactor(cascadeScaleFactor);
|
||||
MirrorCamera = false;
|
||||
FlipCamera = false;
|
||||
SharpnessThreshold = 300.0;
|
||||
isProduction = true;
|
||||
SharpnessThreshold = 850.0;
|
||||
|
||||
Cam1TopCrop = 10.0;
|
||||
Cam1BottomCrop = 20.0;
|
||||
Cam1LeftCrop = 8.0;
|
||||
Cam1RightCrop = 8.0;
|
||||
|
||||
Cam2TopCrop = 10.0;
|
||||
Cam2BottomCrop = 20.0;
|
||||
Cam2LeftCrop = 8.0;
|
||||
Cam2RightCrop = 8.0;
|
||||
|
||||
Cam3TopCrop = 10.0;
|
||||
Cam3BottomCrop = 20.0;
|
||||
Cam3LeftCrop = 8.0;
|
||||
Cam3RightCrop = 8.0;
|
||||
|
||||
Cam4TopCrop = 10.0;
|
||||
Cam4BottomCrop = 20.0;
|
||||
Cam4LeftCrop = 8.0;
|
||||
Cam4RightCrop = 8.0;
|
||||
|
||||
Cam5TopCrop = 10.0;
|
||||
Cam5BottomCrop = 20.0;
|
||||
Cam5LeftCrop = 8.0;
|
||||
Cam5RightCrop = 8.0;
|
||||
|
||||
Logger.info("Default Config Created");
|
||||
needsave = true;
|
||||
Save();
|
||||
@@ -749,8 +1064,31 @@ public class ConfigFile {
|
||||
|
||||
prop.setProperty("MirrorCamera", String.valueOf(MirrorCamera));
|
||||
prop.setProperty("FlipCamera", String.valueOf(FlipCamera));
|
||||
prop.setProperty("Production", String.valueOf(isProduction));
|
||||
prop.setProperty("SharpnessThreshold", String.valueOf(SharpnessThreshold));
|
||||
|
||||
prop.setProperty("Cam1TopCrop", String.valueOf(Cam1TopCrop));
|
||||
prop.setProperty("Cam1BottomCrop", String.valueOf(Cam1BottomCrop));
|
||||
prop.setProperty("Cam1LeftCrop", String.valueOf(Cam1LeftCrop));
|
||||
prop.setProperty("Cam1RightCrop", String.valueOf(Cam1RightCrop));
|
||||
prop.setProperty("Cam2TopCrop", String.valueOf(Cam2TopCrop));
|
||||
prop.setProperty("Cam2BottomCrop", String.valueOf(Cam2BottomCrop));
|
||||
prop.setProperty("Cam2LeftCrop", String.valueOf(Cam2LeftCrop));
|
||||
prop.setProperty("Cam2RightCrop", String.valueOf(Cam2RightCrop));
|
||||
prop.setProperty("Cam3TopCrop", String.valueOf(Cam3TopCrop));
|
||||
prop.setProperty("Cam3BottomCrop", String.valueOf(Cam3BottomCrop));
|
||||
prop.setProperty("Cam3LeftCrop", String.valueOf(Cam3LeftCrop));
|
||||
prop.setProperty("Cam3RightCrop", String.valueOf(Cam3RightCrop));
|
||||
prop.setProperty("Cam4TopCrop", String.valueOf(Cam4TopCrop));
|
||||
prop.setProperty("Cam4BottomCrop", String.valueOf(Cam4BottomCrop));
|
||||
prop.setProperty("Cam4LeftCrop", String.valueOf(Cam4LeftCrop));
|
||||
prop.setProperty("Cam4RightCrop", String.valueOf(Cam4RightCrop));
|
||||
prop.setProperty("Cam5TopCrop", String.valueOf(Cam5TopCrop));
|
||||
prop.setProperty("Cam5BottomCrop", String.valueOf(Cam5BottomCrop));
|
||||
prop.setProperty("Cam5LeftCrop", String.valueOf(Cam5LeftCrop));
|
||||
prop.setProperty("Cam5RightCrop", String.valueOf(Cam5RightCrop));
|
||||
|
||||
|
||||
try{
|
||||
prop.store(new FileOutputStream(Path.of(currentDirectory, "config.properties").toString()), null);
|
||||
Logger.info("Config Saved");
|
||||
|
||||
@@ -12,6 +12,8 @@ import javafx.scene.control.TextField;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.PixelFormat;
|
||||
import javafx.scene.image.WritableImage;
|
||||
import javafx.stage.Stage;
|
||||
import lombok.NonNull;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.bytedeco.javacv.Java2DFrameConverter;
|
||||
import org.bytedeco.javacv.OpenCVFrameConverter;
|
||||
@@ -34,10 +36,15 @@ import java.net.InetAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.bytedeco.opencv.global.opencv_core.CV_64F;
|
||||
|
||||
@@ -105,6 +112,7 @@ public class SomeCodes {
|
||||
Mat resized = new Mat();
|
||||
opencv_imgproc.resize(mat, resized, new org.bytedeco.opencv.opencv_core.Size(width, height));
|
||||
BufferedImage img = converter.convert(matconverter.convert(resized));
|
||||
resized.release();
|
||||
return SwingFXUtils.toFXImage(img, null);
|
||||
}
|
||||
return null;
|
||||
@@ -142,6 +150,19 @@ public class SomeCodes {
|
||||
}
|
||||
}
|
||||
|
||||
public static void WaitAsync(long millis, String threadname, Consumer<Void> success){
|
||||
Thread thread = new Thread(()->{
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (Exception ignored){ }
|
||||
if (success != null) success.accept(null);
|
||||
});
|
||||
thread.setName(threadname);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make thumbfile from source jpg file
|
||||
* @param sourcejpg source jpg file
|
||||
@@ -163,6 +184,7 @@ public class SomeCodes {
|
||||
Mat resized = new Mat();
|
||||
opencv_imgproc.resize(source, resized, thumbsize);
|
||||
opencv_imgcodecs.imwrite(thumbfile, resized);
|
||||
resized.release();
|
||||
return thumbfile;
|
||||
}
|
||||
}
|
||||
@@ -180,6 +202,74 @@ public class SomeCodes {
|
||||
return x.format(dtf);
|
||||
}
|
||||
|
||||
public static LocalDateTime StringToLocalDateTime(String x){
|
||||
if (ValidString(x)){
|
||||
try{
|
||||
return LocalDateTime.parse(x, dtf);
|
||||
} catch (Exception e){
|
||||
Logger.error("Error parsing date: "+x+", Msg : "+e.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static LocalDateTime GetCreationTime(Path p){
|
||||
try{
|
||||
BasicFileAttributes attr = Files.readAttributes(p, BasicFileAttributes.class);
|
||||
FileTime ft = attr.creationTime();
|
||||
return LocalDateTime.ofInstant(ft.toInstant(), java.time.ZoneId.systemDefault());
|
||||
} catch (Exception e){
|
||||
Logger.error("Error getting creation time: "+p+", Msg : "+e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static @NonNull Path[] GetFilesInDirectory(String path) {
|
||||
if (ValidDirectory(path)) {
|
||||
try{
|
||||
return Files.list(Path.of(path))
|
||||
.filter(Files::isRegularFile)
|
||||
.toArray(Path[]::new);
|
||||
} catch (Exception ignored){}
|
||||
}
|
||||
return new Path[0];
|
||||
}
|
||||
|
||||
|
||||
public static boolean Delete(String... path){
|
||||
if (path!=null && path.length>0){
|
||||
Boolean[] result = new Boolean[path.length];
|
||||
for(int i=0; i<path.length; i++){
|
||||
try{
|
||||
result[i] = Files.deleteIfExists(Path.of(path[i]));
|
||||
if (result[i]) Logger.info("Delete: "+path[i]);
|
||||
} catch (Exception e){
|
||||
result[i] = false;
|
||||
Logger.error("Error deleting file: "+path[i]+", Msg : "+e.getMessage());
|
||||
}
|
||||
}
|
||||
return Arrays.stream(result).allMatch(x->x);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean Delete(Path... path){
|
||||
if (path!=null && path.length>0){
|
||||
Boolean[] result = new Boolean[path.length];
|
||||
for(int i=0; i<path.length; i++){
|
||||
try{
|
||||
result[i] = Files.deleteIfExists(path[i]);
|
||||
if (result[i]) Logger.info("Delete: "+path[i]);
|
||||
} catch (Exception e){
|
||||
result[i] = false;
|
||||
Logger.error("Error deleting file: "+path[i]+", Msg : "+e.getMessage());
|
||||
}
|
||||
}
|
||||
return Arrays.stream(result).allMatch(x->x);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract resource file to current directory
|
||||
* @param filename resource file name
|
||||
@@ -555,7 +645,7 @@ public class SomeCodes {
|
||||
* 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
|
||||
* @return true if same, false if different
|
||||
*/
|
||||
public static boolean IsSameROI(Rect ROI1, Rect ROI2){
|
||||
if (ValidROI(ROI1) && ValidROI(ROI2)){
|
||||
@@ -690,7 +780,7 @@ public class SomeCodes {
|
||||
public static double CalculateSharpness(String filename){
|
||||
if (ValidFile(filename)){
|
||||
try(Mat mat = opencv_imgcodecs.imread(filename)){
|
||||
return CalculateSharpness(new UMat(mat));
|
||||
return CalculateSharpness(mat);
|
||||
} catch (Exception e){
|
||||
Logger.error("Error calculating sharpness: "+filename+", Msg : "+e.getMessage());
|
||||
}
|
||||
@@ -728,23 +818,23 @@ public class SomeCodes {
|
||||
* @param mat image in UMat format, expected in gray scale
|
||||
* @return sharpness value
|
||||
*/
|
||||
public static double CalculateSharpness(UMat mat){
|
||||
public static double CalculateSharpness(Mat mat){
|
||||
|
||||
if (mat!=null && !mat.empty()){
|
||||
if (mat.channels()!=1){
|
||||
UMat grey = new UMat();
|
||||
Mat grey = new Mat();
|
||||
opencv_imgproc.cvtColor(mat, grey, opencv_imgproc.COLOR_BGR2GRAY);
|
||||
mat = grey;
|
||||
}
|
||||
|
||||
opencv_imgproc.equalizeHist(mat, mat);
|
||||
|
||||
UMat laplacian = new UMat();
|
||||
Mat laplacian = new Mat();
|
||||
|
||||
opencv_imgproc.Laplacian(mat, laplacian, CV_64F);
|
||||
|
||||
UMat mean = new UMat(1,1, CV_64F);
|
||||
UMat stddev = new UMat(1,1, CV_64F);
|
||||
Mat mean = new Mat(1,1, CV_64F);
|
||||
Mat stddev = new Mat(1,1, CV_64F);
|
||||
|
||||
opencv_core.meanStdDev(laplacian, mean, stddev);
|
||||
|
||||
@@ -752,13 +842,14 @@ public class SomeCodes {
|
||||
stddev.copyTo(_std);
|
||||
|
||||
double value = _std.createIndexer().getDouble(0,0);
|
||||
|
||||
_std.release();
|
||||
laplacian.release();
|
||||
return Math.pow(value,2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static boolean IsBlurred(UMat mat, double threshold){
|
||||
public static boolean IsBlurred(Mat mat, double threshold){
|
||||
return CalculateSharpness(mat)<threshold;
|
||||
}
|
||||
|
||||
@@ -790,4 +881,30 @@ public class SomeCodes {
|
||||
mat.data().get(data);
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close Stage if not null
|
||||
* and wait until closed
|
||||
* @param obj Stage object to close
|
||||
*/
|
||||
public static void closeStage(Stage obj) throws InterruptedException {
|
||||
if (obj != null) {
|
||||
if (Platform.isFxApplicationThread()) {
|
||||
// Already on FX thread, just close directly
|
||||
obj.close();
|
||||
} else {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
Platform.runLater(() -> {
|
||||
try {
|
||||
obj.close();
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
// Wait for runLater task to finish
|
||||
latch.await();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
125
src/main/java/Database/PhotoCleaner.java
Normal file
125
src/main/java/Database/PhotoCleaner.java
Normal file
@@ -0,0 +1,125 @@
|
||||
package Database;
|
||||
|
||||
import Config.SomeCodes;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* PhotoCleaner class
|
||||
* Responsible for deleting photos older than a certain number of days
|
||||
*/
|
||||
public class PhotoCleaner {
|
||||
private final int days;
|
||||
private final boolean[] started;
|
||||
|
||||
/**
|
||||
* PhotoCleaner constructor
|
||||
* @param days how many days old photos to delete
|
||||
*/
|
||||
public PhotoCleaner(int days){
|
||||
this.days = days;
|
||||
this.started = new boolean[]{false};
|
||||
}
|
||||
|
||||
/**
|
||||
* Start PhotoCleaner Thread
|
||||
*/
|
||||
@SuppressWarnings("BusyWait")
|
||||
public void Start(){
|
||||
Thread thread = new Thread(() -> {
|
||||
started[0] = true;
|
||||
while (started[0]) {
|
||||
try {
|
||||
System.out.println("Rechecking Database for older photos...");
|
||||
// Delete photos older than the specified number of days
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
// delete from database
|
||||
Thread sqldelete = new Thread(()->{
|
||||
Sqlite sql = new Sqlite();
|
||||
PhotoReviewClass[] prcs = sql.GetAll();
|
||||
for (PhotoReviewClass prc : prcs) {
|
||||
if (!started[0]) break;
|
||||
if (prc != null && prc.getDateTime() != null) {
|
||||
LocalDateTime ldt = SomeCodes.StringToLocalDateTime(prc.getDateTime());
|
||||
if (ldt!=null){
|
||||
if (ldt.isBefore(now.minusDays(days))) {
|
||||
SomeCodes.Delete(prc.fullres());
|
||||
SomeCodes.Delete(prc.cropped());
|
||||
SomeCodes.Delete(prc.compressed());
|
||||
SomeCodes.Delete(prc.compressedcrop());
|
||||
SomeCodes.Delete(prc.thumbnails());
|
||||
sql.Delete(prc);
|
||||
Logger.info("Deleted PhotoReviewClass: " + prc.getDateTime() + " " + prc.getPrefix());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
RunThread(sqldelete, "DeleteFromDatabase");
|
||||
|
||||
// delete from disk
|
||||
Thread deletefullres = new Thread(new DiskDeleter(SomeCodes.config.getFullQualityDirectory()));
|
||||
RunThread(deletefullres, "DeleteFullRes");
|
||||
Thread deletefullrescrop = new Thread(new DiskDeleter(SomeCodes.config.getFullQualityCropDirectory()));
|
||||
RunThread(deletefullrescrop, "DeleteFullResCrop");
|
||||
Thread deletecompressed = new Thread(new DiskDeleter(SomeCodes.config.getCompressedDirectory()));
|
||||
RunThread(deletecompressed, "DeleteCompressed");
|
||||
Thread deletecompressedcrop = new Thread(new DiskDeleter(SomeCodes.config.getCompressedCropDirectory()));
|
||||
RunThread(deletecompressedcrop, "DeleteCompressedCrop");
|
||||
Thread deletethumbnails = new Thread(new DiskDeleter(SomeCodes.config.getThumbsDirectory()));
|
||||
RunThread(deletethumbnails, "DeleteThumbnails");
|
||||
|
||||
|
||||
// Sleep for 1 hour
|
||||
Thread.sleep(60 * 60 * 1000);
|
||||
} catch (Exception e) {
|
||||
Logger.error("Error in PhotoCleaner Thread: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
System.out.println("PhotoCleaner stopped");
|
||||
});
|
||||
thread.setName("PhotoCleaner Thread");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void RunThread(Thread thread, String name){
|
||||
thread.setName(name);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
class DiskDeleter implements Runnable{
|
||||
private final String path;
|
||||
private final LocalDateTime now ;
|
||||
public DiskDeleter(String path){
|
||||
this.path = path;
|
||||
this.now = LocalDateTime.now();
|
||||
}
|
||||
public void run(){
|
||||
Path[] ppp = SomeCodes.GetFilesInDirectory(path);
|
||||
if (ppp != null){
|
||||
for(Path p : ppp){
|
||||
if (!started[0]) break;
|
||||
LocalDateTime ldt = SomeCodes.GetCreationTime(p);
|
||||
if (ldt != null) {
|
||||
if (ldt.isBefore(now.minusDays(days))) {
|
||||
SomeCodes.Delete(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop PhotoCleaner Thread
|
||||
*/
|
||||
public void Stop(){
|
||||
started[0] = false;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package Database;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static Config.SomeCodes.MakeArray;
|
||||
|
||||
@Data
|
||||
|
||||
@@ -40,13 +40,32 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete PhotoReviewClass object from database
|
||||
* @param pr PhotoReviewClass objects
|
||||
*/
|
||||
public void Delete(PhotoReviewClass... pr){
|
||||
if (pr!=null && pr.length>0){
|
||||
try{
|
||||
Connection conn = GetConnection();
|
||||
if (conn != null){
|
||||
for (PhotoReviewClass photo : pr) {
|
||||
PreparedStatement stmt = conn.prepareStatement("DELETE FROM photos WHERE id = ?");
|
||||
stmt.setInt(1, photo.getId());
|
||||
stmt.execute();
|
||||
}
|
||||
conn.close();
|
||||
Logger.info("Data deleted successfully");
|
||||
} else Logger.info("Delete failed, connection is null");
|
||||
} catch (Exception e){
|
||||
Logger.error("Error deleting data: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all PhotoReviewClass object from database
|
||||
@@ -108,14 +127,6 @@ 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()));
|
||||
stmt.setString(2, ValidString(prefix)?prefix:"");
|
||||
|
||||
10
src/main/java/ErhaAPI/BarcodeHttpResult.java
Normal file
10
src/main/java/ErhaAPI/BarcodeHttpResult.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package ErhaAPI;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BarcodeHttpResult {
|
||||
private int statusCode;
|
||||
private String body;
|
||||
private BarcodeResult result;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package ErhaAPI;
|
||||
|
||||
|
||||
public class BarcodeResullt {
|
||||
public class BarcodeResult {
|
||||
public int currentPage;
|
||||
public int limit;
|
||||
public int totalPages;
|
||||
@@ -3,15 +3,19 @@ package ErhaAPI;
|
||||
import Config.SomeCodes;
|
||||
import com.google.gson.Gson;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.URI;
|
||||
import java.net.UnknownHostException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.net.http.HttpTimeoutException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Base64;
|
||||
import java.util.UUID;
|
||||
@@ -26,7 +30,7 @@ public class ErhaAPI {
|
||||
|
||||
|
||||
private String auth;
|
||||
private final String API_URL;
|
||||
private String API_URL="";
|
||||
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
@@ -35,11 +39,25 @@ public class ErhaAPI {
|
||||
* @param isProduction if true will use Production URL, if false will use Staging URL
|
||||
*/
|
||||
public ErhaAPI(boolean isProduction){
|
||||
setProduction(isProduction);
|
||||
}
|
||||
|
||||
public void setProduction(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;
|
||||
if (isProduction){
|
||||
if (!API_URL.equals(API_URL_PROD)){
|
||||
API_URL = API_URL_PROD;
|
||||
update_auth();
|
||||
}
|
||||
} else {
|
||||
if (!API_URL.equals(API_URL_STAGING)){
|
||||
API_URL = API_URL_STAGING;
|
||||
update_auth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set API Username
|
||||
* @param API_USERNAME API Username
|
||||
@@ -68,14 +86,16 @@ public class ErhaAPI {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate Barcode data
|
||||
* @param Barcode Barcode to verify
|
||||
* @return BarcodeResullt object if success, or null if failed
|
||||
* @return BarcodeHttpResult object
|
||||
*/
|
||||
public BarcodeResullt Validate_Barcode(String Barcode, boolean printdebug){
|
||||
public @NonNull BarcodeHttpResult Validate_Barcode(String Barcode, boolean printdebug){
|
||||
BarcodeHttpResult bhr = new BarcodeHttpResult();
|
||||
if (ValidBarCode(Barcode)){
|
||||
|
||||
System.out.println("Checking Barcode : " + Barcode +" on "+(config.isProduction()?"Production":"Staging")+" API " );
|
||||
try (HttpClient client = HttpClient.newHttpClient()) {
|
||||
int medical_record_detail_id = toInt(Barcode);
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
@@ -84,6 +104,11 @@ public class ErhaAPI {
|
||||
.GET()
|
||||
.build();
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
|
||||
bhr.setStatusCode(response.statusCode());
|
||||
bhr.setBody(response.body());
|
||||
|
||||
if (response.statusCode()==200){
|
||||
String body = response.body();
|
||||
if (printdebug){
|
||||
@@ -91,22 +116,36 @@ public class ErhaAPI {
|
||||
System.out.println("Validate_Barcode HTTP body : ");
|
||||
System.out.println(body);
|
||||
}
|
||||
return gson.fromJson(body, BarcodeResullt.class);
|
||||
BarcodeResult brr = gson.fromJson(body, BarcodeResult.class);
|
||||
bhr.setResult(brr);
|
||||
} 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());
|
||||
} catch (UnknownHostException e) {
|
||||
// no internet or no DNS
|
||||
Logger.error("Validate_Barcode UnknownHostException, Msg : " , e.getMessage());
|
||||
bhr.setStatusCode(0);
|
||||
bhr.setBody("No internet connection or DNS error");
|
||||
} catch (ConnectException e) {
|
||||
// connection refused
|
||||
Logger.error("Validate_Barcode ConnectException , Msg : " , e.getMessage());
|
||||
bhr.setStatusCode(-1);
|
||||
bhr.setBody("Connection refused");
|
||||
} catch( HttpTimeoutException e){
|
||||
// timeout
|
||||
Logger.error("Validate_Barcode HttpTimeoutException, Msg : " , e.getMessage());
|
||||
bhr.setStatusCode(408);
|
||||
bhr.setBody("Http Request timeout");
|
||||
} catch (IOException | InterruptedException e) {
|
||||
// generic network error
|
||||
Logger.error("Validate_Barcode IOException/InterruptedException, Msg : " , e.getMessage());
|
||||
bhr.setStatusCode(-2);
|
||||
bhr.setBody("Network error: " + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
return bhr;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,9 +155,10 @@ public class ErhaAPI {
|
||||
* Upload File
|
||||
* @param patientID Patient ID
|
||||
* @param filename File to upload
|
||||
* @return null if failed, or response body if success
|
||||
* @return UploadHttpResult object
|
||||
*/
|
||||
public UploadResult Upload_File(String patientID, String filename, boolean printdebug) {
|
||||
public @NonNull UploadHttpResult Upload_File(String patientID, String filename, boolean printdebug) {
|
||||
UploadHttpResult uhr = new UploadHttpResult();
|
||||
if (ValidMedicalRecordId(patientID)){
|
||||
int medical_record_detail_id = toInt(patientID);
|
||||
if (ValidFile(filename)){
|
||||
@@ -151,7 +191,7 @@ public class ErhaAPI {
|
||||
endBoundary.getBytes()
|
||||
);
|
||||
|
||||
|
||||
System.out.println("Uploading file : " + filename + " to " + (config.isProduction()?"Production":"Staging")+" API ");
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI(API_URL + "/photobooth/photobooth"))
|
||||
.header("Authorization", "Basic " + auth)
|
||||
@@ -162,6 +202,8 @@ public class ErhaAPI {
|
||||
// Send request
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
uhr.setStatusCode(response.statusCode());
|
||||
uhr.setBody(response.body());
|
||||
if (printdebug){
|
||||
System.out.println("Upload_File status code : " + response.statusCode());
|
||||
System.out.println("Upload_File HTTP body : ");
|
||||
@@ -170,21 +212,20 @@ public class ErhaAPI {
|
||||
|
||||
|
||||
if (response.statusCode()==200){
|
||||
return gson.fromJson(response.body(), UploadResult.class);
|
||||
UploadResult ur = gson.fromJson(response.body(), UploadResult.class);
|
||||
uhr.setResult(ur);
|
||||
|
||||
} 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;
|
||||
return uhr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
10
src/main/java/ErhaAPI/UploadHttpResult.java
Normal file
10
src/main/java/ErhaAPI/UploadHttpResult.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package ErhaAPI;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UploadHttpResult {
|
||||
int statusCode;
|
||||
String body;
|
||||
UploadResult result;
|
||||
}
|
||||
@@ -76,7 +76,6 @@ public class SecureDongle {
|
||||
|
||||
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);
|
||||
@@ -135,10 +134,9 @@ public class SecureDongle {
|
||||
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;
|
||||
}
|
||||
@@ -160,12 +158,11 @@ public class SecureDongle {
|
||||
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];
|
||||
}
|
||||
@@ -181,14 +178,13 @@ public class SecureDongle {
|
||||
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;
|
||||
}
|
||||
@@ -205,11 +201,10 @@ public class SecureDongle {
|
||||
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;
|
||||
}
|
||||
@@ -224,10 +219,9 @@ public class SecureDongle {
|
||||
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;
|
||||
}
|
||||
@@ -268,6 +262,7 @@ public class SecureDongle {
|
||||
} else System.out.println("Canceled Monitoring, UserID not found");
|
||||
|
||||
});
|
||||
tx.setName("SecureDongle Monitor Thread");
|
||||
tx.setDaemon(true);
|
||||
tx.start();
|
||||
}
|
||||
|
||||
@@ -5,24 +5,23 @@ import javafx.animation.PauseTransition;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.application.Platform;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.stage.*;
|
||||
import javafx.util.Duration;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static Config.SomeCodes.*;
|
||||
@@ -44,9 +43,9 @@ public class AutoCloseAlert {
|
||||
|
||||
public static void init(){
|
||||
String f_01 = ExtractResource("/IU photoboth-01.jpg");
|
||||
System.out.println("Banner 01 extracted as file: "+f_01);
|
||||
//System.out.println("Banner 01 extracted as file: "+f_01);
|
||||
String f_02 = ExtractResource("/IU photoboth-02.jpg");
|
||||
System.out.println("Banner 02 extracted as file: "+f_02);
|
||||
//System.out.println("Banner 02 extracted as file: "+f_02);
|
||||
banner_01 = LoadImage(f_01);
|
||||
if (banner_01!=null) System.out.println("Banner 01 loaded"); else System.out.println("Banner 01 not loaded");
|
||||
banner_02 = LoadImage(f_02);
|
||||
@@ -82,8 +81,16 @@ public class AutoCloseAlert {
|
||||
* Close the current alert if it is shown
|
||||
*/
|
||||
public static void close(){
|
||||
Optional.ofNullable(currentAlertStage).ifPresent(Stage::close);
|
||||
if (currentAlertStage!=null){
|
||||
try {
|
||||
closeStage(currentAlertStage);
|
||||
} catch (InterruptedException e) {
|
||||
Logger.error("Error closing alert stage: " + e.getMessage());
|
||||
}
|
||||
currentAlertStage = null;
|
||||
}
|
||||
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
@@ -186,7 +193,12 @@ public class AutoCloseAlert {
|
||||
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(0), event -> alertStage.show()));
|
||||
|
||||
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(seconds* (pictures.length)), event -> {
|
||||
alertStage.close();
|
||||
try {
|
||||
closeStage(alertStage);
|
||||
} catch (InterruptedException e) {
|
||||
Logger.error("Error closing alert stage: " + e.getMessage());
|
||||
}
|
||||
//alertStage.close();
|
||||
if (currentAlertStage == alertStage) {
|
||||
currentAlertStage = null;
|
||||
}
|
||||
@@ -275,26 +287,37 @@ public class AutoCloseAlert {
|
||||
double screenwidth = Screen.getPrimary().getBounds().getWidth();
|
||||
double screenheight = Screen.getPrimary().getBounds().getHeight();
|
||||
|
||||
double height = screenheight/4;
|
||||
double width = height * 21/9;
|
||||
double height = screenheight/4.0;
|
||||
double width = height * 21.0/9.0;
|
||||
|
||||
VBox root = new VBox(10);
|
||||
root.setPadding(new Insets(12));
|
||||
root.setPrefSize(width, height);
|
||||
root.setAlignment(Pos.CENTER);
|
||||
|
||||
List<Node> children = new ArrayList<>();
|
||||
if (ValidString(header)){
|
||||
Label headerLabel = new Label(header);
|
||||
headerLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 28px;");
|
||||
headerLabel.setWrapText(true);
|
||||
headerLabel.setMinHeight(height*0.25);
|
||||
children.add(headerLabel);
|
||||
headerLabel.setMaxWidth(Double.MAX_VALUE);
|
||||
headerLabel.prefWidthProperty().bind(root.widthProperty());
|
||||
root.getChildren().add(headerLabel);
|
||||
}
|
||||
if (ValidString(content)){
|
||||
Label contentLabel = new Label(content);
|
||||
contentLabel.setWrapText(true);
|
||||
contentLabel.setStyle("-fx-font-size: 24px;");
|
||||
contentLabel.setMinHeight(height*0.75);
|
||||
children.add(contentLabel);
|
||||
contentLabel.setMaxWidth(Double.MAX_VALUE);
|
||||
contentLabel.prefWidthProperty().bind(root.widthProperty());
|
||||
|
||||
VBox.setVgrow(contentLabel, Priority.ALWAYS);
|
||||
contentLabel.setAlignment(Pos.TOP_CENTER);
|
||||
root.getChildren().add(contentLabel);
|
||||
}
|
||||
|
||||
VBox root = new VBox(10, children.toArray(new Node[0]));
|
||||
root.setPrefSize(width, height);
|
||||
root.setAlignment(Pos.CENTER);
|
||||
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
alertStage.setScene(scene);
|
||||
@@ -323,10 +346,16 @@ public class AutoCloseAlert {
|
||||
* @param alertStage the alert stage to be closed
|
||||
*/
|
||||
private static void closeAlertStage(int seconds, Consumer<String> onClose, Stage alertStage) {
|
||||
|
||||
if (seconds>0){
|
||||
PauseTransition delay = new PauseTransition(Duration.seconds(seconds));
|
||||
delay.setOnFinished(e -> {
|
||||
alertStage.close();
|
||||
try {
|
||||
closeStage(alertStage);
|
||||
} catch (InterruptedException err) {
|
||||
Logger.error("Error closing alert stage: " + err.getMessage());
|
||||
}
|
||||
//alertStage.close();
|
||||
if (currentAlertStage == alertStage) {
|
||||
currentAlertStage = null;
|
||||
}
|
||||
@@ -340,13 +369,11 @@ public class AutoCloseAlert {
|
||||
private static Image LoadImage(String filename){
|
||||
if (ValidFile(filename)){
|
||||
try{
|
||||
Image mm = new Image(Paths.get(filename).toUri().toString());
|
||||
System.out.println("Load image from "+filename);
|
||||
return mm;
|
||||
return new Image(Paths.get(filename).toUri().toString());
|
||||
} catch (Exception e){
|
||||
System.out.println("Error loading image: " + filename+", Message: "+e.getMessage());
|
||||
Logger.error("Error loading image: " + filename+", Message: "+e.getMessage());
|
||||
}
|
||||
} else System.out.println("LoadImage: Invalid file: "+filename);
|
||||
} else Logger.error("LoadImage: Invalid file: " + filename);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static Config.SomeCodes.*;
|
||||
import static id.co.gtc.erhacam.Detectors.*;
|
||||
import static org.bytedeco.opencv.global.opencv_imgproc.*;
|
||||
|
||||
@SuppressWarnings({"unused"})
|
||||
@@ -67,6 +66,11 @@ public class Cameradetail {
|
||||
private LiveCamEvent event = null;
|
||||
private @Getter @Setter CameraConfigEnum cameraConfigEnum = CameraConfigEnum.CameraConfigCenter;
|
||||
private @Getter int LiveFPS = 0;
|
||||
private double topcrop = 0.0;
|
||||
private double bottomcrop = 0.0;
|
||||
private double leftcrop = 0.0;
|
||||
private double rightcrop = 0.0;
|
||||
private String title = "";
|
||||
|
||||
|
||||
|
||||
@@ -111,11 +115,11 @@ public class Cameradetail {
|
||||
private @Getter final UMat BestMat = new UMat();
|
||||
private @Getter final UMat LiveMat = new UMat();
|
||||
private @Getter final UMat ReducedMat = new UMat();
|
||||
private @Getter final UMat GrayMat = new UMat();
|
||||
private @Getter final Mat GrayMat = new Mat();
|
||||
|
||||
private @Getter Rect BestMatROI;
|
||||
private @Getter Rect ReducedMatROI;
|
||||
private @Getter Rect LiveMatROI;
|
||||
// private @Getter Rect BestMatROI;
|
||||
// private @Getter Rect ReducedMatROI;
|
||||
// private @Getter Rect LiveMatROI;
|
||||
|
||||
private boolean IsPortrait = false;
|
||||
|
||||
@@ -151,7 +155,8 @@ public class Cameradetail {
|
||||
|
||||
private boolean use_qr = false;
|
||||
private boolean use_face = false;
|
||||
private int _hardwareID = -1;
|
||||
|
||||
private @Getter Detectors detector;
|
||||
|
||||
private void setSliderValue(Slider sld, CameraProperty prop, double value){
|
||||
|
||||
@@ -235,6 +240,8 @@ public class Cameradetail {
|
||||
raise_log("Exposure for "+getCameraTitle()+" changed to "+newVal);
|
||||
});
|
||||
|
||||
detector = new Detectors();
|
||||
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -261,14 +268,20 @@ public class Cameradetail {
|
||||
public void setCameraTitle(String title){
|
||||
|
||||
if (ValidString(title)){
|
||||
this.title = title;
|
||||
LabelSetText(cameratitle, title,null);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSharpness_indicator(double value){
|
||||
if (value >= config.getSharpnessThreshold()){
|
||||
if (value < 0){
|
||||
// not defined
|
||||
LabelSetText(sharpness_indicator, "","");
|
||||
} else if (value >= config.getSharpnessThreshold()){
|
||||
// sharpness is good
|
||||
LabelSetText(sharpness_indicator, "OK","-fx-text-fill: green; -fx-border-color: black");
|
||||
} else {
|
||||
// sharpness is bad
|
||||
LabelSetText(sharpness_indicator,"BAD","-fx-text-fill: red; -fx-border-color: black");
|
||||
}
|
||||
}
|
||||
@@ -413,7 +426,6 @@ public class Cameradetail {
|
||||
}
|
||||
|
||||
mGrabber = grabber;
|
||||
_hardwareID = hardwareID;
|
||||
}
|
||||
|
||||
//Exposure and Focus Tricks :
|
||||
@@ -678,7 +690,7 @@ public class Cameradetail {
|
||||
* @return filename path of the saved photo, or null if failed
|
||||
*/
|
||||
public PhotoResult TakePhoto(String directory, String prefix) {
|
||||
PhotoResult result = new PhotoResult(cameratitle.getText());
|
||||
PhotoResult result = new PhotoResult(title);
|
||||
if (!ValidDirectory(directory)) directory = currentDirectory;
|
||||
|
||||
if (mGrabber!=null){
|
||||
@@ -690,34 +702,50 @@ public class Cameradetail {
|
||||
|
||||
|
||||
if (!BestMat.empty()){
|
||||
UMat cloned = new UMat();
|
||||
synchronized (BestMat){
|
||||
BestMat.copyTo(cloned);
|
||||
}
|
||||
|
||||
|
||||
// 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()));
|
||||
}
|
||||
|
||||
String fullresfile = GetFullQualityPhotoPath(directory, prefix);
|
||||
if (opencv_imgcodecs.imwrite(fullresfile, cloned, parampng)){
|
||||
result.setFullres(fullresfile);
|
||||
} else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+title);
|
||||
|
||||
// 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()));
|
||||
String reducedfile = GetReducedPhotoPath(directory, prefix);
|
||||
opencv_imgproc.resize(cloned, ReducedMat, ReducedSize);
|
||||
if (opencv_imgcodecs.imwrite(reducedfile, ReducedMat, paramjpeg)){
|
||||
result.setCompressedfile(reducedfile);
|
||||
} else {
|
||||
System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+title);
|
||||
}
|
||||
|
||||
String fullcropfile = GetFullQualityCropPhotoPath(directory, prefix);
|
||||
UMat croppedfull = CropMat(cloned);
|
||||
if (croppedfull!=null && !croppedfull.empty()){
|
||||
if (opencv_imgcodecs.imwrite(fullcropfile, croppedfull, parampng)){
|
||||
result.setFullcrop(fullcropfile);
|
||||
} else {
|
||||
System.out.println("TakePhoto failed, Unable to Save FullCrop Photo for camera "+title);
|
||||
}
|
||||
} else System.out.println("TakePhoto failed, Unable to Save FullCrop Photo for camera "+title);
|
||||
|
||||
|
||||
String reducedcropfile = GetReducedCropPhotoPath(directory, prefix);
|
||||
UMat reducedcrop = CropMat(ReducedMat);
|
||||
if (reducedcrop!=null && !reducedcrop.empty()){
|
||||
if (opencv_imgcodecs.imwrite(reducedcropfile, reducedcrop, paramjpeg)){
|
||||
result.setCompressedcrop(reducedcropfile);
|
||||
} else {
|
||||
System.out.println("TakePhoto failed, Unable to Save ReducedCrop Photo for camera "+title);
|
||||
}
|
||||
} else System.out.println("TakePhoto failed, Unable to Save ReducedCrop Photo for camera "+title);
|
||||
|
||||
cloned.release();
|
||||
|
||||
} else raise_log("TakePhoto failed, Live View is Empty");
|
||||
} catch (InterruptedException e){
|
||||
System.out.println("TakePhoto IsGrabbingLiveView interrupted");
|
||||
@@ -736,7 +764,9 @@ public class Cameradetail {
|
||||
|
||||
public String CropBestMat(String directory, String prefix, Rect ROI){
|
||||
UMat cloned = new UMat();
|
||||
synchronized (BestMat){
|
||||
BestMat.copyTo(cloned);
|
||||
}
|
||||
if (!cloned.empty()) {
|
||||
if (ValidROI(ROI)){
|
||||
if (ROIInsideUMat(ROI, cloned)){
|
||||
@@ -751,6 +781,7 @@ public class Cameradetail {
|
||||
} else Logger.error("CropBestMat failed, ROI is outside BestMat");
|
||||
} else Logger.error("CropBestMat failed, ROI is invalid");
|
||||
} else Logger.error("CropBestMat failed, BestMat is empty");
|
||||
cloned.release();
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -779,22 +810,34 @@ public class Cameradetail {
|
||||
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() + extension;
|
||||
return prefix+" "+timetag+" "+title + 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;
|
||||
return prefix+" "+timetag+" "+title + "_reduced" + extension;
|
||||
}
|
||||
|
||||
// public void Release(){
|
||||
// if (mGrabber!=null){
|
||||
// try{
|
||||
// StopLiveView();
|
||||
// mGrabber.release();
|
||||
// mGrabber = null;
|
||||
// } catch (Exception e){
|
||||
// System.out.println("Release failed, Unable to Release Camera, Error: " + e.getMessage());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public void StopLiveView(){
|
||||
Capturing.set(false);
|
||||
if (mGrabber!=null){
|
||||
try{
|
||||
mGrabber.close();
|
||||
System.out.println("Camera "+cameratitle.getText()+" stopped");
|
||||
System.out.println("Camera "+title+" stopped");
|
||||
setCameraStatus("Camera Stopped");
|
||||
} catch (Exception e){
|
||||
raise_log("StopLiveView failed, Unable to Stop Camera, Error: " + e.getMessage());
|
||||
@@ -829,11 +872,8 @@ public class Cameradetail {
|
||||
while(Capturing.get()){
|
||||
try {
|
||||
qr_semaphore.acquire();
|
||||
UMat gray;
|
||||
synchronized (lockObject){
|
||||
gray = GrayMat;
|
||||
}
|
||||
String qr = DetectQRFromMat(gray);
|
||||
|
||||
String qr = DetectQRFromMat(GrayMat.clone());
|
||||
if (ValidBarCode(qr)){
|
||||
if (event!=null) event.onDetectedQRCode(qr);
|
||||
}
|
||||
@@ -858,18 +898,15 @@ public class Cameradetail {
|
||||
while(Capturing.get()){
|
||||
try {
|
||||
face_semaphore.acquire();
|
||||
UMat gray;
|
||||
synchronized (lockObject){
|
||||
gray = GrayMat;
|
||||
}
|
||||
|
||||
|
||||
DetectorResult theface = null;
|
||||
boolean have_frontal_face = false;
|
||||
boolean have_left_45_face = false;
|
||||
int _face_width = 0;
|
||||
int _face_height = 0;
|
||||
|
||||
List<DetectorResult> frontalfaces = HaveFrontalFace(gray);
|
||||
List<DetectorResult> frontalfaces = detector.HaveFrontalFace(GrayMat.clone());
|
||||
//System.out.println("camera "+title+ (frontalfaces.isEmpty() ? " no frontal face detected" : " found "+frontalfaces.size()+" frontal faces"));
|
||||
if (!frontalfaces.isEmpty()){
|
||||
for(DetectorResult rect : frontalfaces){
|
||||
if (rect.haveFace() ){
|
||||
@@ -881,12 +918,14 @@ public class Cameradetail {
|
||||
if (rect.haveEyes()){
|
||||
rect.EyesRectangle(LiveMat);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// gak punya frontal face
|
||||
// coba cek punya profile left face 45 gak
|
||||
List<DetectorResult> Left45Faces = HaveLeft45Face(gray);
|
||||
List<DetectorResult> Left45Faces = detector.HaveLeft45Face(GrayMat.clone());
|
||||
//System.out.println("camera "+title+ (Left45Faces.isEmpty() ? " no left 45 face detected" : " found "+Left45Faces.size()+" left 45 faces"));
|
||||
if (!Left45Faces.isEmpty()){
|
||||
for(DetectorResult rect : Left45Faces){
|
||||
if (rect.haveFace()){
|
||||
@@ -908,10 +947,10 @@ public class Cameradetail {
|
||||
if (event!=null) event.onFrontalFaceDetector(true, _face_width, _face_height);
|
||||
LabelVisible(face_indicator,true);
|
||||
|
||||
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));
|
||||
}
|
||||
// Revisi 26/05/2025, LiveMatROI dihitung dari topcrop, bottomcrop, leftcrop dan rightcrop
|
||||
// if (theface.getFace()!=null){
|
||||
// LiveMatROI = new Rect(theface.getFace().x(), theface.getFace().y(), theface.getFace().width(), theface.getFace().height());
|
||||
// }
|
||||
|
||||
if (theface.getEyesCount()>=2){
|
||||
// ada mata (buka mata)
|
||||
@@ -921,16 +960,14 @@ public class Cameradetail {
|
||||
if (event!=null) event.onEyeDetector(true);
|
||||
LabelVisible(eye_indicator,true);
|
||||
|
||||
//System.out.println("Valid Eye Detected from camera "+cameratitle);
|
||||
// Valid eye condition
|
||||
|
||||
if (eye_state.get()!=1){
|
||||
// transisi dari tutup mata ke buka mata
|
||||
if (eye_state.get()==-1) {
|
||||
System.out.println("First Eye Detected from camera "+cameratitle.getText());
|
||||
//System.out.println("First Eye Detected from camera "+title);
|
||||
eye_state.set(1);
|
||||
} else {
|
||||
//System.out.println("Transition from close to open eyes");
|
||||
eye_state.set(1);
|
||||
|
||||
blink_counter.incrementAndGet();
|
||||
@@ -942,13 +979,13 @@ public class Cameradetail {
|
||||
long diff = now - last_blink.get();
|
||||
// kalau beda waktu antara blink 1 dan blink 2 kurang dari 3 detik
|
||||
if (diff<=3000){
|
||||
System.out.println("Double Blink Detected from camera "+cameratitle.getText());
|
||||
//System.out.println("Double Blink Detected from camera "+title);
|
||||
if (event!=null) event.onDoubleBlink((int)diff);
|
||||
}
|
||||
waiting_for_second_blink.set(false);
|
||||
} else {
|
||||
waiting_for_second_blink.set(true);
|
||||
System.out.println("First Blink Detected from camera "+cameratitle.getText());
|
||||
//System.out.println("First Blink Detected from camera "+title);
|
||||
}
|
||||
last_blink.set(now);
|
||||
}
|
||||
@@ -966,7 +1003,6 @@ public class Cameradetail {
|
||||
|
||||
|
||||
if (eye_state.get()!=0){
|
||||
//System.out.println("Transition from open to close eyes");
|
||||
eye_state.set(0);
|
||||
|
||||
}
|
||||
@@ -1003,12 +1039,21 @@ public class Cameradetail {
|
||||
|
||||
}
|
||||
|
||||
Mat imgmat = new Mat();
|
||||
LiveMat.copyTo(imgmat); // copy back to CPU
|
||||
|
||||
|
||||
if (LiveMat != null && !LiveMat.empty()){
|
||||
Mat imgmat = new Mat();
|
||||
// copy back to CPU
|
||||
LiveMat.copyTo(imgmat);
|
||||
setCameraStream(MatToImage(imgmat));
|
||||
imgmat.release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.println(Thread.currentThread().getName()+" interrupted");
|
||||
//System.out.println(Thread.currentThread().getName()+" interrupted");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1022,11 +1067,11 @@ public class Cameradetail {
|
||||
// 30 fps means 33 ms per frame
|
||||
// so if grab is quicker than 30 ms , its stale frame
|
||||
try{
|
||||
if (mGrabber==null) throw new FrameGrabber.Exception("Grabber is null");
|
||||
if (mGrabber==null) throw new Exception("Grabber is null");
|
||||
Frame frame = mGrabber.grab(); // grab frame
|
||||
delta = System.currentTimeMillis() - now;
|
||||
now = System.currentTimeMillis();
|
||||
} catch (FrameGrabber.Exception ignored) {
|
||||
} catch (Exception ignored) {
|
||||
|
||||
}
|
||||
|
||||
@@ -1052,11 +1097,10 @@ public class Cameradetail {
|
||||
|
||||
if (Capturing.get()) {
|
||||
try{
|
||||
if (mGrabber!=null)
|
||||
frame = mGrabber.grab();
|
||||
else throw new FrameGrabber.Exception("Grabber is null");
|
||||
if (mGrabber==null) throw new Exception("Grabber is null");
|
||||
|
||||
} catch (FrameGrabber.Exception e){
|
||||
frame = mGrabber.grab();
|
||||
} catch (Exception e){
|
||||
if (Capturing.get()){
|
||||
// kalau ada exception padahal masih capturing. Kalau sudah tidak capturing, tidak peduli
|
||||
if (ValidString(e.getMessage())){
|
||||
@@ -1098,27 +1142,41 @@ public class Cameradetail {
|
||||
UMat flippedmat = new UMat();
|
||||
opencv_core.flip(originalmat, flippedmat, 0); // flip vertical
|
||||
flippedmat.copyTo(originalmat);
|
||||
flippedmat.close();
|
||||
flippedmat.release();
|
||||
}
|
||||
if (config.isFlipCamera()){
|
||||
// revisi 18/03/2025
|
||||
UMat flippedmat = new UMat();
|
||||
opencv_core.flip(originalmat, flippedmat, 1); // flip horizontal
|
||||
flippedmat.copyTo(originalmat);
|
||||
flippedmat.close();
|
||||
flippedmat.release();
|
||||
}
|
||||
|
||||
// rotate 90 degree counter clockwise karena kamera potrait
|
||||
opencv_core.rotate(originalmat, BestMat, opencv_core.ROTATE_90_COUNTERCLOCKWISE);
|
||||
|
||||
|
||||
originalmat.release();
|
||||
|
||||
if (!BestMat.empty()) {
|
||||
|
||||
// LiveMat and GrayMat are synchronized
|
||||
synchronized (lockObject){
|
||||
opencv_imgproc.resize(BestMat, LiveMat, LiveSize); // resize to LiveSize
|
||||
opencv_imgproc.cvtColor(LiveMat,GrayMat, COLOR_BGR2GRAY); // convert to grayscale
|
||||
// resize BestMat to LiveSize
|
||||
UMat _liveMat = new UMat();
|
||||
opencv_imgproc.resize(BestMat, _liveMat, LiveSize);
|
||||
// crop LiveMat
|
||||
UMat croppedLiveMat = CropMat(_liveMat);
|
||||
if (croppedLiveMat!=null && !croppedLiveMat.empty()){
|
||||
croppedLiveMat.copyTo(LiveMat);
|
||||
croppedLiveMat.release();
|
||||
} else {
|
||||
_liveMat.copyTo(LiveMat);
|
||||
_liveMat.release();
|
||||
}
|
||||
// convert to grayscale
|
||||
|
||||
Mat xx = new Mat();
|
||||
LiveMat.copyTo(xx);
|
||||
opencv_imgproc.cvtColor(xx,GrayMat, COLOR_BGR2GRAY);
|
||||
}
|
||||
|
||||
if (use_qr){
|
||||
@@ -1132,19 +1190,73 @@ public class Cameradetail {
|
||||
}
|
||||
} catch ( FrameGrabber.Exception fe){
|
||||
System.out.println("FrameGrabber Exception in" + Thread.currentThread().getName() + " : " + fe.getMessage());
|
||||
fe.printStackTrace();
|
||||
//fe.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(Thread.currentThread().getName()+" interrupted");
|
||||
} catch (Exception e){
|
||||
System.out.println(Thread.currentThread().getName()+" exception : "+e.getMessage());
|
||||
e.printStackTrace();
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
private UMat CropMat(UMat mat){
|
||||
if (mat != null && !mat.empty()){
|
||||
int width = mat.cols();
|
||||
int height = mat.rows();
|
||||
|
||||
int x = (int) (width * leftcrop / 100);
|
||||
int y = (int) (height * topcrop / 100);
|
||||
int w = (int) (width * (100 - leftcrop - rightcrop) / 100);
|
||||
int h = (int) (height * (100 - topcrop - bottomcrop) / 100);
|
||||
|
||||
// Ensure the crop dimensions are valid
|
||||
if (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= width && y + h <= height) {
|
||||
Rect roi = new Rect(x, y, w, h);
|
||||
|
||||
UMat crop = new UMat();
|
||||
mat.apply(roi).copyTo(crop);
|
||||
return crop;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public void ChangeCropValue(){
|
||||
if ("01".equals(title)){
|
||||
topcrop = config.getCam1TopCrop();
|
||||
leftcrop = config.getCam1LeftCrop();
|
||||
rightcrop = config.getCam1RightCrop();
|
||||
bottomcrop = config.getCam1BottomCrop();
|
||||
} else if ("02".equals(title)){
|
||||
topcrop = config.getCam2TopCrop();
|
||||
leftcrop = config.getCam2LeftCrop();
|
||||
rightcrop = config.getCam2RightCrop();
|
||||
bottomcrop = config.getCam2BottomCrop();
|
||||
} else if ("03".equals(title)){
|
||||
topcrop = config.getCam3TopCrop();
|
||||
leftcrop = config.getCam3LeftCrop();
|
||||
rightcrop = config.getCam3RightCrop();
|
||||
bottomcrop = config.getCam3BottomCrop();
|
||||
} else if ("04".equals(title)){
|
||||
topcrop = config.getCam4TopCrop();
|
||||
leftcrop = config.getCam4LeftCrop();
|
||||
rightcrop = config.getCam4RightCrop();
|
||||
bottomcrop = config.getCam4BottomCrop();
|
||||
} else if ("05".equals(title)){
|
||||
topcrop = config.getCam5TopCrop();
|
||||
leftcrop = config.getCam5LeftCrop();
|
||||
rightcrop = config.getCam5RightCrop();
|
||||
bottomcrop = config.getCam5BottomCrop();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean StartLiveView(LiveCamEvent event, String cameratitle, boolean use_qr , boolean use_face) {
|
||||
this.event = event;
|
||||
this.title = cameratitle;
|
||||
ChangeCropValue();
|
||||
if (mGrabber != null) {
|
||||
try {
|
||||
|
||||
@@ -1172,6 +1284,7 @@ public class Cameradetail {
|
||||
@Override
|
||||
public void run() {
|
||||
if (Capturing.get()){
|
||||
|
||||
int fpsval = fps.getAndSet(0);
|
||||
if (fpsval!=LiveFPS){
|
||||
LiveFPS = fpsval;
|
||||
@@ -1221,83 +1334,78 @@ public class Cameradetail {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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());
|
||||
|
||||
}
|
||||
// /**
|
||||
// * 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));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Detect QR Code from Mat
|
||||
* @param graymat Mat in Gray Scale
|
||||
* @param mat Mat in Gray Scale
|
||||
* @return QR Code Text, or null if not detected
|
||||
*/
|
||||
private String DetectQRFromMat(UMat graymat){
|
||||
private String DetectQRFromMat(Mat mat){
|
||||
if (qrreader!=null){
|
||||
Mat mat = new Mat();
|
||||
graymat.copyTo(mat); // back to CPU, because zxing only accept BufferedImage
|
||||
if (mat!=null && !mat.empty()){
|
||||
BufferedImage bufferedImage = matToBufferedImage(mat);
|
||||
String title = cameratitle.getText();
|
||||
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(bufferedImage)));
|
||||
try{
|
||||
Result result = qrreader.decode(binaryBitmap);
|
||||
@@ -1306,6 +1414,9 @@ public class Cameradetail {
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
mat.release();
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@ import BASS.AudioPlayer;
|
||||
import BASS.PlaybackStatus;
|
||||
import Camera.*;
|
||||
import Config.CameraConfigEnum;
|
||||
import Config.SomeCodes;
|
||||
import Database.PhotoReviewClass;
|
||||
import Database.Sqlite;
|
||||
import ErhaAPI.ErhaAPI;
|
||||
import ErhaAPI.BarcodeResullt;
|
||||
import ErhaAPI.BarcodeHttpResult;
|
||||
import ErhaAPI.UploadHttpResult;
|
||||
import ErhaAPI.PhotoResult;
|
||||
import ErhaAPI.PatientRecord;
|
||||
import ErhaAPI.UploadResult;
|
||||
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.application.Platform;
|
||||
|
||||
import javafx.concurrent.Task;
|
||||
@@ -27,8 +28,10 @@ import javafx.stage.DirectoryChooser;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
import javafx.util.Duration;
|
||||
import org.bytedeco.javacv.OpenCVFrameGrabber;
|
||||
import org.bytedeco.javacv.VideoInputFrameGrabber;
|
||||
import org.bytedeco.opencv.opencv_core.Rect;
|
||||
@@ -36,6 +39,7 @@ import org.bytedeco.opencv.opencv_core.Size;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import static Config.SomeCodes.*;
|
||||
import static org.bytedeco.opencv.global.opencv_videoio.CAP_DSHOW;
|
||||
|
||||
public class CaptureView {
|
||||
|
||||
@@ -71,7 +75,7 @@ public class CaptureView {
|
||||
private String audio_posisikan_muka = "posisikan_wajah.wav";
|
||||
private String audio_scan_barcode = "scan_barcode.wav";
|
||||
private String audio_pengambilan_gagal = "pengambilan_gagal.wav";
|
||||
private String audio_pengambilan_berhasil = "pengambilan_berhasil.wav";
|
||||
private String audio_pengambilan_berhasil = "pengambilan_berhasil_tunggu_lobby.wav";
|
||||
private String audio_upload_gagal = "upload_gagal.wav";
|
||||
private String audio_countdown = "countdown321.wav";
|
||||
private String audio_camera_shutter = "camera-shutter-click-01.wav";
|
||||
@@ -86,7 +90,7 @@ public class CaptureView {
|
||||
|
||||
private final AtomicBoolean isTakingPhoto = new AtomicBoolean(false);
|
||||
|
||||
private final ErhaAPI erhaAPI = new ErhaAPI(false);
|
||||
private final ErhaAPI erhaAPI = new ErhaAPI(config.isProduction());
|
||||
|
||||
// for timeout 180 detik
|
||||
private final int timeout = 180;
|
||||
@@ -140,6 +144,7 @@ public class CaptureView {
|
||||
|
||||
@FXML
|
||||
private void TakePhotos(){
|
||||
if (audioTimeline!=null) audioTimeline.stop();
|
||||
String directory = config.getPhotoDirectory();
|
||||
String prefix = RemoveSpaces(medicalRecordID.getText()) ;
|
||||
boolean has_face = Arrays.stream(have_face).anyMatch(AtomicBoolean::get);
|
||||
@@ -148,10 +153,7 @@ public class CaptureView {
|
||||
isTakingPhoto.set(true);
|
||||
if (has_face){
|
||||
AutoCloseAlert.show("Pengambilan Foto", "Tahan Posisi Anda", "Proses ini kurang lebih 3 detik", 5, null);
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_tahan_posisi)){
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_tahan_posisi, new PlaybackStatus() {
|
||||
PlayFileWithEvent(audio_tahan_posisi, new PlaybackStatus() {
|
||||
@Override
|
||||
public void onPlaybackStarted(String filename) {
|
||||
|
||||
@@ -159,9 +161,8 @@ public class CaptureView {
|
||||
|
||||
@Override
|
||||
public void onPlaybackFinished(String filename) {
|
||||
|
||||
|
||||
audioPlayer.PlayFile(audio_countdown, new PlaybackStatus() {
|
||||
Wait(500);
|
||||
PlayFileWithEvent(audio_countdown, new PlaybackStatus() {
|
||||
@Override
|
||||
public void onPlaybackStarted(String filename) {
|
||||
|
||||
@@ -177,8 +178,6 @@ public class CaptureView {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -187,42 +186,22 @@ public class CaptureView {
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
AutoCloseAlert.show("Error", "No Face Detected", "No Face Detected", 5, null);
|
||||
isTakingPhoto.set(false);
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_posisikan_muka)) {
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_posisikan_muka, null);
|
||||
PlayFileWithoutEvent(audio_posisikan_muka);
|
||||
}
|
||||
} else {
|
||||
isTakingPhoto.set(false);
|
||||
clear();
|
||||
PlayFileWithoutEvent(audio_scan_barcode);
|
||||
}
|
||||
} else {
|
||||
isTakingPhoto.set(false);
|
||||
AutoCloseAlert.show("Invalid Photo Directory","Photo Directory not set", "Please set photo directory at Setting", 5, s -> AutoCloseAlert.show("Setting", "Setting", "Please set photo directory", 0, sx-> clear()));
|
||||
|
||||
}
|
||||
} else {
|
||||
System.out.println("Prefix invalid, not taking photo");
|
||||
isTakingPhoto.set(false);
|
||||
//AutoCloseAlert.show("QR Code Not Available", "", "Please scan QR before continue", 5, s -> AutoCloseAlert.show("Scan Barcode", "Silahkan Scan Barcode Anda", "Arahkan kertas barcode ke kamera", 0, null));
|
||||
if (!Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
|
||||
if (AutoCloseAlert.banner_01!=null){
|
||||
System.out.println("Showing banner 01 because prefix invalid");
|
||||
AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0,null);
|
||||
}
|
||||
}
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_scan_barcode)) {
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_scan_barcode, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("Photo Directory invalid, not taking photo");
|
||||
isTakingPhoto.set(false);
|
||||
AutoCloseAlert.show("Invalid Photo Directory","Photo Directory not set", "Please set photo directory at Setting", 5, s -> AutoCloseAlert.show("Setting", "Setting", "Please set photo directory", 0, null));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -241,7 +220,7 @@ public class CaptureView {
|
||||
@Override
|
||||
public PhotoResult call() {
|
||||
if (image!=null){
|
||||
image.RemapROI(0.1, 0.3, false);
|
||||
//image.RemapROI(0.1, 0.3, false);
|
||||
double sharpness = CalculateSharpness(image.getGrayMat());
|
||||
image.setSharpness_indicator(sharpness);
|
||||
PhotoResult p = image.TakePhoto(directory, prefix);
|
||||
@@ -256,8 +235,10 @@ public class CaptureView {
|
||||
}
|
||||
}
|
||||
|
||||
AtomicInteger takephoto_failure_counter = new AtomicInteger(0);
|
||||
|
||||
private void take_photo_lanjutan(String directory, String prefix){
|
||||
audioPlayer.PlayFile(audio_camera_shutter, null);
|
||||
PlayFileWithoutEvent(audio_camera_shutter);
|
||||
Size thumbsize = new Size(160,120);
|
||||
|
||||
PhotoReviewClass prc = new PhotoReviewClass();
|
||||
@@ -299,8 +280,6 @@ public class CaptureView {
|
||||
|
||||
|
||||
|
||||
String timestamp = SomeCodes.GetDateTimeString();
|
||||
System.out.println("Creating timestamp: "+timestamp);
|
||||
|
||||
// check for blurred image
|
||||
double score1=-1, score2=-1, score3=-1, score4=-1, score5=-1;
|
||||
@@ -322,6 +301,7 @@ public class CaptureView {
|
||||
System.out.println("Sharpness score: "+score1+", "+score2+", "+score3+", "+score4+", "+score5);
|
||||
double lowest = FindLowestValue(score1,score2,score3,score4,score5);
|
||||
if (lowest<=config.getSharpnessThreshold()){
|
||||
// jelek
|
||||
String culprit = "";
|
||||
if (lowest==score1) culprit = "camera 1";
|
||||
else if (lowest==score2) culprit = "camera 2";
|
||||
@@ -329,9 +309,19 @@ public class CaptureView {
|
||||
else if (lowest==score4) culprit = "camera 4";
|
||||
else if (lowest==score5) culprit = "camera 5";
|
||||
String lowest_string = String.format("%.2f", lowest);
|
||||
AutoCloseAlert.show("Take Photos Failed", "Blurred Image Detected", "Blurred Image Detected at "+culprit+" with sharpness score "+lowest_string, 5, null);
|
||||
isTakingPhoto.set(false);
|
||||
AutoCloseAlert.show("Take Photos Failed", "Blurred Image Detected", "Blurred Image Detected at "+culprit+" with sharpness score "+lowest_string, 5, s -> isTakingPhoto.set(false));
|
||||
takephoto_failure_counter.incrementAndGet();
|
||||
if (takephoto_failure_counter.get() < 2){
|
||||
PlayFileWithoutEvent(audio_pengambilan_gagal);
|
||||
} else {
|
||||
PlayFileWithoutEvent(audio_hubungi_staf_kami);
|
||||
clear();
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
// bagus
|
||||
takephoto_failure_counter.set(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -487,10 +477,15 @@ public class CaptureView {
|
||||
|
||||
String[] files = prc.compressed();
|
||||
if (files.length>0){
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_pengambilan_berhasil)){
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_pengambilan_berhasil, new PlaybackStatus() {
|
||||
AutoCloseAlert.showpictures(prc.compressedcrop(),3, (s)->{
|
||||
if (AutoCloseAlert.banner_02!=null) {
|
||||
AutoCloseAlert.showbanner(AutoCloseAlert.banner_02, 0, null);
|
||||
|
||||
UploadFiles(prc, prefix);
|
||||
if (runningTask!=null) runningTask.cancel(false);
|
||||
}
|
||||
});
|
||||
PlayFileWithEvent(audio_pengambilan_berhasil, new PlaybackStatus() {
|
||||
@Override
|
||||
public void onPlaybackStarted(String filename) {
|
||||
|
||||
@@ -498,16 +493,6 @@ public class CaptureView {
|
||||
|
||||
@Override
|
||||
public void onPlaybackFinished(String filename) {
|
||||
AutoCloseAlert.showpictures(prc.compressed(),2, (s)->{
|
||||
if (AutoCloseAlert.banner_02!=null) {
|
||||
System.out.println("Showing banner 02 after photo taken");
|
||||
AutoCloseAlert.showbanner(AutoCloseAlert.banner_02, 0, null);
|
||||
|
||||
UploadFiles(prc, prefix);
|
||||
if (runningTask!=null) runningTask.cancel(false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -515,41 +500,32 @@ public class CaptureView {
|
||||
public void onPlaybackFailure(String filename) {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_pengambilan_gagal)){
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_pengambilan_gagal, null);
|
||||
}
|
||||
}
|
||||
PlayFileWithoutEvent(audio_pengambilan_gagal);
|
||||
clear();
|
||||
if (runningTask!=null) runningTask.cancel(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void UploadFiles(PhotoReviewClass prc, String prefix){
|
||||
String[] files = prc.compressed();
|
||||
String[] files = prc.compressedcrop();
|
||||
if (files.length>0){
|
||||
InsertSQL(prc);
|
||||
|
||||
erhaAPI.setProduction(config.isProduction());
|
||||
Task<Void> uploadtask = new Task<>() {
|
||||
@Override
|
||||
protected Void call() {
|
||||
int totalfiles = files.length;
|
||||
int counter = 0;
|
||||
for (String ff : files) {
|
||||
UploadResult ur = erhaAPI.Upload_File(prefix, ff,true);
|
||||
if (ur != null) {
|
||||
if (ur.message.startsWith("Record has been created")) {
|
||||
|
||||
UploadHttpResult ur = erhaAPI.Upload_File(prefix, ff,true);
|
||||
if (ur.getResult().message.startsWith("Record has been created")) {
|
||||
counter++;
|
||||
updateMessage("Upload success for " + ff);
|
||||
} else updateMessage("Upload failed for " + ff+", Message : "+ur.message);
|
||||
} else updateMessage("Upload failed for " + ff+" because UploadResult is null");
|
||||
|
||||
} else updateMessage("Upload failed for " + ff+", Message : "+ur.getResult().message);
|
||||
}
|
||||
if (counter == totalfiles) {
|
||||
super.succeeded();
|
||||
@@ -560,29 +536,18 @@ public class CaptureView {
|
||||
|
||||
|
||||
|
||||
uploadtask.messageProperty().addListener((obs, oldval, newval)-> {
|
||||
System.out.println("UploadTask message: "+newval);
|
||||
Logger.info(newval);
|
||||
});
|
||||
uploadtask.messageProperty().addListener((obs, oldval, newval)-> Logger.info(newval));
|
||||
|
||||
|
||||
uploadtask.setOnSucceeded(e-> {
|
||||
System.out.println("UploadTask succeeded");
|
||||
clear();
|
||||
});
|
||||
uploadtask.setOnSucceeded(e-> clear());
|
||||
|
||||
uploadtask.setOnFailed(e-> {
|
||||
System.out.println("UploadTask failed");
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_upload_gagal)){
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_upload_gagal, null);
|
||||
}
|
||||
}
|
||||
PlayFileWithoutEvent(audio_upload_gagal);
|
||||
AutoCloseAlert.show("Upload Failed", "Upload Failed", "Upload Failed", 5, s -> clear());
|
||||
});
|
||||
|
||||
Thread uploadThread = new Thread(uploadtask);
|
||||
uploadThread.setName("UploadThread MedicalRecordID="+prefix);
|
||||
uploadThread.setDaemon(true);
|
||||
uploadThread.start();
|
||||
|
||||
@@ -592,7 +557,7 @@ public class CaptureView {
|
||||
@FXML
|
||||
public void initialize(){
|
||||
audio_posisikan_muka = ExtractResource("/posisikan_wajah.wav");
|
||||
audio_pengambilan_berhasil = ExtractResource("/pengambilan_berhasil.wav");
|
||||
audio_pengambilan_berhasil = ExtractResource("/pengambilan_berhasil_tunggu_lobby.wav");
|
||||
audio_pengambilan_gagal = ExtractResource("/pengambilan_gagal.wav");
|
||||
audio_scan_barcode = ExtractResource("/scan_barcode.wav");
|
||||
audio_upload_gagal = ExtractResource("/upload_gagal.wav");
|
||||
@@ -604,15 +569,12 @@ public class CaptureView {
|
||||
|
||||
//tambahan 19/03/2025
|
||||
barcodeData.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
System.out.println("barcodeData changed from ["+oldValue+"] to ["+newValue+"]");
|
||||
if (ValidBarCode(newValue)){
|
||||
if (Objects.equals(AutoCloseAlert.banner_01, AutoCloseAlert.shownBanner)){
|
||||
System.out.println("Close banner 01");
|
||||
AutoCloseAlert.close();
|
||||
}
|
||||
} else {
|
||||
if (AutoCloseAlert.banner_01!=null){
|
||||
System.out.println("Show banner 01");
|
||||
AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0, null);
|
||||
}
|
||||
}
|
||||
@@ -645,12 +607,7 @@ public class CaptureView {
|
||||
LoadCameraDetail(cam5, 5, CameraConfigEnum.CameraConfigRight90);
|
||||
|
||||
Platform.runLater(()->{
|
||||
if (!Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
|
||||
if (AutoCloseAlert.banner_01!=null){
|
||||
System.out.println("Showing banner 01 for first time");
|
||||
AutoCloseAlert.showbanner(AutoCloseAlert.banner_01,0,null);
|
||||
}
|
||||
}
|
||||
clear();
|
||||
|
||||
int indexleft90=-1;
|
||||
int indexleft45=-1;
|
||||
@@ -667,6 +624,7 @@ public class CaptureView {
|
||||
if (indexleft90!=-1){
|
||||
final int finalindex = indexleft90;
|
||||
Thread c1 = new Thread(()-> SetupCameraWithController(image1, camleft90, finalindex));
|
||||
c1.setName("SetupCameraWithController "+camleft90);
|
||||
c1.setDaemon(true);
|
||||
c1.start();
|
||||
}
|
||||
@@ -681,6 +639,7 @@ public class CaptureView {
|
||||
if (indexleft45!=-1) {
|
||||
final int finalindex = indexleft45;
|
||||
Thread c2 = new Thread(()-> SetupCameraWithController(image2, camleft45, finalindex));
|
||||
c2.setName("SetupCameraWithController "+camleft45);
|
||||
c2.setDaemon(true);
|
||||
c2.start();
|
||||
}
|
||||
@@ -695,6 +654,7 @@ public class CaptureView {
|
||||
if (indexcenter!=-1) {
|
||||
final int finalindex = indexcenter;
|
||||
Thread c3 = new Thread(()-> SetupCameraWithController(image3, camcenter, finalindex));
|
||||
c3.setName("SetupCameraWithController "+camcenter);
|
||||
c3.setDaemon(true);
|
||||
c3.start();
|
||||
}
|
||||
@@ -709,6 +669,7 @@ public class CaptureView {
|
||||
if (indexright45!=-1) {
|
||||
final int finalindex = indexright45;
|
||||
Thread c4 = new Thread(()-> SetupCameraWithController(image4, camright45, finalindex));
|
||||
c4.setName("SetupCameraWithController "+camright45);
|
||||
c4.setDaemon(true);
|
||||
c4.start();
|
||||
}
|
||||
@@ -724,6 +685,7 @@ public class CaptureView {
|
||||
if (indexright90!=-1) {
|
||||
final int finalindex = indexright90;
|
||||
Thread c5 = new Thread(()-> SetupCameraWithController(image5, camright90, finalindex));
|
||||
c5.setName("SetupCameraWithController "+camright90);
|
||||
c5.setDaemon(true);
|
||||
c5.start();
|
||||
}
|
||||
@@ -737,11 +699,23 @@ public class CaptureView {
|
||||
|
||||
}
|
||||
|
||||
Timeline audioTimeline;
|
||||
|
||||
private void clear(){
|
||||
isTakingPhoto.set(false);
|
||||
TextAreaSetText(medicalRecordID,"");
|
||||
TextAreaSetText(PatientName,"");
|
||||
if (image1!=null) image1.setSharpness_indicator(-1);
|
||||
if (image2!=null) image2.setSharpness_indicator(-1);
|
||||
if (image3!=null) image3.setSharpness_indicator(-1);
|
||||
if (image4!=null) image4.setSharpness_indicator(-1);
|
||||
if (image5!=null) image5.setSharpness_indicator(-1);
|
||||
if (barcodeData.getText().isBlank()){
|
||||
// pancing supaya addlistener barcodeData trigger
|
||||
TextAreaSetText(barcodeData,"x");
|
||||
Wait(10);
|
||||
TextAreaSetText(barcodeData,"");
|
||||
} else TextAreaSetText(barcodeData,"");
|
||||
}
|
||||
|
||||
public void Unload(){
|
||||
@@ -764,6 +738,7 @@ public class CaptureView {
|
||||
config.Save();
|
||||
}
|
||||
|
||||
AtomicBoolean anti_bawel = new AtomicBoolean(false);
|
||||
|
||||
private void SetupCameraWithController(Cameradetail image, String cameraname, int devicenumber){
|
||||
if (image!=null){
|
||||
@@ -804,7 +779,9 @@ public class CaptureView {
|
||||
|
||||
Platform.runLater(()-> image.setCameraTitle(title));
|
||||
if (devicenumber!=-1){
|
||||
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(devicenumber);
|
||||
// revisi 09/05/2025 dari new OpenCVFrameGrabber(devicenumber)
|
||||
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(CAP_DSHOW+devicenumber);
|
||||
|
||||
// default
|
||||
int livewidth = 640;
|
||||
int liveheight = 480;
|
||||
@@ -836,8 +813,8 @@ public class CaptureView {
|
||||
photoheight = ObsbotMeet2.ModeBest.getHeight();
|
||||
livewidth = ObsbotMeet2.ModeLive.getWidth();
|
||||
liveheight = ObsbotMeet2.ModeLive.getHeight();
|
||||
reducewidth = ObsbotMeet2.Mode3.getWidth();
|
||||
reduceheight = ObsbotMeet2.Mode3.getHeight();
|
||||
reducewidth = ObsbotMeet2.Mode2.getWidth();
|
||||
reduceheight = ObsbotMeet2.Mode2.getHeight();
|
||||
}
|
||||
image.SetGrabber(devicenumber,grabber, livewidth,liveheight,photowidth,photoheight,reducewidth,reduceheight, true);
|
||||
|
||||
@@ -845,6 +822,9 @@ public class CaptureView {
|
||||
boolean use_qr_detector = true;
|
||||
|
||||
LiveCamEvent lce = new LiveCamEvent() {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onDetectedQRCode(String barCode) {
|
||||
barCode = RemoveSpaces(barCode);
|
||||
@@ -853,39 +833,135 @@ public class CaptureView {
|
||||
if (!barCode.equals(prefix)){
|
||||
final String finalbarCode = barCode;
|
||||
TextAreaSetText(barcodeData, finalbarCode);
|
||||
|
||||
// revisi 19/05/2025
|
||||
if (runningTask!=null) runningTask.cancel(false);
|
||||
runningTask = timeoutExecutor.schedule(()->{
|
||||
// timeout
|
||||
clear();
|
||||
System.out.println("180 seconds timeout");
|
||||
}, timeout, TimeUnit.SECONDS);
|
||||
|
||||
// Revisi 19/05/2025
|
||||
// pakai Timeline untuk pengulangan PlayFile audio_posisikan_muka dengan interval 5 detik
|
||||
// diulang 3x
|
||||
// terakhir, PlayFile audio_hubungi_staf_kami
|
||||
|
||||
audioTimeline = new Timeline();
|
||||
final int file_duration = 8; // audio_posisikan_muka durasi 7 detik
|
||||
audioTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(0), k1 -> PlayFileWithEvent(audio_posisikan_muka, new PlaybackStatus() {
|
||||
@Override
|
||||
public void onPlaybackStarted(String filename) {
|
||||
anti_bawel.set(true);
|
||||
System.out.println("Peringatan pertama audio_posisikan_muka");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFinished(String filename) {
|
||||
anti_bawel.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFailure(String filename) {
|
||||
anti_bawel.set(false);
|
||||
}
|
||||
})));
|
||||
|
||||
audioTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(file_duration+5), k2 -> PlayFileWithEvent(audio_posisikan_muka, new PlaybackStatus() {
|
||||
|
||||
@Override
|
||||
public void onPlaybackStarted(String filename) {
|
||||
anti_bawel.set(true);
|
||||
System.out.println("Peringatan kedua audio_posisikan_muka");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFinished(String filename) {
|
||||
anti_bawel.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFailure(String filename) {
|
||||
anti_bawel.set(false);
|
||||
}
|
||||
})));
|
||||
|
||||
audioTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(3*file_duration+5), k3 -> PlayFileWithEvent(audio_posisikan_muka, new PlaybackStatus() {
|
||||
|
||||
@Override
|
||||
public void onPlaybackStarted(String filename) {
|
||||
anti_bawel.set(true);
|
||||
System.out.println("Peringatan ketiga audio_posisikan_muka");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFinished(String filename) {
|
||||
anti_bawel.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFailure(String filename) {
|
||||
anti_bawel.set(false);
|
||||
}
|
||||
})));
|
||||
audioTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(5*file_duration+5), k4 ->{
|
||||
PlayFileWithEvent(audio_hubungi_staf_kami, new PlaybackStatus() {
|
||||
@Override
|
||||
public void onPlaybackStarted(String filename) {
|
||||
anti_bawel.set(true);
|
||||
System.out.println("Peringatan keempat audio_hubungi_staf_kami");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFinished(String filename) {
|
||||
anti_bawel.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFailure(String filename) {
|
||||
anti_bawel.set(false);
|
||||
}
|
||||
});
|
||||
clear();
|
||||
}));
|
||||
|
||||
|
||||
Task<PatientRecord> checkpatientID = new Task<>() {
|
||||
@Override
|
||||
protected PatientRecord call() throws Exception {
|
||||
BarcodeResullt br = erhaAPI.Validate_Barcode(finalbarCode,true);
|
||||
if (br!=null){
|
||||
if (br.message.startsWith("Records found")){
|
||||
if (br.data!=null && br.data.length>0){
|
||||
PatientRecord pr = br.data[0];
|
||||
erhaAPI.setProduction(config.isProduction());
|
||||
BarcodeHttpResult br = erhaAPI.Validate_Barcode(finalbarCode,true);
|
||||
if (br.getStatusCode()==200){
|
||||
if (br.getResult().message.startsWith("Records found")){
|
||||
if (br.getResult().data!=null && br.getResult().data.length>0){
|
||||
PatientRecord pr = br.getResult().data[0];
|
||||
if (!pr.medical_record_detail_id.isBlank()){
|
||||
if (!pr.name.isBlank()){
|
||||
super.succeeded();
|
||||
return pr;
|
||||
} else {
|
||||
Logger.error("Barcode ",finalbarCode," PatientRecord name is empty");
|
||||
throw new Exception("Barcode "+finalbarCode+" PatientRecord name kosong");
|
||||
throw new Exception("Barcode "+finalbarCode+" PatientRecord name kosong, code= "+br.getStatusCode());
|
||||
}
|
||||
} else {
|
||||
Logger.error("Barcode ",finalbarCode," PatientRecord medical_record_detail_id is empty");
|
||||
throw new Exception("Data dengan barcode "+finalbarCode+", PatientRecord medical_record_detail_id kosong");
|
||||
throw new Exception("Data dengan barcode "+finalbarCode+", PatientRecord medical_record_detail_id kosong, code= "+br.getStatusCode());
|
||||
}
|
||||
} else {
|
||||
Logger.error("Record associated with barcode ",finalbarCode," is empty");
|
||||
throw new Exception("Data dengan barcode "+finalbarCode+" ditemukan di server, tetapi kosong");
|
||||
throw new Exception("Data dengan barcode "+finalbarCode+" ditemukan di server, tetapi kosong, code= "+br.getStatusCode());
|
||||
}
|
||||
} else {
|
||||
Logger.error("Record associated with barcode ",finalbarCode," is not found");
|
||||
throw new Exception("Data dengan barcode "+finalbarCode+" tidak ditemukan di server");
|
||||
throw new Exception("Data dengan barcode "+finalbarCode+" tidak ditemukan di server, code= "+br.getStatusCode());
|
||||
}
|
||||
} else {
|
||||
Logger.error("BarcodeResullt with barcode ",finalbarCode," is null");
|
||||
throw new Exception("BarcodeResult dengan barcode "+finalbarCode+" menghasilkan null");
|
||||
Logger.error("HTTP code ", br.getStatusCode(), " for barcode ", finalbarCode);
|
||||
throw new Exception("Barcode "+finalbarCode+" failed, code= "+br.getStatusCode()+", message: "+br.getBody());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
checkpatientID.setOnSucceeded(event -> {
|
||||
@@ -895,34 +971,19 @@ public class CaptureView {
|
||||
TextAreaSetText(medicalRecordID,""+medrecid);
|
||||
TextAreaSetText(PatientName, pr.name);
|
||||
|
||||
if (anti_bawel.get()) return; // sudah ada LiveCamEvent lain yang bunyiin, jadi tidak usah bunyiin lagi
|
||||
if (audioTimeline!=null) audioTimeline.playFromStart();
|
||||
|
||||
runningTask = timeoutExecutor.schedule(()->{
|
||||
// timeout
|
||||
System.out.println("runningTask timeout after "+timeout+" seconds");
|
||||
clear();
|
||||
}, timeout, TimeUnit.SECONDS);
|
||||
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(),audio_posisikan_muka)) {
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_posisikan_muka, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
checkpatientID.setOnFailed(event -> {
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_data_barcode_tidak_ditemukan)) {
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_data_barcode_tidak_ditemukan,null);
|
||||
}
|
||||
}
|
||||
PlayFileWithoutEvent(audio_data_barcode_tidak_ditemukan);
|
||||
clear();
|
||||
Task<?> failed = (Task<?>) event.getSource();
|
||||
Throwable t = failed.getException();
|
||||
final String message = t.getMessage();
|
||||
System.out.println("checkpatientID.setOnFailed message : "+message);
|
||||
|
||||
|
||||
AutoCloseAlert.show("Data Tidak Ditemukan", "Pastikan data barcode anda benar", message , 5, s -> clear());
|
||||
@@ -930,6 +991,7 @@ public class CaptureView {
|
||||
});
|
||||
|
||||
Thread checkpatientIDThread = new Thread(checkpatientID);
|
||||
checkpatientIDThread.setName("CheckPatientID barcode="+barCode);
|
||||
checkpatientIDThread.setDaemon(true);
|
||||
checkpatientIDThread.start();
|
||||
|
||||
@@ -937,6 +999,8 @@ public class CaptureView {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onFrontalFaceDetector(boolean hasface, int width, int height) {
|
||||
if (hasface!= _have_face.get()){
|
||||
@@ -946,15 +1010,33 @@ public class CaptureView {
|
||||
}
|
||||
//update_status(image);
|
||||
|
||||
// instruksi scan barcode ketika welcomeUI masih muncul dan ada muka terdeteksi
|
||||
if (hasface && Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(), audio_scan_barcode)) {
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
audioPlayer.PlayFile(audio_scan_barcode, null);
|
||||
}
|
||||
if (hasface){
|
||||
// ada face terdeteksi
|
||||
if (Objects.equals(AutoCloseAlert.shownBanner, AutoCloseAlert.banner_01)){
|
||||
// WelcomeUI masih muncul
|
||||
if (anti_bawel.get()) return; // sudah ada LiveCamEvent lain yang bunyiin, jadi tidak usah bunyiin lagi
|
||||
PlayFileWithEvent(audio_scan_barcode, new PlaybackStatus() {
|
||||
@Override
|
||||
public void onPlaybackStarted(String filename) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFinished(String filename) {
|
||||
WaitAsync(15*1000, "anti bawel", x-> anti_bawel.set(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaybackFailure(String filename) {
|
||||
|
||||
}
|
||||
});
|
||||
} else if (audioTimeline!=null){
|
||||
// WelcomeUI sudah tidak muncul, tapi audioTimeLine masih ada
|
||||
audioTimeline.stop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -992,9 +1074,8 @@ public class CaptureView {
|
||||
|
||||
@Override
|
||||
public void onDoubleBlink(int counter) {
|
||||
System.out.println("Double Blink detected at camera "+title+" delay= "+counter);
|
||||
if (audioPlayer!=null && audioPlayer.isPlaying()) return; // let audio finish playback
|
||||
if (isTakingPhoto.get()) return; // other camera is taking picture
|
||||
if (isTakingPhoto.get()) return; // another camera is taking picture
|
||||
// revisi 08/04/2025
|
||||
TakePhotos();
|
||||
}
|
||||
@@ -1022,8 +1103,11 @@ public class CaptureView {
|
||||
};
|
||||
image.setCameraStatus("Camera Starting");
|
||||
if (image.StartLiveView(lce, title, use_qr_detector, use_face_detector)){
|
||||
//TODO Start Live View berhasil, apa lagi yang mau dikerjakan ?
|
||||
|
||||
image.getDetector().setFaceMaxSize(config.getCascadeMaxSize());
|
||||
image.getDetector().setFaceMinSize(config.getCascadeMinSize());
|
||||
image.getDetector().setScaleFactor(config.getCascadeScaleFactor());
|
||||
MainApplication.detectorsList.put(devicenumber, image.getDetector());
|
||||
Logger.info("Camera "+cameraname+" started with device number "+devicenumber);
|
||||
} else image.setCameraStatus("Unable to Set Grabber");
|
||||
} else image.setCameraStatus("Camera not found, please check setting");
|
||||
}
|
||||
@@ -1045,7 +1129,6 @@ public class CaptureView {
|
||||
cam.getChildren().add(child);
|
||||
|
||||
cam.widthProperty().addListener(observable ->{
|
||||
//System.out.println("Width property, cam "+camid+" width="+cam.getWidth()+" height="+cam.getHeight());
|
||||
if (cam.getWidth()!=0) {
|
||||
if (cam.getHeight()!=0){
|
||||
AnchorPane.setTopAnchor(child, 0.0);
|
||||
@@ -1056,7 +1139,6 @@ public class CaptureView {
|
||||
}
|
||||
});
|
||||
cam.heightProperty().addListener(observable -> {
|
||||
//System.out.println("Height property, cam "+camid+" width="+cam.getWidth()+" height="+cam.getHeight());
|
||||
if (cam.getWidth()!=0) {
|
||||
if (cam.getHeight()!=0){
|
||||
AnchorPane.setTopAnchor(child, 0.0);
|
||||
@@ -1099,4 +1181,24 @@ public class CaptureView {
|
||||
Sqlite sql = new Sqlite();
|
||||
sql.Insert(prc);
|
||||
}
|
||||
|
||||
private void PlayFileWithoutEvent(String filename){
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(),filename)) {
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
Wait(500);
|
||||
audioPlayer.PlayFile(filename, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayFileWithEvent(String filename, PlaybackStatus ps){
|
||||
if (audioPlayer!=null && audioPlayer.isInited()){
|
||||
if (!Objects.equals(audioPlayer.getCurrentFile(),filename)) {
|
||||
audioPlayer.StopCurrentPlayback();
|
||||
Wait(500);
|
||||
audioPlayer.PlayFile(filename, ps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,14 @@ public class DetectorResult {
|
||||
Eyes.add(eye);
|
||||
}
|
||||
|
||||
// trouble di sini
|
||||
public void FaceRectangle(UMat mat){
|
||||
if (mat == null || mat.empty()) return;
|
||||
if (Face == null || Face.width() <= 0 || Face.height() <= 0) return;
|
||||
if (Face.x() < 0 || Face.y() < 0) return; // ignore negative coordinates
|
||||
if (Face.x() + Face.width() > mat.cols() || Face.y() + Face.height() > mat.rows()) return; // ignore out of bounds
|
||||
if (haveFace()){
|
||||
|
||||
try{
|
||||
rectangle(mat, Face, Scalar.GREEN, linethickness, linetype, lineshift);
|
||||
|
||||
@@ -33,9 +39,17 @@ public class DetectorResult {
|
||||
}
|
||||
}
|
||||
|
||||
// trouble di sini
|
||||
public void EyesRectangle(UMat mat){
|
||||
if (mat == null || mat.empty()) return;
|
||||
|
||||
if (haveEyes()){
|
||||
|
||||
for(Rect eye : Eyes){
|
||||
if (eye == null || eye.width() <= 0 || eye.height() <= 0) continue;
|
||||
if (eye.x() < 0 || eye.y() < 0) continue; // ignore negative coordinates
|
||||
if (eye.x() + eye.width() > mat.cols() || eye.y() + eye.height() > mat.rows()) continue; // ignore out of bounds
|
||||
|
||||
try{
|
||||
rectangle(mat, eye, Scalar.BLUE);
|
||||
|
||||
|
||||
@@ -10,71 +10,55 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Detectors {
|
||||
public static CascadeClassifier frontalfaceDetector;
|
||||
private static CascadeClassifier eyeDetector;
|
||||
private static CascadeClassifier profilefaceDetector;
|
||||
public CascadeClassifier frontalfaceDetector;
|
||||
private CascadeClassifier eyeDetector;
|
||||
private CascadeClassifier profilefaceDetector;
|
||||
|
||||
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;
|
||||
|
||||
public static void LoadAllDetectors(){
|
||||
private double scaleFactor = 1.05; // revisi 09/05/2025, dari nilai 1.05
|
||||
private final int minNeighbors = 3; // revisi 09/05/2025, dari nilai 3
|
||||
private final int flags = 0;
|
||||
private Size FaceminSize;
|
||||
private Size FacemaxSize;
|
||||
|
||||
public Detectors(){
|
||||
LoadFrontalFaceDetector();
|
||||
LoadEyeDetector();
|
||||
|
||||
LoadProfileFaceDetector();
|
||||
|
||||
}
|
||||
|
||||
private static void LoadFrontalFaceDetector(){
|
||||
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml");
|
||||
private void LoadFrontalFaceDetector(){
|
||||
// revisi 09/05/2025, dari filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml");
|
||||
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(){
|
||||
private 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(){
|
||||
private 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");
|
||||
}
|
||||
|
||||
@@ -83,27 +67,31 @@ public class Detectors {
|
||||
* @param graymat Mat in Gray Scale
|
||||
* @return List of Rect if face detected, otherwise empty list
|
||||
*/
|
||||
public static @NonNull List<DetectorResult> HaveFrontalFace(UMat graymat){
|
||||
public @NonNull List<DetectorResult> HaveFrontalFace(Mat graymat){
|
||||
List<DetectorResult> result = new ArrayList<>();
|
||||
//System.out.println("Detecting frontal from "+ graymat.size().width() + "x" + graymat.size().height());
|
||||
RectVector faces = DetectFrontalFace(graymat);
|
||||
if (faces!=null && faces.size()>0){
|
||||
|
||||
//System.out.println("faces size = " + faces.size());
|
||||
for(Rect face : faces.get()){
|
||||
RectVector eyes = DetectEye(graymat, face.width());
|
||||
DetectorResult dr = new DetectorResult();
|
||||
dr.setFace(face);
|
||||
if (eyes!=null && eyes.size()>=2){
|
||||
//System.out.println("eyes size = " + eyes.size());
|
||||
if (eyes.size()>=2){
|
||||
for(Rect eye : eyes.get()){
|
||||
if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye);
|
||||
if (SomeCodes.IsInsideRect(eye, face)) {
|
||||
dr.AddEye(eye);
|
||||
}
|
||||
}
|
||||
}
|
||||
result.add(dr);
|
||||
}
|
||||
}
|
||||
} //else System.out.println("faces size = 0");
|
||||
return result;
|
||||
}
|
||||
|
||||
public static @NonNull List<DetectorResult> HaveLeft45Face(UMat graymat){
|
||||
public @NonNull List<DetectorResult> HaveLeft45Face(Mat graymat){
|
||||
List<DetectorResult> result = new ArrayList<>();
|
||||
RectVector faces = DetectProfileFace(graymat);
|
||||
if (faces!=null && faces.size()>0){
|
||||
@@ -112,7 +100,7 @@ public class Detectors {
|
||||
RectVector eyes = DetectEye(graymat, face.width());
|
||||
DetectorResult dr = new DetectorResult();
|
||||
dr.setFace(face);
|
||||
if (eyes!=null && eyes.size()>0){
|
||||
if (eyes.size()>0){
|
||||
for(Rect eye : eyes.get()){
|
||||
if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye);
|
||||
}
|
||||
@@ -126,40 +114,38 @@ public class Detectors {
|
||||
|
||||
|
||||
|
||||
public static void setScaleFactor(double value){
|
||||
public void setScaleFactor(double value){
|
||||
if (scaleFactor!=value) scaleFactor = value;
|
||||
}
|
||||
|
||||
public static void setFaceMinSize(int value){
|
||||
public void setFaceMinSize(int value){
|
||||
if (FaceminSize!=null){
|
||||
if (FaceminSize.width()!=value || FaceminSize.height()!=value) {
|
||||
FaceminSize = new Size(value, value);
|
||||
//Logger.info("FaceMinSize changed to : " + FaceminSize.width());
|
||||
Logger.info("FaceMinSize changed to : " + FaceminSize.width());
|
||||
}
|
||||
} else {
|
||||
FaceminSize = new Size(value, value);
|
||||
//Logger.info("FaceMinSize created with value : " + FaceminSize.width());
|
||||
Logger.info("FaceMinSize created with value : " + FaceminSize.width());
|
||||
}
|
||||
|
||||
System.out.println("Face Min Size : " + FaceminSize.width());
|
||||
}
|
||||
|
||||
public static void setFaceMaxSize(int value){
|
||||
public void setFaceMaxSize(int value){
|
||||
if (FacemaxSize!=null){
|
||||
if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) {
|
||||
FacemaxSize = new Size(value, value);
|
||||
//Logger.info("FaceMaxSize changed to : " + FacemaxSize.width());
|
||||
Logger.info("FaceMaxSize changed to : " + FacemaxSize.width());
|
||||
}
|
||||
} else {
|
||||
FacemaxSize = new Size(value, value);
|
||||
//Logger.info("FaceMaxSize created with value : " + FacemaxSize.width());
|
||||
Logger.info("FaceMaxSize created with value : " + FacemaxSize.width());
|
||||
}
|
||||
|
||||
System.out.println("Face Max Size : " + FacemaxSize.width());
|
||||
}
|
||||
|
||||
|
||||
public static RectVector DetectProfileFace(UMat graymat){
|
||||
public RectVector DetectProfileFace(Mat graymat){
|
||||
return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
|
||||
}
|
||||
|
||||
@@ -168,7 +154,7 @@ public class Detectors {
|
||||
* @param graymat Mat in Gray Scale
|
||||
* @return RectVector if face detected, otherwise null
|
||||
*/
|
||||
public static RectVector DetectFrontalFace(UMat graymat){
|
||||
public RectVector DetectFrontalFace(Mat graymat){
|
||||
return Detect(graymat, frontalfaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
|
||||
}
|
||||
|
||||
@@ -178,38 +164,39 @@ public class Detectors {
|
||||
* @param graymat Mat in Gray Scale
|
||||
* @return RectVector if eye detected, otherwise null
|
||||
*/
|
||||
public static RectVector DetectEye(UMat graymat, int facewidth){
|
||||
public RectVector DetectEye(Mat graymat, int facewidth){
|
||||
//return Detect(graymat, eyeDetector);
|
||||
int minwidth = Math.max((int)(facewidth*0.25), 24);
|
||||
int minwidth = (int)(facewidth*0.2);
|
||||
int maxwidth = (int)(facewidth*0.4);
|
||||
Size minsize = new Size(minwidth, minwidth);
|
||||
Size maxsize = new Size(maxwidth, maxwidth);
|
||||
//System.out.println("Detecting Eye with minsize = " + minsize.width() + "x" + minsize.height() + ", maxsize = " + maxsize.width() + "x" + maxsize.height());
|
||||
return Detect(graymat, eyeDetector, scaleFactor, minNeighbors, flags, minsize, maxsize);
|
||||
}
|
||||
|
||||
@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 && graymat.channels()==1){
|
||||
if (!graymat.empty()){
|
||||
if (minSize!=null){
|
||||
if (maxSize!=null){
|
||||
private RectVector Detect(Mat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){
|
||||
if (detector!=null && !detector.empty()){
|
||||
if (graymat!=null && graymat.channels()==1 && !graymat.empty()){
|
||||
if (minSize!=null && maxSize!=null){
|
||||
if (minSize.width()< maxSize.width() && minSize.height() < maxSize.height()){
|
||||
if (graymat.cols()> minSize.width() && graymat.rows() > minSize.height()) {
|
||||
try {
|
||||
RectVector detected = new RectVector();
|
||||
detector.detectMultiScale(graymat, detected, scaleFactor, minNeighbors, flags, minSize, maxSize);
|
||||
// try defaulting minSize and maxSize
|
||||
detector.detectMultiScale(graymat, detected, scaleFactor, minNeighbors, flags, minSize, new Size());
|
||||
|
||||
return detected;
|
||||
} catch (Exception e) {
|
||||
System.out.println("Detectors Detect Error, Message : " + e.getMessage());
|
||||
}
|
||||
} else System.out.println("graymat is smaller than minSize");
|
||||
|
||||
}
|
||||
}
|
||||
} else System.out.println("minSize is larger than maxSize");
|
||||
} else System.out.println("minSize or maxSize is null");
|
||||
} else System.out.println("graymat is null, not 1 channel, or empty");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else System.out.println("detector empty");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package id.co.gtc.erhacam;
|
||||
|
||||
import Config.SomeCodes;
|
||||
import Database.PhotoCleaner;
|
||||
import SecureDongle.SecureDongle;
|
||||
import SecureDongle.SecureDongleEvent;
|
||||
import javafx.application.Application;
|
||||
@@ -14,15 +15,31 @@ import javafx.stage.Stage;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static Config.SomeCodes.ShowAlert;
|
||||
import static Config.SomeCodes.config;
|
||||
|
||||
|
||||
public class MainApplication extends Application {
|
||||
|
||||
final String version = "27082025-PRODUCTION-1.0.7";
|
||||
PhotoCleaner photoCleaner;
|
||||
public static Map<Integer, Detectors> detectorsList = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) throws IOException {
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
if (photoCleaner!=null) photoCleaner.Stop();
|
||||
System.out.println("ShutdownHook Checking running threads...");
|
||||
// Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
|
||||
// for(Thread thread : allThreads.keySet()){
|
||||
// System.out.println("Thread: " + thread.getName()+", State: " + thread.getState()+", Daemon: " + thread.isDaemon());
|
||||
// thread.interrupt();
|
||||
// }
|
||||
}));
|
||||
|
||||
|
||||
SecureDongle sd = new SecureDongle((short)0x4B30, (short)0xA66C, (short)0x3109, (short)0x37B1);
|
||||
@@ -37,7 +54,7 @@ public class MainApplication extends Application {
|
||||
Screen screen = Screen.getPrimary();
|
||||
Rectangle2D screenbound = screen.getBounds();
|
||||
Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight());
|
||||
stage.setTitle("MultiCam Capture App for ERHA 14042025-041");
|
||||
stage.setTitle("MultiCam Capture App for ERHA "+version);
|
||||
stage.setScene(scene);
|
||||
stage.setResizable(true);
|
||||
stage.setMaximized(true);
|
||||
@@ -49,13 +66,16 @@ public class MainApplication extends Application {
|
||||
Logger.info("Application closed");
|
||||
});
|
||||
SomeCodes.LoadQRReader();
|
||||
Detectors.LoadAllDetectors();
|
||||
// buang, pindah ke Cameradetail
|
||||
//Detectors.LoadAllDetectors();
|
||||
|
||||
stage.show();
|
||||
|
||||
AutoCloseAlert.init();
|
||||
|
||||
Logger.info("Application started");
|
||||
System.out.println("Application version : " + version+" started");
|
||||
System.out.println("Using "+(config.isProduction()?"Production":"Staging")+" API URL ");
|
||||
sd.setEvent(new SecureDongleEvent() {
|
||||
@Override
|
||||
public void onDongleMissing() {
|
||||
@@ -73,6 +93,9 @@ public class MainApplication extends Application {
|
||||
});
|
||||
sd.StartMonitor();
|
||||
|
||||
photoCleaner = new PhotoCleaner(90);
|
||||
photoCleaner.Start();
|
||||
|
||||
} 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");
|
||||
|
||||
@@ -45,17 +45,8 @@ public class PhotoRow {
|
||||
imgview.setStyle(borderstyle);
|
||||
imgview.setOnMouseClicked(e->{
|
||||
if (e.getClickCount()>=2){
|
||||
//System.out.println("Photo path: "+photopath);
|
||||
File ff = new File(photopath);
|
||||
// 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);
|
||||
|
||||
@@ -3,10 +3,7 @@ package id.co.gtc.erhacam;
|
||||
import FTP.FTPCheck;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.stage.DirectoryChooser;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.bytedeco.javacv.VideoInputFrameGrabber;
|
||||
@@ -49,6 +46,158 @@ public class SettingView {
|
||||
@FXML
|
||||
private CheckBox FlipCamera;
|
||||
|
||||
@FXML
|
||||
private TextField Cam1TopCrop;
|
||||
@FXML
|
||||
private TextField Cam1BottomCrop;
|
||||
@FXML
|
||||
private TextField Cam1LeftCrop;
|
||||
@FXML
|
||||
private TextField Cam1RightCrop;
|
||||
|
||||
@FXML
|
||||
private TextField Cam2TopCrop;
|
||||
@FXML
|
||||
private TextField Cam2BottomCrop;
|
||||
@FXML
|
||||
private TextField Cam2LeftCrop;
|
||||
@FXML
|
||||
private TextField Cam2RightCrop;
|
||||
|
||||
@FXML
|
||||
private TextField Cam3TopCrop;
|
||||
@FXML
|
||||
private TextField Cam3BottomCrop;
|
||||
@FXML
|
||||
private TextField Cam3LeftCrop;
|
||||
@FXML
|
||||
private TextField Cam3RightCrop;
|
||||
|
||||
@FXML
|
||||
private TextField Cam4TopCrop;
|
||||
@FXML
|
||||
private TextField Cam4BottomCrop;
|
||||
@FXML
|
||||
private TextField Cam4LeftCrop;
|
||||
@FXML
|
||||
private TextField Cam4RightCrop;
|
||||
|
||||
@FXML
|
||||
private TextField Cam5TopCrop;
|
||||
@FXML
|
||||
private TextField Cam5BottomCrop;
|
||||
@FXML
|
||||
private TextField Cam5LeftCrop;
|
||||
@FXML
|
||||
private TextField Cam5RightCrop;
|
||||
|
||||
@FXML
|
||||
private RadioButton apiStaging;
|
||||
@FXML
|
||||
private RadioButton apiProduction;
|
||||
|
||||
@FXML
|
||||
public void changeAPIClick(){
|
||||
if (apiStaging.isSelected()){
|
||||
config.setAPI(false);
|
||||
config.Save();
|
||||
ShowAlert(Alert.AlertType.INFORMATION, "API Change", "API Change", "API Staging is selected, API will use Staging URL");
|
||||
} else if (apiProduction.isSelected()){
|
||||
config.setAPI(true);
|
||||
config.Save();
|
||||
ShowAlert(Alert.AlertType.INFORMATION, "API Change", "API Change", "API Production is selected, API will use Production URL");
|
||||
} else {
|
||||
ShowAlert(Alert.AlertType.ERROR, "API Change Error", "API Change Error", "Please select API Staging or API Production");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void ApplyCropClick(){
|
||||
// Apply crop settings for each camera
|
||||
boolean[] all_correct = {true};
|
||||
|
||||
CheckTextField(Cam1TopCrop,all_correct);
|
||||
CheckTextField(Cam1BottomCrop,all_correct);
|
||||
CheckTextField(Cam1LeftCrop,all_correct);
|
||||
CheckTextField(Cam1RightCrop,all_correct);
|
||||
CheckTextField(Cam2TopCrop,all_correct);
|
||||
CheckTextField(Cam2BottomCrop,all_correct);
|
||||
CheckTextField(Cam2LeftCrop,all_correct);
|
||||
CheckTextField(Cam2RightCrop,all_correct);
|
||||
CheckTextField(Cam3TopCrop,all_correct);
|
||||
CheckTextField(Cam3BottomCrop,all_correct);
|
||||
CheckTextField(Cam3LeftCrop,all_correct);
|
||||
CheckTextField(Cam3RightCrop,all_correct);
|
||||
CheckTextField(Cam4TopCrop,all_correct);
|
||||
CheckTextField(Cam4BottomCrop,all_correct);
|
||||
CheckTextField(Cam4LeftCrop,all_correct);
|
||||
CheckTextField(Cam4RightCrop,all_correct);
|
||||
CheckTextField(Cam5TopCrop,all_correct);
|
||||
CheckTextField(Cam5BottomCrop,all_correct);
|
||||
CheckTextField(Cam5LeftCrop,all_correct);
|
||||
CheckTextField(Cam5RightCrop,all_correct);
|
||||
|
||||
if (all_correct[0]){
|
||||
config.setCam1TopCrop(Cam1TopCrop.getText());
|
||||
config.setCam1BottomCrop(Cam1BottomCrop.getText());
|
||||
config.setCam1LeftCrop(Cam1LeftCrop.getText());
|
||||
config.setCam1RightCrop(Cam1RightCrop.getText());
|
||||
config.setCam2TopCrop(Cam2TopCrop.getText());
|
||||
config.setCam2BottomCrop(Cam2BottomCrop.getText());
|
||||
config.setCam2LeftCrop(Cam2LeftCrop.getText());
|
||||
config.setCam2RightCrop(Cam2RightCrop.getText());
|
||||
config.setCam3TopCrop(Cam3TopCrop.getText());
|
||||
config.setCam3BottomCrop(Cam3BottomCrop.getText());
|
||||
config.setCam3LeftCrop(Cam3LeftCrop.getText());
|
||||
config.setCam3RightCrop(Cam3RightCrop.getText());
|
||||
config.setCam4TopCrop(Cam4TopCrop.getText());
|
||||
config.setCam4BottomCrop(Cam4BottomCrop.getText());
|
||||
config.setCam4LeftCrop(Cam4LeftCrop.getText());
|
||||
config.setCam4RightCrop(Cam4RightCrop.getText());
|
||||
config.setCam5TopCrop(Cam5TopCrop.getText());
|
||||
config.setCam5BottomCrop(Cam5BottomCrop.getText());
|
||||
config.setCam5LeftCrop(Cam5LeftCrop.getText());
|
||||
config.setCam5RightCrop(Cam5RightCrop.getText());
|
||||
|
||||
config.Save();
|
||||
} else {
|
||||
ShowAlert(Alert.AlertType.ERROR, "Crop Setting Error", "Crop Setting Error", "Please check your crop settings, some values are invalid");
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckTextField(TextField tf, boolean[] value){
|
||||
if (ValidCropValue(tf)){
|
||||
tf.setStyle("");
|
||||
} else {
|
||||
tf.setStyle("-fx-border-color: red;");
|
||||
value[0] = false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean ValidCropValue(TextField tf){
|
||||
if (tf != null){
|
||||
double value;
|
||||
String name = tf.getId();
|
||||
try {
|
||||
value = Double.parseDouble(tf.getText());
|
||||
if (value >= 0.0){
|
||||
if (name.contains("Top")){
|
||||
return value <= config.getTopcropmax();
|
||||
} else if (name.contains("Bottom")){
|
||||
return value <= config.getBottomcropmax();
|
||||
} else if (name.contains("Left")){
|
||||
return value <= config.getLeftcropmax();
|
||||
} else if (name.contains("Right")){
|
||||
return value <= config.getRightcropmax();
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
final FileChooser jfc = new FileChooser();
|
||||
@@ -108,9 +257,20 @@ public class SettingView {
|
||||
config.setCascadeScaleFactor(scale);
|
||||
config.Save();
|
||||
|
||||
Detectors.setFaceMaxSize(max);
|
||||
Detectors.setFaceMinSize(min);
|
||||
Detectors.setScaleFactor(scale);
|
||||
if (MainApplication.detectorsList!=null){
|
||||
MainApplication.detectorsList.forEach((i,d)-> {
|
||||
d.setFaceMaxSize(max);
|
||||
d.setFaceMinSize(min);
|
||||
d.setScaleFactor(scale);
|
||||
});
|
||||
|
||||
} else {
|
||||
Logger.error("MainApplication.detectorsList is null, unable to set cascade settings");
|
||||
}
|
||||
|
||||
// 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");
|
||||
@@ -144,13 +304,11 @@ public class SettingView {
|
||||
}
|
||||
|
||||
MirrorCamera.selectedProperty().addListener(((observable, oldValue, newValue) -> {
|
||||
System.out.println("Mirror option changed to : "+newValue);
|
||||
config.setMirrorCamera(newValue);
|
||||
config.Save();
|
||||
}));
|
||||
|
||||
FlipCamera.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
System.out.println("Flip option changed to : "+newValue);
|
||||
config.setFlipCamera(newValue);
|
||||
config.Save();
|
||||
});
|
||||
@@ -200,8 +358,31 @@ public class SettingView {
|
||||
|
||||
MirrorCamera.setSelected(config.isMirrorCamera());
|
||||
FlipCamera.setSelected(config.isFlipCamera());
|
||||
apiStaging.setSelected(!config.isProduction());
|
||||
apiProduction.setSelected(config.isProduction());
|
||||
|
||||
TextFieldSetText(Sharpness,String.valueOf(config.getSharpnessThreshold()));
|
||||
TextFieldSetText(Cam1TopCrop,String.valueOf(config.getCam1TopCrop()));
|
||||
TextFieldSetText(Cam1BottomCrop,String.valueOf(config.getCam1BottomCrop()));
|
||||
TextFieldSetText(Cam1LeftCrop,String.valueOf(config.getCam1LeftCrop()));
|
||||
TextFieldSetText(Cam1RightCrop,String.valueOf(config.getCam1RightCrop()));
|
||||
TextFieldSetText(Cam2TopCrop,String.valueOf(config.getCam2TopCrop()));
|
||||
TextFieldSetText(Cam2BottomCrop,String.valueOf(config.getCam2BottomCrop()));
|
||||
TextFieldSetText(Cam2LeftCrop,String.valueOf(config.getCam2LeftCrop()));
|
||||
TextFieldSetText(Cam2RightCrop,String.valueOf(config.getCam2RightCrop()));
|
||||
TextFieldSetText(Cam3TopCrop,String.valueOf(config.getCam3TopCrop()));
|
||||
TextFieldSetText(Cam3BottomCrop,String.valueOf(config.getCam3BottomCrop()));
|
||||
TextFieldSetText(Cam3LeftCrop,String.valueOf(config.getCam3LeftCrop()));
|
||||
TextFieldSetText(Cam3RightCrop,String.valueOf(config.getCam3RightCrop()));
|
||||
TextFieldSetText(Cam4TopCrop,String.valueOf(config.getCam4TopCrop()));
|
||||
TextFieldSetText(Cam4BottomCrop,String.valueOf(config.getCam4BottomCrop()));
|
||||
TextFieldSetText(Cam4LeftCrop,String.valueOf(config.getCam4LeftCrop()));
|
||||
TextFieldSetText(Cam4RightCrop,String.valueOf(config.getCam4RightCrop()));
|
||||
TextFieldSetText(Cam5TopCrop,String.valueOf(config.getCam5TopCrop()));
|
||||
TextFieldSetText(Cam5BottomCrop,String.valueOf(config.getCam5BottomCrop()));
|
||||
TextFieldSetText(Cam5LeftCrop,String.valueOf(config.getCam5LeftCrop()));
|
||||
TextFieldSetText(Cam5RightCrop,String.valueOf(config.getCam5RightCrop()));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ module id.co.gtc.erhacam {
|
||||
requires java.sql;
|
||||
requires javafx.graphics;
|
||||
requires java.net.http;
|
||||
requires org.tinylog.impl;
|
||||
|
||||
|
||||
opens id.co.gtc.erhacam to javafx.fxml;
|
||||
|
||||
@@ -39,7 +39,6 @@ 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;
|
||||
@@ -776,11 +775,11 @@ public class Cameradetail_Arducam {
|
||||
* @return true if face detected, otherwise false
|
||||
*/
|
||||
private RectVector DetectFace(UMat graymat){
|
||||
if (frontalfaceDetector!=null){
|
||||
val face = new RectVector();
|
||||
frontalfaceDetector.detectMultiScale(graymat, face);
|
||||
return face;
|
||||
}
|
||||
// if (frontalfaceDetector!=null){
|
||||
// val face = new RectVector();
|
||||
// frontalfaceDetector.detectMultiScale(graymat, face);
|
||||
// return face;
|
||||
// }
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,20 +30,23 @@
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<GridPane fx:id="camerassetting" prefHeight="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" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="40.0" prefWidth="100.0" />
|
||||
<ColumnConstraints percentWidth="40.0" />
|
||||
<ColumnConstraints percentWidth="40.0" />
|
||||
<ColumnConstraints percentWidth="20.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane>
|
||||
<AnchorPane>
|
||||
<children>
|
||||
<GridPane fx:id="cameraselection" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="25.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 percentWidth="25" />
|
||||
<ColumnConstraints percentWidth="50" />
|
||||
<ColumnConstraints percentWidth="25" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
@@ -53,124 +56,148 @@
|
||||
<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>
|
||||
<children>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label layoutX="30.0" layoutY="12.0" prefHeight="40.8" prefWidth="87.2" text="Left 90" 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="44.0" layoutY="12.0" prefHeight="40.8" prefWidth="87.2" text="Left 45" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
|
||||
<Label layoutX="30.0" layoutY="12.0" prefHeight="40.8" prefWidth="87.2" text="Cam 1" 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="30.0" layoutY="6.0" prefHeight="40.8" prefWidth="87.2" text="Center" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
|
||||
<Label layoutX="44.0" layoutY="12.0" prefHeight="40.8" prefWidth="87.2" text="Cam 2" 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="24.0" layoutY="6.0" prefHeight="40.0" prefWidth="87.2" text="Right 45" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
|
||||
<Label layoutX="30.0" layoutY="6.0" prefHeight="40.8" prefWidth="87.2" text="Cam 3" 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="36.0" layoutY="11.0" prefHeight="40.0" prefWidth="87.2" text="Right 90" 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>
|
||||
<ComboBox fx:id="CameraLeft90" layoutX="54.0" layoutY="8.0" prefHeight="40.8" prefWidth="408.0" 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="1" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<ComboBox fx:id="CameraLeft45" layoutX="26.0" layoutY="14.0" prefHeight="40.8" prefWidth="408.0" 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="1" GridPane.rowIndex="2">
|
||||
<children>
|
||||
<ComboBox fx:id="CameraCenter" layoutX="88.0" layoutY="8.0" prefHeight="40.8" prefWidth="408.0" 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="1" GridPane.rowIndex="3">
|
||||
<children>
|
||||
<ComboBox fx:id="CameraRight45" layoutX="54.0" layoutY="8.0" prefHeight="40.0" prefWidth="408.0" 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="1" GridPane.rowIndex="4">
|
||||
<children>
|
||||
<ComboBox fx:id="CameraRight90" layoutX="75.0" layoutY="1.0" prefHeight="40.0" prefWidth="408.0" 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">
|
||||
<children>
|
||||
<Button layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraLeft90" prefHeight="40.8" prefWidth="88.0" text="Apply" 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="22.0" layoutY="2.0" mnemonicParsing="false" onAction="#ApplyCameraLeft45" prefHeight="40.8" prefWidth="88.0" text="Apply" 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="18.0" layoutY="2.0" mnemonicParsing="false" onAction="#ApplyCameraFront" prefHeight="40.8" prefWidth="88.0" text="Apply" 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="22.0" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraRight45" prefHeight="40.0" prefWidth="88.0" text="Apply" 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 layoutX="22.0" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraRight90" prefHeight="40.0" prefWidth="88.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
|
||||
<Label layoutX="24.0" layoutY="6.0" prefHeight="40.0" prefWidth="87.2" text="Cam 4" 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">
|
||||
<children>
|
||||
<Label layoutX="60.0" prefHeight="40.0" prefWidth="175.0" text="Mirror Camera" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
|
||||
<Label layoutX="36.0" layoutY="11.0" prefHeight="40.0" prefWidth="87.2" text="Cam 5" 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" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<ComboBox fx:id="CameraLeft90" layoutX="54.0" layoutY="8.0" prefHeight="40.8" prefWidth="408.0" 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="1" GridPane.rowIndex="2">
|
||||
<children>
|
||||
<ComboBox fx:id="CameraLeft45" layoutX="26.0" layoutY="14.0" prefHeight="40.8" prefWidth="408.0" 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="1" GridPane.rowIndex="3">
|
||||
<children>
|
||||
<ComboBox fx:id="CameraCenter" layoutX="88.0" layoutY="8.0" prefHeight="40.8" prefWidth="408.0" 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="1" GridPane.rowIndex="4">
|
||||
<children>
|
||||
<ComboBox fx:id="CameraRight45" layoutX="54.0" layoutY="8.0" prefHeight="40.0" prefWidth="408.0" 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="1" GridPane.rowIndex="5">
|
||||
<children>
|
||||
<CheckBox fx:id="MirrorCamera" layoutX="30.0" layoutY="6.0" mnemonicParsing="false" prefHeight="40.0" prefWidth="175.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
|
||||
<ComboBox fx:id="CameraRight90" layoutX="75.0" layoutY="1.0" prefHeight="40.0" prefWidth="408.0" 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 layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraLeft90" prefHeight="40.8" prefWidth="88.0" text="Apply" 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="22.0" layoutY="2.0" mnemonicParsing="false" onAction="#ApplyCameraLeft45" prefHeight="40.8" prefWidth="88.0" text="Apply" 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="18.0" layoutY="2.0" mnemonicParsing="false" onAction="#ApplyCameraFront" prefHeight="40.8" prefWidth="88.0" text="Apply" 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 layoutX="22.0" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraRight45" prefHeight="40.0" prefWidth="88.0" text="Apply" 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="5">
|
||||
<children>
|
||||
<Button layoutX="22.0" layoutY="8.0" mnemonicParsing="false" onAction="#ApplyCameraRight90" prefHeight="40.0" prefWidth="88.0" text="Apply" 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.rowIndex="6">
|
||||
<children>
|
||||
<Label prefHeight="40.0" prefWidth="175.0" text="Flip Camera" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
|
||||
<Label layoutX="60.0" prefHeight="40.0" prefWidth="175.0" text="Mirror" 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" GridPane.rowIndex="6">
|
||||
<children>
|
||||
<CheckBox fx:id="FlipCamera" mnemonicParsing="false" prefHeight="40.0" prefWidth="175.0" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
|
||||
<CheckBox fx:id="MirrorCamera" layoutX="30.0" layoutY="6.0" mnemonicParsing="false" prefHeight="40.0" prefWidth="175.0" 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.rowIndex="7">
|
||||
<children>
|
||||
<Label layoutX="32.0" layoutY="19.0" prefHeight="37.0" prefWidth="92.0" text="Sharpness Threshold" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
|
||||
<Label prefHeight="40.0" prefWidth="175.0" text="Flip" 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" GridPane.rowIndex="7">
|
||||
<children>
|
||||
<CheckBox fx:id="FlipCamera" mnemonicParsing="false" prefHeight="40.0" prefWidth="175.0" 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">
|
||||
<children>
|
||||
<Label layoutX="32.0" layoutY="19.0" prefHeight="37.0" prefWidth="92.0" text="Sharpness" 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="Sharpness" layoutX="35.0" layoutY="2.0" prefHeight="37.0" prefWidth="368.0" promptText="if Sharpness below this number, photos considered as blurred" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane GridPane.columnIndex="2" GridPane.rowIndex="7">
|
||||
<AnchorPane GridPane.columnIndex="2">
|
||||
<children>
|
||||
<Button mnemonicParsing="false" onAction="#SharpnessApply" prefHeight="37.0" prefWidth="92.0" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane GridPane.rowIndex="8">
|
||||
<children>
|
||||
<Label text="API Type" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane GridPane.columnIndex="1" GridPane.rowIndex="8">
|
||||
<children>
|
||||
<RadioButton fx:id="apiStaging" layoutX="14.0" layoutY="8.0" mnemonicParsing="false" text="Staging" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.topAnchor="2.0">
|
||||
<toggleGroup>
|
||||
<ToggleGroup fx:id="apiselect" />
|
||||
</toggleGroup></RadioButton>
|
||||
<RadioButton fx:id="apiProduction" layoutX="103.0" layoutY="11.0" mnemonicParsing="false" text="Production" toggleGroup="$apiselect" AnchorPane.bottomAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane GridPane.columnIndex="2" GridPane.rowIndex="8">
|
||||
<children>
|
||||
<Button mnemonicParsing="false" onAction="#changeAPIClick" prefHeight="33.6" prefWidth="102.4" text="Apply" AnchorPane.bottomAnchor="2.0" AnchorPane.leftAnchor="2.0" AnchorPane.rightAnchor="2.0" AnchorPane.topAnchor="2.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
<GridPane GridPane.columnIndex="1">
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane maxWidth="400.0" GridPane.columnIndex="2">
|
||||
<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" prefWidth="100.0" />
|
||||
<ColumnConstraints prefWidth="300" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
@@ -190,14 +217,10 @@
|
||||
</AnchorPane>
|
||||
<AnchorPane GridPane.rowIndex="1">
|
||||
<children>
|
||||
<ScrollPane layoutX="5.0" 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">
|
||||
<GridPane prefHeight="200.0" prefWidth="300.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.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 percentWidth="70.0" />
|
||||
<ColumnConstraints percentWidth="30.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES" />
|
||||
@@ -207,27 +230,27 @@
|
||||
<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" />
|
||||
<Label prefHeight="40.0" 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" />
|
||||
<Label prefHeight="40.0" 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" />
|
||||
<Label prefHeight="40.0" 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" />
|
||||
<TextField fx:id="cascadeScaleFactor" alignment="CENTER" prefHeight="40.0" prefWidth="175.0" 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" />
|
||||
<TextField fx:id="cascadeMinSize" alignment="CENTER" prefHeight="40.0" prefWidth="175.0" 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">
|
||||
@@ -239,13 +262,252 @@
|
||||
</GridPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</content>
|
||||
</ScrollPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane GridPane.columnIndex="1">
|
||||
<children>
|
||||
<GridPane fx:id="cropsetting" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="50.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<GridPane layoutX="-21.0" layoutY="-31.0" prefHeight="30.4" prefWidth="399.2" 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 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>
|
||||
<children>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label alignment="CENTER" layoutX="36.0" layoutY="6.0" prefHeight="30.4" prefWidth="100.0" text="Top" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<Label alignment="CENTER" text="Bottom" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
|
||||
<children>
|
||||
<Label alignment="CENTER" layoutX="7.0" layoutY="8.0" text="Left" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
</children></AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
|
||||
<children>
|
||||
<Label alignment="CENTER" layoutX="36.0" layoutY="8.0" text="Right" 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" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<GridPane prefHeight="50.4" prefWidth="399.2" 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 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>
|
||||
<children>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<TextField fx:id="Cam1TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<TextField fx:id="Cam1BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
|
||||
<children>
|
||||
<TextField fx:id="Cam1LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
|
||||
<children>
|
||||
<TextField fx:id="Cam1RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
|
||||
<children>
|
||||
<GridPane layoutX="-27.0" layoutY="-31.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 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>
|
||||
<children>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<TextField fx:id="Cam2TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<TextField fx:id="Cam2BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
|
||||
<children>
|
||||
<TextField fx:id="Cam2LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
|
||||
<children>
|
||||
<TextField fx:id="Cam2RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children></AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="3">
|
||||
<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" 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>
|
||||
<children>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<TextField fx:id="Cam3TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<TextField fx:id="Cam3BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
|
||||
<children>
|
||||
<TextField fx:id="Cam3LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
|
||||
<children>
|
||||
<TextField fx:id="Cam3RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children></AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="4">
|
||||
<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" 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>
|
||||
<children>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<TextField fx:id="Cam4TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<TextField fx:id="Cam4BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
|
||||
<children>
|
||||
<TextField fx:id="Cam4LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
|
||||
<children>
|
||||
<TextField fx:id="Cam4RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children></AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="5">
|
||||
<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" 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>
|
||||
<children>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
||||
<children>
|
||||
<TextField fx:id="Cam5TopCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<TextField fx:id="Cam5BottomCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">
|
||||
<children>
|
||||
<TextField fx:id="Cam5LeftCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3">
|
||||
<children>
|
||||
<TextField fx:id="Cam5RightCrop" alignment="CENTER" promptText="crop percent" text="10" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="3.0" AnchorPane.rightAnchor="3.0" AnchorPane.topAnchor="3.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children></AnchorPane>
|
||||
<AnchorPane GridPane.rowIndex="6">
|
||||
<children>
|
||||
<Button fx:id="btnApplyCrop" mnemonicParsing="false" onAction="#ApplyCropClick" prefHeight="40.0" prefWidth="399.2" text="Apply Crop" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children>
|
||||
</AnchorPane>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
voices/pengambilan_berhasil_tunggu_lobby.wav
Normal file
BIN
voices/pengambilan_berhasil_tunggu_lobby.wav
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user