Trial 04022025

This commit is contained in:
2025-02-04 08:48:28 +07:00
parent a60fe56510
commit 29884c03ed
24 changed files with 16423 additions and 158594 deletions

View File

@@ -1,15 +1,15 @@
#Mon Jan 20 17:42:44 WIB 2025 #Thu Jan 30 14:56:00 WIB 2025
AudioPhase1=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase1.mp3 AudioPhase1=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase1.mp3
AudioPhase2=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase2.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 AudioPhase3=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase3.mp3
AudioPhase4=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase4.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 AudioPhase5=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase5.mp3
CameraCenter=OBSBOT Meet 2 StreamCamera CameraCenter=OBSBOT Meet 2 StreamCamera
CameraConfigCenter={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true} CameraConfigCenter={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigLeft45={"Brightness"\:37.58730158730158,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true} CameraConfigLeft45={"Brightness"\:37.58730158730158,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigLeft90={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true} CameraConfigLeft90={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigRight45={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true} CameraConfigRight45={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraConfigRight90={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:0.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true} CameraConfigRight90={"Brightness"\:0.0,"Contrast"\:32.0,"Saturation"\:64.0,"Hue"\:0.0,"Gain"\:1.0,"Exposure"\:157.0,"Sharpness"\:3.0,"Gamma"\:100.0,"AutoExposure"\:true,"AutoFocus"\:true,"AutoWhiteBalance"\:true}
CameraLeft45=OBSBOT Meet 2 StreamCamera CameraLeft45=OBSBOT Meet 2 StreamCamera
CameraLeft90=OBSBOT Meet 2 StreamCamera CameraLeft90=OBSBOT Meet 2 StreamCamera
CameraRight45=OBSBOT Meet 2 StreamCamera CameraRight45=OBSBOT Meet 2 StreamCamera

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,7 +1,7 @@
package Config; package Config;
import id.co.gtc.erhacam.Detectors;
import lombok.Getter; import lombok.Getter;
import lombok.val;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.io.File; import java.io.File;
@@ -40,6 +40,11 @@ public class ConfigFile {
private String PhotoDirectory; private String PhotoDirectory;
private @Getter double cascadeScaleFactor;
private @Getter int cascadeMinNeighbors;
private @Getter int cascadeMinSize;
private @Getter int cascadeMaxSize;
private boolean needsave = false; private boolean needsave = false;
public ConfigFile(){ public ConfigFile(){
@@ -48,6 +53,34 @@ public class ConfigFile {
Load(); Load();
} }
public void setCascadeScaleFactor(double value){
if (cascadeScaleFactor != value){
cascadeScaleFactor = value;
needsave = true;
}
}
public void setCascadeMinNeighbors(int value){
if (cascadeMinNeighbors != value){
cascadeMinNeighbors = value;
needsave = true;
}
}
public void setCascadeMinSize(int value){
if (cascadeMinSize != value){
cascadeMinSize = value;
needsave = true;
}
}
public void setCascadeMaxSize(int value){
if (cascadeMaxSize != value){
cascadeMaxSize = value;
needsave = true;
}
}
public void SetPhotoDirectory(String path){ public void SetPhotoDirectory(String path){
if (ValidString(path)){ if (ValidString(path)){
if (!path.equals(PhotoDirectory)){ if (!path.equals(PhotoDirectory)){
@@ -528,6 +561,11 @@ public class ConfigFile {
if (prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()) == null) allcorrect = false; if (prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()) == null) allcorrect = false;
if (prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()) == null) allcorrect = false; if (prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()) == null) allcorrect = false;
if (prop.getProperty("cascadeScaleFactor") == null) allcorrect = false;
if (prop.getProperty("cascadeMinNeighbors") == null) allcorrect = false;
if (prop.getProperty("cascadeMinSize") == null) allcorrect = false;
if (prop.getProperty("cascadeMaxSize") == null) allcorrect = false;
if (allcorrect){ if (allcorrect){
AudioPhase1 = prop.getProperty("AudioPhase1"); AudioPhase1 = prop.getProperty("AudioPhase1");
AudioPhase2 = prop.getProperty("AudioPhase2"); AudioPhase2 = prop.getProperty("AudioPhase2");
@@ -554,6 +592,15 @@ public class ConfigFile {
ConfigRight45 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()), CameraConfig.class); ConfigRight45 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()), CameraConfig.class);
ConfigRight90 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()), CameraConfig.class); ConfigRight90 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()), CameraConfig.class);
cascadeScaleFactor = toDouble(prop.getProperty("cascadeScaleFactor"));
cascadeMinNeighbors = toInt(prop.getProperty("cascadeMinNeighbors"));
cascadeMinSize = toInt(prop.getProperty("cascadeMinSize"));
cascadeMaxSize = toInt(prop.getProperty("cascadeMaxSize"));
Detectors.setMaxSize(cascadeMaxSize);
Detectors.setMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
Logger.info("Config Loaded"); Logger.info("Config Loaded");
return; return;
} else { } else {
@@ -568,6 +615,14 @@ public class ConfigFile {
CreateDefault(); CreateDefault();
} }
private double toDouble(String cascadeScaleFactor) {
try{
return Double.parseDouble(cascadeScaleFactor);
} catch (Exception e){
return 1.1;
}
}
private void CreateDefault(){ private void CreateDefault(){
AudioPhase1 = Path.of(currentDirectory, "audio", "phase1.mp3").toString(); AudioPhase1 = Path.of(currentDirectory, "audio", "phase1.mp3").toString();
AudioPhase2 = Path.of(currentDirectory, "audio", "phase2.mp3").toString(); AudioPhase2 = Path.of(currentDirectory, "audio", "phase2.mp3").toString();
@@ -590,6 +645,13 @@ public class ConfigFile {
SetDefaultCameraConfig(ConfigCenter); SetDefaultCameraConfig(ConfigCenter);
SetDefaultCameraConfig(ConfigRight45); SetDefaultCameraConfig(ConfigRight45);
SetDefaultCameraConfig(ConfigRight90); SetDefaultCameraConfig(ConfigRight90);
cascadeScaleFactor = 1.1;
cascadeMinNeighbors = 3;
cascadeMinSize = 200;
cascadeMaxSize = 400;
Detectors.setMaxSize(cascadeMaxSize);
Detectors.setMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
Logger.info("Default Config Created"); Logger.info("Default Config Created");
needsave = true; needsave = true;
Save(); Save();
@@ -640,6 +702,11 @@ public class ConfigFile {
prop.setProperty(CameraConfigEnum.CameraConfigRight45.toString(), gson.toJson(ConfigRight45)); prop.setProperty(CameraConfigEnum.CameraConfigRight45.toString(), gson.toJson(ConfigRight45));
prop.setProperty(CameraConfigEnum.CameraConfigRight90.toString(), gson.toJson(ConfigRight90)); prop.setProperty(CameraConfigEnum.CameraConfigRight90.toString(), gson.toJson(ConfigRight90));
prop.setProperty("cascadeScaleFactor", String.valueOf(cascadeScaleFactor));
prop.setProperty("cascadeMinNeighbors", String.valueOf(cascadeMinNeighbors));
prop.setProperty("cascadeMinSize", String.valueOf(cascadeMinSize));
prop.setProperty("cascadeMaxSize", String.valueOf(cascadeMaxSize));
try{ try{
prop.store(new FileOutputStream(Path.of(currentDirectory, "config.properties").toString()), null); prop.store(new FileOutputStream(Path.of(currentDirectory, "config.properties").toString()), null);
Logger.info("Config Saved"); Logger.info("Config Saved");

View File

@@ -11,7 +11,6 @@ import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc; import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat; import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Size; import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;

View File

@@ -38,13 +38,13 @@ import java.awt.image.DataBufferByte;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static Config.SomeCodes.*; import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.*;
import static org.bytedeco.opencv.global.opencv_core.CV_8UC3; import static org.bytedeco.opencv.global.opencv_core.CV_8UC3;
import static org.bytedeco.opencv.global.opencv_core.mean; import static org.bytedeco.opencv.global.opencv_core.mean;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite; import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
@@ -60,6 +60,7 @@ public class Cameradetail {
} else { } else {
System.out.println("CUDA is not available"); System.out.println("CUDA is not available");
} }
} }
private final AtomicBoolean Capturing = new AtomicBoolean(false); private final AtomicBoolean Capturing = new AtomicBoolean(false);
private final AtomicBoolean TakingPhoto = new AtomicBoolean(false); private final AtomicBoolean TakingPhoto = new AtomicBoolean(false);
@@ -684,49 +685,116 @@ public class Cameradetail {
} }
} }
if (use_face){ if (use_face){
RectVector face = DetectFace(graymat);
if (face!=null && face.size()>0){ List<Rect> frontalfaces = Detectors.HaveFrontalFace(graymat);
// ada muka if (!frontalfaces.isEmpty()){
if (event!=null) event.onFaceDetector(true, BestSize.width(), BestSize.height()); if (event!=null) event.onFrontalFaceDetector(true, BestSize.width(), BestSize.height());
for(int i=0; i<face.size(); i++){ for(Rect rect : frontalfaces){
Rect rect = face.get(i);
rectangle(LiveMat, rect, Scalar.GREEN); rectangle(LiveMat, rect, Scalar.GREEN);
} }
// kalau detect muka, baru coba detect mata
RectVector eye = DetectEye(graymat);
if (eye!=null && eye.size()>=2){
// ada mata
if (eye_was_closed.get()){
eye_was_closed.set(false);
if (blink_counter.get()>=2){
blink_counter.set(0);
if (event!=null) event.onBlink(blink_counter.get());
}
}
if (event!=null) event.onEyeDetector(true, BestSize.width(), BestSize.height());
for(int i=0; i<eye.size(); i++){
Rect rect = eye.get(i);
rectangle(LiveMat, rect, Scalar.RED);
}
} else {
// mata tidak ada
if (!eye_was_closed.get()){
eye_was_closed.set(true);
blink_counter.incrementAndGet();
}
if (event!=null) event.onEyeDetector(false, BestSize.width(), BestSize.height());
}
} else { } else {
eye_was_closed.set(false); if (event!=null) event.onFrontalFaceDetector(false, BestSize.width(), BestSize.height());
blink_counter.set(0);
// tidak ada muka, tidak ada mata
if (event!=null) event.onFaceDetector(false, BestSize.width(), BestSize.height());
if (event!=null) event.onEyeDetector(false, BestSize.width(), BestSize.height());
} }
List<Rect> Left45Faces = Detectors.HaveLeft45Face(graymat);
if (!Left45Faces.isEmpty()){
if (event!=null){
event.onLeftEyeDetector(true, BestSize.width(), BestSize.height());
event.onProfileFaceDetector(true, BestSize.width(), BestSize.height());
}
for(Rect rect : Left45Faces){
rectangle(LiveMat, rect, Scalar.BLUE);
}
} else {
if (event!=null) {
event.onLeftEyeDetector(false, BestSize.width(), BestSize.height());
event.onProfileFaceDetector(false, BestSize.width(), BestSize.height());
}
}
List<Rect> Right45Faces = Detectors.HaveRight45Face(graymat);
if (!Right45Faces.isEmpty()){
if (event!=null){
event.onRightEyeDetector(true, BestSize.width(), BestSize.height());
event.onProfileFaceDetector(true, BestSize.width(), BestSize.height());
}
for(Rect rect : Right45Faces){
rectangle(LiveMat, rect, Scalar.BLUE);
}
} else {
if (event!=null) {
event.onRightEyeDetector(false, BestSize.width(), BestSize.height());
event.onProfileFaceDetector(false, BestSize.width(), BestSize.height());
}
}
// List<Rect> Left90Faces = Detectors.HaveLeft90Face(graymat);
// if (!Left90Faces.isEmpty()){
// if (event!=null){
// event.onLeftEyeDetector(true, BestSize.width(), BestSize.height());
// event.onLeftEarDetector(true, BestSize.width(), BestSize.height());
// }
// for(Rect rect : Left90Faces){
// rectangle(LiveMat, rect, Scalar.YELLOW);
// }
// } else {
// if (event!=null) {
// event.onLeftEyeDetector(false, BestSize.width(), BestSize.height());
// event.onLeftEarDetector(false, BestSize.width(), BestSize.height());
// }
// }
//
// List<Rect> Right90Faces = Detectors.HaveRight90Face(graymat);
// if (!Right90Faces.isEmpty()){
// if (event!=null){
// event.onRightEyeDetector(true, BestSize.width(), BestSize.height());
// event.onRightEarDetector(true, BestSize.width(), BestSize.height());
// }
// for(Rect rect : Right90Faces){
// rectangle(LiveMat, rect, Scalar.YELLOW);
// }
// } else {
// if (event!=null) {
// event.onRightEyeDetector(false, BestSize.width(), BestSize.height());
// event.onRightEarDetector(false, BestSize.width(), BestSize.height());
// }
// }
// if (have_face){
// // kalau detect muka, baru coba detect mata
// RectVector eye = DetectEye(graymat);
// if (eye!=null && eye.size()>=2){
// // ada mata
// if (eye_was_closed.get()){
// eye_was_closed.set(false);
// if (blink_counter.get()>=2){
// blink_counter.set(0);
// if (event!=null) event.onBlink(blink_counter.get());
// }
// }
//
// if (event!=null) event.onEyeDetector(true, BestSize.width(), BestSize.height());
// for(int i=0; i<eye.size(); i++){
// Rect rect = eye.get(i);
// rectangle(LiveMat, rect, Scalar.RED);
// }
// } else {
// // mata tidak ada
// if (!eye_was_closed.get()){
// eye_was_closed.set(true);
// blink_counter.incrementAndGet();
// }
// if (event!=null) event.onEyeDetector(false, BestSize.width(), BestSize.height());
// }
//
// } else {
// eye_was_closed.set(false);
// blink_counter.set(0);
// // tidak ada muka, tidak ada mata
//
// }
} }

View File

@@ -69,6 +69,11 @@ public class CaptureView {
private final AtomicBoolean[] have_face = new AtomicBoolean[5]; private final AtomicBoolean[] have_face = new AtomicBoolean[5];
private final AtomicBoolean[] have_eyes = new AtomicBoolean[5]; private final AtomicBoolean[] have_eyes = new AtomicBoolean[5];
private final AtomicBoolean[] have_profile = new AtomicBoolean[5];
private final AtomicBoolean[] have_left_ear = new AtomicBoolean[5];
private final AtomicBoolean[] have_right_ear = new AtomicBoolean[5];
private final AtomicBoolean[] have_left_eye = new AtomicBoolean[5];
private final AtomicBoolean[] have_right_eye = new AtomicBoolean[5];
private final AtomicBoolean isTakingPhoto = new AtomicBoolean(false); private final AtomicBoolean isTakingPhoto = new AtomicBoolean(false);
@FXML @FXML
@@ -463,6 +468,14 @@ public class CaptureView {
case CameraConfigRight90 -> have_face[4]; case CameraConfigRight90 -> have_face[4];
}; };
final AtomicBoolean _have_profile = switch (image.getCameraConfigEnum()){
case CameraConfigCenter -> have_profile[2];
case CameraConfigLeft45 -> have_profile[1];
case CameraConfigLeft90 -> have_profile[0];
case CameraConfigRight45 -> have_profile[3];
case CameraConfigRight90 -> have_profile[4];
};
final AtomicBoolean _have_eye = switch (image.getCameraConfigEnum()){ final AtomicBoolean _have_eye = switch (image.getCameraConfigEnum()){
case CameraConfigCenter -> have_eyes[2]; case CameraConfigCenter -> have_eyes[2];
case CameraConfigLeft45 -> have_eyes[1]; case CameraConfigLeft45 -> have_eyes[1];
@@ -471,6 +484,38 @@ public class CaptureView {
case CameraConfigRight90 -> have_eyes[4]; case CameraConfigRight90 -> have_eyes[4];
}; };
final AtomicBoolean _have_left_ear = switch (image.getCameraConfigEnum()){
case CameraConfigCenter -> have_left_ear[2];
case CameraConfigLeft45 -> have_left_ear[1];
case CameraConfigLeft90 -> have_left_ear[0];
case CameraConfigRight45 -> have_left_ear[3];
case CameraConfigRight90 -> have_left_ear[4];
};
final AtomicBoolean _have_right_ear = switch (image.getCameraConfigEnum()){
case CameraConfigCenter -> have_right_ear[2];
case CameraConfigLeft45 -> have_right_ear[1];
case CameraConfigLeft90 -> have_right_ear[0];
case CameraConfigRight45 -> have_right_ear[3];
case CameraConfigRight90 -> have_right_ear[4];
};
final AtomicBoolean _have_left_eye = switch (image.getCameraConfigEnum()){
case CameraConfigCenter -> have_left_eye[2];
case CameraConfigLeft45 -> have_left_eye[1];
case CameraConfigLeft90 -> have_left_eye[0];
case CameraConfigRight45 -> have_left_eye[3];
case CameraConfigRight90 -> have_left_eye[4];
};
final AtomicBoolean _have_right_eye = switch (image.getCameraConfigEnum()){
case CameraConfigCenter -> have_right_eye[2];
case CameraConfigLeft45 -> have_right_eye[1];
case CameraConfigLeft90 -> have_right_eye[0];
case CameraConfigRight45 -> have_right_eye[3];
case CameraConfigRight90 -> have_right_eye[4];
};
Platform.runLater(()-> image.setCameraTitle(title)); Platform.runLater(()-> image.setCameraTitle(title));
if (devicenumber!=-1){ if (devicenumber!=-1){
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(devicenumber); OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(devicenumber);
@@ -521,17 +566,47 @@ public class CaptureView {
} }
@Override @Override
public void onFaceDetector(boolean hasface, int width, int height) { public void onFrontalFaceDetector(boolean hasface, int width, int height) {
_have_face.set(hasface); _have_face.set(hasface);
update_status(image); update_status(image);
} }
@Override
public void onProfileFaceDetector(boolean hasface, int width, int height) {
_have_profile.set(hasface);
update_status(image);
}
@Override @Override
public void onEyeDetector(boolean hasEye, int width, int height) { public void onEyeDetector(boolean hasEye, int width, int height) {
_have_eye.set(hasEye); _have_eye.set(hasEye);
update_status(image); update_status(image);
} }
@Override
public void onLeftEarDetector(boolean hasLeftEar, int width, int height) {
_have_left_ear.set(hasLeftEar);
update_status(image);
}
@Override
public void onRightEarDetector(boolean hasRightEar, int width, int height) {
_have_right_ear.set(hasRightEar);
update_status(image);
}
@Override
public void onLeftEyeDetector(boolean hasLeftEye, int width, int height) {
_have_left_eye.set(hasLeftEye);
update_status(image);
}
@Override
public void onRightEyeDetector(boolean hasRightEye, int width, int height) {
_have_right_eye.set(hasRightEye);
update_status(image);
}
@Override @Override
public void onLog(String log) { public void onLog(String log) {
String ss = String.format("[%s] : %s", title, log); String ss = String.format("[%s] : %s", title, log);
@@ -556,8 +631,14 @@ public class CaptureView {
sb.append(image.getBestHeight()); sb.append(image.getBestHeight());
sb.append("@"); sb.append("@");
sb.append(image.getLiveFPS()); sb.append(image.getLiveFPS());
if (_have_face.get()) sb.append(", Face Detected"); if (_have_face.get()) sb.append(", Face");
if (_have_eye.get()) sb.append(", Eye Detected"); if (_have_profile.get()) sb.append(", Profile");
if (_have_eye.get()) sb.append(", Eye");
if (_have_left_eye.get()) sb.append(", Left Eye");
if (_have_right_eye.get()) sb.append(", Right Eye");
if (_have_left_ear.get()) sb.append(", Left Ear");
if (_have_right_ear.get()) sb.append(", Right Ear");
image.setCameraStatus(sb.toString()); image.setCameraStatus(sb.toString());
}); });
@@ -578,6 +659,11 @@ public class CaptureView {
have_face[camid-1] = new AtomicBoolean(false); have_face[camid-1] = new AtomicBoolean(false);
have_eyes[camid-1] = new AtomicBoolean(false); have_eyes[camid-1] = new AtomicBoolean(false);
have_profile[camid-1] = new AtomicBoolean(false);
have_left_ear[camid-1] = new AtomicBoolean(false);
have_right_ear[camid-1] = new AtomicBoolean(false);
have_left_eye[camid-1] = new AtomicBoolean(false);
have_right_eye[camid-1] = new AtomicBoolean(false);
FXMLLoader loader = new FXMLLoader(getClass().getResource("cameradetail.fxml")); FXMLLoader loader = new FXMLLoader(getClass().getResource("cameradetail.fxml"));
AnchorPane child = loader.load(); AnchorPane child = loader.load();

View File

@@ -1,23 +1,43 @@
package id.co.gtc.erhacam; package id.co.gtc.erhacam;
import Config.SomeCodes; import Config.SomeCodes;
import lombok.NonNull;
import org.bytedeco.opencv.opencv_core.Rect;
import org.bytedeco.opencv.opencv_core.RectVector; import org.bytedeco.opencv.opencv_core.RectVector;
import org.bytedeco.opencv.opencv_core.Size; import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_core.UMat; import org.bytedeco.opencv.opencv_core.UMat;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier; import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import org.tinylog.Logger; import org.tinylog.Logger;
public class Detectors { import java.util.ArrayList;
public static CascadeClassifier faceDetector; import java.util.List;
public static CascadeClassifier eyeDetector;
public static void LoadFaceDetector(){ public class Detectors {
String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml"); public static CascadeClassifier frontalfaceDetector;
public static CascadeClassifier eyeDetector;
public static CascadeClassifier leftEyeDetector;
public static CascadeClassifier rightEyeDetector;
public static CascadeClassifier leftEarDetector;
public static CascadeClassifier rightEarDetector;
public static CascadeClassifier profilefaceDetector;
public static void LoadAllDetectors(){
LoadFrontalFaceDetector();
LoadProfileFaceDetector();
LoadEyeDetector();
LoadLeftEarDetector();
LoadRightEarDetector();
LoadLeftEyeDetector();
LoadRightEyeDetector();
}
private static void LoadFrontalFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml");
if (filename!=null) { if (filename!=null) {
System.out.println("Face Detector file : " + filename); System.out.println("Face Detector file : " + filename);
if (faceDetector==null) { if (frontalfaceDetector==null) {
try{ try{
faceDetector = new CascadeClassifier(filename); frontalfaceDetector = new CascadeClassifier(filename);
Logger.info("FaceDetector loaded"); Logger.info("FaceDetector loaded");
} catch (Exception e){ } catch (Exception e){
Logger.error("Exception on loading FaceDetector : " + e.getMessage()); Logger.error("Exception on loading FaceDetector : " + e.getMessage());
@@ -27,28 +47,23 @@ public class Detectors {
} else Logger.error("Unable to extract face detector file"); } else Logger.error("Unable to extract face detector file");
} }
static double scaleFactor = 1.1; private static void LoadProfileFaceDetector(){
static int minNeighbors = 3; String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml");
static int flags = 0; if (filename!=null) {
static Size minSize = new Size(30, 30); System.out.println("Profile Face Detector file : " + filename);
static Size maxSize = new Size(300, 300); 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");
* Detect Face from Mat } else Logger.error("Unable to extract profile face detector file");
* @param graymat Mat in Gray Scale
* @return RectVector if face detected, otherwise false
*/
public static RectVector DetectFace(UMat graymat){
if (faceDetector!=null){
RectVector face = new RectVector();
//faceDetector.detectMultiScale(graymat, face);
faceDetector.detectMultiScale(graymat, face, scaleFactor, minNeighbors,flags, minSize, maxSize);
return face;
}
return null;
} }
public static void LoadEyeDetector(){ private static void LoadEyeDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_eye_tree_eyeglasses.xml"); String filename = SomeCodes.ExtractResource("/haarcascade_eye_tree_eyeglasses.xml");
if (filename!=null) { if (filename!=null) {
System.out.println("Eye Detector file : " + filename); System.out.println("Eye Detector file : " + filename);
@@ -65,13 +80,272 @@ public class Detectors {
} else Logger.error("Unable to extract eye detector file"); } else Logger.error("Unable to extract eye detector file");
} }
private static void LoadLeftEyeDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_lefteye_2splits.xml");
if (filename!=null) {
System.out.println("Left Eye Detector file : " + filename);
if (leftEyeDetector==null) {
try{
leftEyeDetector = new CascadeClassifier(filename);
Logger.info("LeftEyeDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading LeftEyeDetector : " + e.getMessage());
}
} else Logger.info("LeftEyeDetector already loaded");
} else Logger.error("Unable to extract left eye detector file");
}
private static void LoadRightEyeDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_righteye_2splits.xml");
if (filename!=null) {
System.out.println("Right Eye Detector file : " + filename);
if (rightEyeDetector==null) {
try{
rightEyeDetector = new CascadeClassifier(filename);
Logger.info("RightEyeDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading RightEyeDetector : " + e.getMessage());
}
} else Logger.info("RightEyeDetector already loaded");
} else Logger.error("Unable to extract right eye detector file");
}
private static void LoadLeftEarDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_mcs_leftear.xml");
if (filename!=null) {
System.out.println("Left Ear Detector file : " + filename);
if (leftEarDetector==null) {
try{
leftEarDetector = new CascadeClassifier(filename);
Logger.info("LeftEarDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading LeftEarDetector : " + e.getMessage());
}
} else Logger.info("LeftEarDetector already loaded");
} else Logger.error("Unable to extract left ear detector file");
}
private static void LoadRightEarDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_mcs_rightear.xml");
if (filename!=null) {
System.out.println("Right Ear Detector file : " + filename);
if (rightEarDetector==null) {
try{
rightEarDetector = new CascadeClassifier(filename);
Logger.info("RightEarDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading RightEarDetector : " + e.getMessage());
}
} else Logger.info("RightEarDetector already loaded");
} else Logger.error("Unable to extract right ear detector file");
}
//TODO buat kalkulasi range minSize dan maxSize kalau pakai BestMat (3840x2160) dan LiveMat (1280x720)
/**
* Detect if there is a frontal face, containing 2 eyes
* @param graymat Mat in Gray Scale
* @return List of Rect if face detected, otherwise empty list
*/
public static @NonNull List<Rect> HaveFrontalFace(UMat graymat){
List<Rect> result = new ArrayList<>();
RectVector faces = DetectFrontalFace(graymat);
if (faces!=null && faces.size()>0){
for(Rect face : faces.get()){
UMat faceMat = new UMat(graymat, face);
RectVector eyes = DetectEye(faceMat);
if (eyes!=null && eyes.size()>=2){
result.add(face);
}
}
}
return result;
}
public static @NonNull List<Rect> HaveLeft45Face(UMat graymat){
List<Rect> result = new ArrayList<>();
RectVector faces = DetectProfileFace(graymat);
if (faces!=null && faces.size()>0){
for(Rect face : faces.get()){
UMat faceMat = new UMat(graymat, face);
RectVector eyes = DetectLeftEye(faceMat);
if (eyes!=null && eyes.size()>0){
result.add(face);
}
}
}
return result;
}
public static @NonNull List<Rect> HaveRight45Face(UMat graymat){
List<Rect> result = new ArrayList<>();
RectVector faces = DetectProfileFace(graymat);
if (faces!=null && faces.size()>0){
for(Rect face : faces.get()){
UMat faceMat = new UMat(graymat, face);
RectVector eyes = DetectRightEye(faceMat);
if (eyes!=null && eyes.size()>0){
result.add(face);
}
}
}
return result;
}
public static @NonNull List<Rect> HaveLeft90Face(UMat graymat){
List<Rect> result = new ArrayList<>();
RectVector leftears = DetectLeftEar(graymat);
RectVector lefteyes = DetectLeftEye(graymat);
if (leftears!=null && leftears.size()>0 && lefteyes!=null && lefteyes.size()>0){
for(Rect ear : leftears.get()){
result.add(ear);
}
}
return result;
}
public static @NonNull List<Rect> HaveRight90Face(UMat graymat){
List<Rect> result = new ArrayList<>();
RectVector rightears = DetectRightEar(graymat);
RectVector righteyes = DetectRightEye(graymat);
if (rightears!=null && rightears.size()>0 && righteyes!=null && righteyes.size()>0){
for(Rect ear : rightears.get()){
result.add(ear);
}
}
return result;
}
private static double scaleFactor = 1.1;
private final static int minNeighbors = 3;
private final static int flags = 0;
private static Size minSize = new Size(200,200);
private static Size maxSize = new Size(400,400);
public static void setScaleFactor(double value){
if (scaleFactor!=value) scaleFactor = value;
}
public static void setMinSize(int value){
if (minSize.width()!=value || minSize.height()!=value) minSize = new Size(value, value);
}
public static void setMaxSize(int value){
if (maxSize.width()!=value || maxSize.height()!=value) maxSize = new Size(value, value);
}
public static RectVector DetectProfileFace(UMat graymat){
return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, minSize, maxSize);
}
/**
* Detect Face from Mat
* @param graymat Mat in Gray Scale
* @return RectVector if face detected, otherwise null
*/
public static RectVector DetectFrontalFace(UMat graymat){
return Detect(graymat, frontalfaceDetector, scaleFactor, minNeighbors, flags, minSize, maxSize);
}
/**
* Detect Eye from Mat
* If Eye detected, it will return RectVector with size is number of eyes detected
* @param graymat Mat in Gray Scale
* @return RectVector if eye detected, otherwise null
*/
public static RectVector DetectEye(UMat graymat){ public static RectVector DetectEye(UMat graymat){
if (eyeDetector!=null){ return Detect(graymat, eyeDetector);
RectVector eye = new RectVector(); }
eyeDetector.detectMultiScale(graymat, eye);
return eye;
/**
* Detect Left Eye from Mat
* @param graymat Mat in Gray Scale
* @return RectVector if left eye detected, otherwise null
*/
public static RectVector DetectLeftEye(UMat graymat){
return Detect(graymat, leftEyeDetector);
}
/**
* Detect Right Eye from Mat
* @param graymat Mat in Gray Scale
* @return RectVector if right eye detected, otherwise null
*/
public static RectVector DetectRightEye(UMat graymat){
return Detect(graymat, rightEyeDetector);
}
/**
* Detect Left Ear from Mat
* @param graymat Mat in Gray Scale
* @return RectVector if left ear detected, otherwise null
*/
public static RectVector DetectLeftEar(UMat graymat){
return Detect(graymat, leftEarDetector);
}
/**
* Detect Right Ear from Mat
* @param graymat Mat in Gray Scale
* @return RectVector if right ear detected, otherwise null
*/
public static RectVector DetectRightEar(UMat graymat){
return Detect(graymat, rightEarDetector);
}
private static RectVector Detect(UMat graymat, CascadeClassifier detector){
if (detector!=null){
if (graymat!=null){
if (!graymat.empty()){
RectVector detected = new RectVector();
detector.detectMultiScale(graymat, detected);
return detected;
}
}
} }
return null; return null;
} }
@SuppressWarnings("SameParameterValue")
private static RectVector Detect(UMat graymat, CascadeClassifier detector, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize){
if (detector!=null){
if (graymat!=null){
if (!graymat.empty()){
RectVector detected = new RectVector();
detector.detectMultiScale(graymat, detected, scaleFactor, minNeighbors, flags, minSize, maxSize);
return detected;
}
}
}
return null;
}
} }

View File

@@ -21,7 +21,7 @@ public class MainApplication extends Application {
Screen screen = Screen.getPrimary(); Screen screen = Screen.getPrimary();
Rectangle2D screenbound = screen.getVisualBounds(); Rectangle2D screenbound = screen.getVisualBounds();
Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight()); Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight());
stage.setTitle("MultiCam Capture App for ERHA"); stage.setTitle("MultiCam Capture App for ERHA 03022025-011");
stage.setScene(scene); stage.setScene(scene);
stage.setResizable(true); stage.setResizable(true);
stage.setMaximized(true); stage.setMaximized(true);
@@ -32,9 +32,10 @@ public class MainApplication extends Application {
Logger.info("Application closed"); Logger.info("Application closed");
}); });
SomeCodes.LoadQRReader(); SomeCodes.LoadQRReader();
Detectors.LoadFaceDetector(); Detectors.LoadAllDetectors();
Detectors.LoadEyeDetector();
stage.show(); stage.show();
Logger.info("Application started"); Logger.info("Application started");
} }

View File

@@ -59,7 +59,7 @@ public class MainView {
@FXML @FXML
private void initialize(){ private void initialize(){
ReviewClick(null); CaptureClick(null);
} }
public void Unload(){ public void Unload(){

View File

@@ -13,6 +13,7 @@ import org.tinylog.Logger;
import java.io.File; import java.io.File;
import static Config.SomeCodes.ValidString;
import static Config.SomeCodes.config; import static Config.SomeCodes.config;
public class SettingView { public class SettingView {
@@ -53,6 +54,64 @@ public class SettingView {
String[] cameranames = null; String[] cameranames = null;
@FXML
private TextField cascadeMinSize;
@FXML
private TextField cascadeScaleFactor;
@FXML
private TextField cascadeMaxSize;
@FXML
private void CascadeSettingApply(){
String minsize = cascadeMinSize.getText();
String scalefactor = cascadeScaleFactor.getText();
String maxsize = cascadeMaxSize.getText();
if (ValidString(minsize)){
if (ValidString(maxsize)){
if (ValidString(scalefactor)){
try{
int min = Integer.parseInt(minsize);
double scale = Double.parseDouble(scalefactor);
int max = Integer.parseInt(maxsize);
if (scale> 1.0){
if (min>0){
if (max>min){
config.setCascadeMaxSize(max);
config.setCascadeMinSize(min);
config.setCascadeScaleFactor(scale);
config.Save();
Detectors.setMaxSize(max);
Detectors.setMinSize(min);
Detectors.setScaleFactor(scale);
val alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Cascade Setting");
alert.setHeaderText("Cascade Setting Saved");
alert.setContentText("Cascade Setting Saved Successfully");
alert.showAndWait();
} else show_cascade_alert("Max Size must be greater than Min Size");
} else show_cascade_alert("Min Size must be greater than 0");
} else show_cascade_alert("Scale Factor must be greater than 1.0");
} catch (NumberFormatException e){
show_cascade_alert("Min Size, Scale Factor, and Max Size must be a number");
}
} else show_cascade_alert("Scale Factor must not empty");
} else show_cascade_alert("Max Size must not empty");
} else show_cascade_alert("Min Size must not empty");
}
private void show_cascade_alert(String content){
val alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Cascade Setting Error");
alert.setHeaderText("Cascade Setting Error");
alert.setContentText(content);
alert.showAndWait();
}
@FXML @FXML
public void initialize(){ public void initialize(){
FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("Audio File", "wav","mp3"); FileChooser.ExtensionFilter filter = new FileChooser.ExtensionFilter("Audio File", "wav","mp3");
@@ -108,6 +167,10 @@ public class SettingView {
FTPUser.setText(config.getFTPUser()); FTPUser.setText(config.getFTPUser());
FTPPass.setText(config.getFTPPass()); FTPPass.setText(config.getFTPPass());
FTPPath.setText(config.getFTPPath()); FTPPath.setText(config.getFTPPath());
cascadeScaleFactor.setText(String.valueOf(config.getCascadeScaleFactor()));
cascadeMinSize.setText(String.valueOf(config.getCascadeMinSize()));
cascadeMaxSize.setText(String.valueOf(config.getCascadeMaxSize()));
}); });
} }

View File

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

View File

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

View File

@@ -1,16 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.*?>
<?import javafx.scene.control.ComboBox?> <?import javafx.scene.layout.*?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefWidth="1024.0" xmlns="http://javafx.com/javafx/22" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.SettingView"> <AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefWidth="1024.0" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="id.co.gtc.erhacam.SettingView">
<children> <children>
<GridPane layoutX="70.0" layoutY="78.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <GridPane layoutX="70.0" layoutY="78.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints> <columnConstraints>
@@ -137,97 +130,185 @@
</AnchorPane> </AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="3"> <AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="3">
<children> <children>
<GridPane layoutX="166.0" layoutY="-29.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="40.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" /> </columnConstraints>
</columnConstraints> <rowConstraints>
<rowConstraints> <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> </rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <children>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <GridPane>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <columnConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" />
</rowConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<children> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="15.0" prefWidth="100.0" />
<AnchorPane prefHeight="200.0" prefWidth="200.0"> </columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children> <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" /> <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" />
</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" />
</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" />
</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" />
</children>
</AnchorPane>
</children>
</GridPane>
<GridPane GridPane.columnIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane GridPane.rowIndex="2">
<children>
<Button mnemonicParsing="false" onAction="#CascadeSettingApply" prefHeight="40.0" prefWidth="410.4" text="Apply" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane>
<children>
<Label alignment="CENTER" prefHeight="30.4" prefWidth="410.4" text="Detection Parameters" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="1">
<children>
<ScrollPane layoutY="0.7999992370605469" prefHeight="200.8" prefWidth="410.4" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="200.0" minWidth="0.0" prefWidth="350.0">
<children>
<GridPane prefHeight="200.0" prefWidth="300.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane>
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Scale Factor" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="1">
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Minimum Size" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.rowIndex="2">
<children>
<Label prefHeight="40.0" prefWidth="175.2" text="Maximum Size" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1">
<children>
<TextField fx:id="cascadeScaleFactor" alignment="CENTER" prefHeight="40.0" prefWidth="175.2" text="1.2" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1" GridPane.rowIndex="1">
<children>
<TextField fx:id="cascadeMinSize" alignment="CENTER" prefHeight="40.0" prefWidth="175.2" text="200" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane GridPane.columnIndex="1" GridPane.rowIndex="2">
<children>
<TextField fx:id="cascadeMaxSize" alignment="CENTER" prefHeight="40.0" prefWidth="175.2" text="400" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</children>
</GridPane>
</children> </children>
</AnchorPane> </AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1"> </content>
<children> </ScrollPane>
<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" /> </children>
</children> </AnchorPane>
</AnchorPane> </children>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2"> </GridPane>
<children> </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" /> </GridPane>
</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" />
</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" />
</children>
</AnchorPane>
</children>
</GridPane>
</children> </children>
</AnchorPane> </AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="5"> <AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="5">