Commit 19022025

This commit is contained in:
2025-02-19 10:14:10 +07:00
parent 64f5b619b7
commit b248c59e32
8 changed files with 24886 additions and 251 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -361,6 +361,17 @@ public class SomeCodes {
return null; return null;
} }
public static boolean Save(UMat source, String filename, int[] param){
if (source!=null && !source.empty() && ValidString(filename)){
try{
return opencv_imgcodecs.imwrite(filename, source, param);
} catch (Exception e){
Logger.error("Error saving file: "+filename+", Msg : "+e.getMessage());
}
}
return false;
}
/** /**
* Concatenate byte arrays * Concatenate byte arrays
* @param args byte arrays * @param args byte arrays

View File

@@ -2,6 +2,7 @@ package ErhaAPI;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.bytedeco.opencv.opencv_core.Rect;
@Getter @Setter @Getter @Setter
public class PhotoResult { public class PhotoResult {
@@ -11,6 +12,8 @@ public class PhotoResult {
private String fullcrop; private String fullcrop;
private String compressedcrop; private String compressedcrop;
private String thumbnail; private String thumbnail;
private Rect BestROI;
private Rect ReducedROI;
public PhotoResult(String cameraname){ public PhotoResult(String cameraname){
this.cameraname = cameraname; this.cameraname = cameraname;
this.fullres = ""; this.fullres = "";
@@ -18,6 +21,8 @@ public class PhotoResult {
this.fullcrop = ""; this.fullcrop = "";
this.compressedcrop = ""; this.compressedcrop = "";
this.thumbnail = ""; this.thumbnail = "";
this.BestROI = null;
this.ReducedROI = null;
} }
public PhotoResult(String cameraname,String fullres, String compressedfile, String fullcrop, String compressedcrop, String thumbnail){ public PhotoResult(String cameraname,String fullres, String compressedfile, String fullcrop, String compressedcrop, String thumbnail){
this.cameraname = cameraname; this.cameraname = cameraname;
@@ -26,5 +31,17 @@ public class PhotoResult {
this.fullcrop = fullcrop; this.fullcrop = fullcrop;
this.compressedcrop = compressedcrop; this.compressedcrop = compressedcrop;
this.thumbnail = thumbnail; this.thumbnail = thumbnail;
this.BestROI = null;
this.ReducedROI = null;
}
@Override
public String toString(){
return "Camera Name: " + cameraname + "\n" +
"Full Resolution: " + fullres + "\n" +
"Compressed File: " + compressedfile + "\n" +
"Full Crop: " + fullcrop + "\n" +
"Compressed Crop: " + compressedcrop + "\n" +
"Thumbnail: " + thumbnail + "\n";
} }
} }

View File

@@ -4,7 +4,6 @@ import Camera.CameraProperty;
import Camera.LiveCamEvent; import Camera.LiveCamEvent;
import Camera.ObsbotMeet2Preset; import Camera.ObsbotMeet2Preset;
import Config.CameraConfigEnum; import Config.CameraConfigEnum;
import Config.SomeCodes;
import ErhaAPI.PhotoResult; import ErhaAPI.PhotoResult;
import com.google.zxing.BinaryBitmap; import com.google.zxing.BinaryBitmap;
import com.google.zxing.NotFoundException; import com.google.zxing.NotFoundException;
@@ -102,22 +101,20 @@ public class Cameradetail {
@FXML @FXML
private Slider exposureSlider; private Slider exposureSlider;
private final UMat BestMat = new UMat(); private @Getter final UMat BestMat = new UMat();
private final UMat LiveMat = new UMat(); private @Getter final UMat LiveMat = new UMat();
private final UMat ReducedMat = new UMat(); private @Getter final UMat ReducedMat = new UMat();
private @Getter Rect BestMatROI; private @Getter Rect BestMatROI;
private @Getter Rect ReducedMatROI; private @Getter Rect ReducedMatROI;
private @Getter Rect LiveMatROI; private @Getter Rect LiveMatROI;
// private Size LiveSize = new Size(640, 360); private boolean IsPortrait = false;
// private Size ReducedSize = new Size(1280, 720);
// private Size BestSize = new Size(1920, 1080);
// putar portrait // putar portrait
private Size LiveSize = new Size(360, 640); private @Getter Size LiveSize = new Size(360, 640);
private Size ReducedSize = new Size(720, 1280); private @Getter Size ReducedSize = new Size(720, 1280);
private Size BestSize = new Size(2160, 3840); private @Getter Size BestSize = new Size(2160, 3840);
//TODO ini angka dari Erha, cek apakah masih cocok atau tidak //TODO ini angka dari Erha, cek apakah masih cocok atau tidak
private @Getter @Setter Size FullCropSize = new Size(1036,1036); private @Getter @Setter Size FullCropSize = new Size(1036,1036);
@@ -130,6 +127,8 @@ public class Cameradetail {
return BestSize.height(); return BestSize.height();
} }
int[] paramjpeg = {opencv_imgcodecs.IMWRITE_JPEG_QUALITY, 100};
int[] parampng = {opencv_imgcodecs.IMWRITE_PNG_COMPRESSION, 0};
private void setSliderValue(Slider sld, CameraProperty prop, double value){ private void setSliderValue(Slider sld, CameraProperty prop, double value){
@@ -358,7 +357,9 @@ public class Cameradetail {
StopLiveView(); StopLiveView();
} }
if (isPotrait){ IsPortrait = isPotrait;
if (IsPortrait){
// putar portrait // putar portrait
LiveSize = new Size(liveheight, livewidth); LiveSize = new Size(liveheight, livewidth);
BestSize = new Size(photoheight, photowidth); BestSize = new Size(photoheight, photowidth);
@@ -554,17 +555,85 @@ public class Cameradetail {
return 0; return 0;
} }
public boolean PutText(String filename, String text, double fontScale, Scalar textColor, int thickness){
if (ValidString(filename)){
Mat mat = opencv_imgcodecs.imread(filename);
if (PutText(mat, text, fontScale, textColor, thickness)){
return opencv_imgcodecs.imwrite(filename, mat);
}
}
return false;
}
public boolean PutText(UMat Mat, String text, double fontScale, Scalar textColor, int thickness){
if (!Mat.empty()){
if (text!=null && !text.isEmpty()){
//String timestamp = prefix+" "+SomeCodes.GetDateTimeString();
int fontFace = FONT_HERSHEY_SIMPLEX;
//double fontScale = 4.0;
//int thickness = 2;
//Scalar textColor = new Scalar(255, 255, 255, 0); // white color in BGR format
int[] baseline = {0};
Size textSize = getTextSize(text, fontFace, fontScale, thickness, baseline);
// position of the text in the bottom right corner
int textX = Mat.cols() - textSize.width() - 10; // 10 pixels from the right
int textY = Mat.rows() - 10; // 10 pixels from the bottom
opencv_imgproc.putText(Mat, text, new Point(textX, textY), fontFace, fontScale, textColor, thickness, LINE_8, false);
return true;
}
}
return false;
}
public boolean PutText(Mat Mat, String text, double fontScale, Scalar textColor, int thickness){
if (!Mat.empty()){
if (text!=null && !text.isEmpty()){
//String timestamp = prefix+" "+SomeCodes.GetDateTimeString();
int fontFace = FONT_HERSHEY_SIMPLEX;
//double fontScale = 4.0;
//int thickness = 2;
//Scalar textColor = new Scalar(255, 255, 255, 0); // white color in BGR format
int[] baseline = {0};
Size textSize = getTextSize(text, fontFace, fontScale, thickness, baseline);
// position of the text in the bottom right corner
int textX = Mat.cols() - textSize.width() - 10; // 10 pixels from the right
int textY = Mat.rows() - 10; // 10 pixels from the bottom
opencv_imgproc.putText(Mat, text, new Point(textX, textY), fontFace, fontScale, textColor, thickness, LINE_8, false);
return true;
}
}
return false;
}
public String GetFullQualityPhotoPath(String directory, String prefix){
if (!ValidDirectory(directory)) directory = currentDirectory;
return Path.of(directory, "FullQuality", makeFileName(prefix,".png")).toString();
}
public String GetReducedPhotoPath(String directory, String prefix){
if (!ValidDirectory(directory)) directory = currentDirectory;
return Path.of(directory, "Compressed", makeReducedFileName(prefix,".jpg")).toString();
}
public String GetFullQualityCropPhotoPath(String directory, String prefix){
if (!ValidDirectory(directory)) directory = currentDirectory;
return Path.of(directory, "FullQualityCrop", makeFileName(prefix,".png")).toString();
}
public String GetReducedCropPhotoPath(String directory, String prefix){
if (!ValidDirectory(directory)) directory = currentDirectory;
return Path.of(directory, "CompressedCrop", makeReducedFileName(prefix,".jpg")).toString();
}
/** /**
* Take Photo from Camera * Take Photo from Camera
* @param directory directory to save the photo, if null, will use default directory * @param directory directory to save the photo, if null, will use default directory
* @param prefix filename prefix * @param prefix filename prefix
* @param ROI_Full Region of Interest for Full Quality Photo. If Null, will not save cropped photo
* @param ROI_Compressed Region of Interest for Compressed Photo. If Null, will not save cropped photo
* @return filename path of the saved photo, or null if failed * @return filename path of the saved photo, or null if failed
*/ */
public PhotoResult TakePhoto(String directory, String prefix, Rect ROI_Full, Rect ROI_Compressed) throws InterruptedException { public PhotoResult TakePhoto(String directory, String prefix) throws InterruptedException {
PhotoResult result = new PhotoResult(cameratitle.getText()); PhotoResult result = new PhotoResult(cameratitle.getText());
if (!ValidDirectory(directory)) directory = currentDirectory; if (!ValidDirectory(directory)) directory = currentDirectory;
@@ -577,50 +646,64 @@ public class Cameradetail {
Size sz = BestMat.size(); Size sz = BestMat.size();
raise_log("TakePhoto got frame with width: " + sz.width() + " and height: " + sz.height()); raise_log("TakePhoto got frame with width: " + sz.width() + " and height: " + sz.height());
String timestamp = prefix+" "+SomeCodes.GetDateTimeString(); // String timestamp = prefix+" "+SomeCodes.GetDateTimeString();
int fontFace = FONT_HERSHEY_SIMPLEX; // Scalar color = new Scalar(255, 255, 255, 0); // white
double fontScale = 4.0; // PutText(BestMat, timestamp, 4.0, color, 2);
int thickness = 2;
Scalar textColor = new Scalar(255, 255, 255, 0); // white color in BGR format
int[] baseline = {0};
Size textSize = getTextSize(timestamp, fontFace, fontScale, thickness, baseline);
// position of the text in the bottom right corner
int textX = BestMat.cols() - textSize.width() - 10; // 10 pixels from the right
int textY = BestMat.rows() - 10; // 10 pixels from the bottom
opencv_imgproc.putText(BestMat, timestamp, new Point(textX, textY), fontFace, fontScale, textColor, thickness, opencv_imgproc.LINE_AA, false);
int[] paramjpeg = {opencv_imgcodecs.IMWRITE_JPEG_QUALITY, 100};
int[] parampng = {opencv_imgcodecs.IMWRITE_PNG_COMPRESSION, 0};
// save BestMat at quality 9 PNG // save BestMat at quality 9 PNG
String filename = Path.of(directory, "FullQuality", makeFileName(prefix,".png")).toString(); String filename = GetFullQualityCropPhotoPath(directory, prefix);
if (imwrite(filename, BestMat, parampng)){ //String filename = Path.of(directory, "FullQuality", makeFileName(prefix,".png")).toString();
if (opencv_imgcodecs.imwrite(filename, BestMat, parampng)){
result.setFullres(filename); result.setFullres(filename);
} else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+cameratitle.getText()); } else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+cameratitle.getText());
UMat FullCrop = CropUMat(BestMat, ROI_Full); String xx = CropBestMat(directory, prefix, BestMatROI);
if (FullCrop!=null){ if (ValidFile(xx)) {
String roifilename = Path.of(directory, "FullQualityCrop", makeFileName(prefix,".png")).toString(); result.setFullcrop(xx);
if (!imwrite(roifilename, FullCrop, parampng)){ result.setBestROI(new Rect(BestMatROI.x(), BestMatROI.y(), BestMatROI.width(), BestMatROI.height()));
System.out.println("TakePhoto failed, Unable to Save FullQUalityCrop for camera "+cameratitle.getText());
} else result.setFullcrop(roifilename);
} }
// if (BestMatROI!=null){
// UMat FullCrop = CropUMat(BestMat, BestMatROI);
// if (FullCrop!=null){
// //String roifilename = Path.of(directory, "FullQualityCrop", makeFileName(prefix,".png")).toString();
// String roifilename = GetFullQualityCropPhotoPath(directory, prefix);
// if (!opencv_imgcodecs.imwrite(roifilename, FullCrop, parampng)){
// System.out.println("TakePhoto failed, Unable to Save FullQUalityCrop for camera "+cameratitle.getText());
// } else {
// result.setFullcrop(roifilename);
// result.setBestROI(new Rect(BestMatROI.x(), BestMatROI.y(), BestMatROI.width(), BestMatROI.height()));
// }
// }
// }
// save ReducedMat at 100% JPEG // save ReducedMat at 100% JPEG
String reducedfilename = Path.of(directory, "Compressed", makeReducedFileName(prefix,".jpg")).toString(); //String reducedfilename = Path.of(directory, "Compressed", makeReducedFileName(prefix,".jpg")).toString();
String reducedfilename = GetReducedPhotoPath(directory, prefix);
opencv_imgproc.resize(BestMat, ReducedMat, ReducedSize); opencv_imgproc.resize(BestMat, ReducedMat, ReducedSize);
if (!imwrite(reducedfilename, ReducedMat, paramjpeg)){ if (!opencv_imgcodecs.imwrite(reducedfilename, ReducedMat, paramjpeg)){
System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+cameratitle.getText()); System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+cameratitle.getText());
} else result.setCompressedfile(reducedfilename); } else result.setCompressedfile(reducedfilename);
UMat CompressedCrop = CropUMat(ReducedMat, ROI_Compressed); String xy = CropReducedMat(directory, prefix, ReducedMatROI);
if (CompressedCrop!=null){ if (ValidFile(xy)){
String roifilename = Path.of(directory, "CompressedCrop", makeReducedFileName(prefix,".jpg")).toString(); result.setCompressedcrop(xy);
if (!imwrite(roifilename, CompressedCrop, paramjpeg)){ result.setReducedROI(new Rect(ReducedMatROI.x(), ReducedMatROI.y(), ReducedMatROI.width(), ReducedMatROI.height()));
System.out.println("TakePhoto failed, Unable to Save CompressedCrop for camera "+cameratitle.getText());
} else result.setCompressedcrop(roifilename);
} }
// if (ReducedMatROI!=null){
// UMat ReducedCrop = CropUMat(ReducedMat, ReducedMatROI);
// if (ReducedCrop!=null){
// //String roifilename = Path.of(directory, "CompressedCrop", makeReducedFileName(prefix,".jpg")).toString();
// String roifilename = GetReducedCropPhotoPath(directory, prefix);
// if (!opencv_imgcodecs.imwrite(roifilename, ReducedCrop, paramjpeg)){
// System.out.println("TakePhoto failed, Unable to Save CompressedCrop for camera "+cameratitle.getText());
// } else {
// result.setCompressedcrop(roifilename);
// result.setReducedROI(new Rect(ReducedMatROI.x(), ReducedMatROI.y(), ReducedMatROI.width(), ReducedMatROI.height()));
// }
// }
// }
} else raise_log("TakePhoto failed, Live View is Empty"); } else raise_log("TakePhoto failed, Live View is Empty");
} else raise_log("TakePhoto failed, Grabber is null"); } else raise_log("TakePhoto failed, Grabber is null");
@@ -628,6 +711,44 @@ public class Cameradetail {
return result; return result;
} }
public String CropBestMat(String directory, String prefix, Rect ROI){
if (!BestMat.empty()) {
if (ValidROI(ROI)){
if (ROIInsideUMat(ROI, BestMat)){
UMat cropped = CropUMat(BestMat, ROI);
if (cropped != null) {
String filename = GetFullQualityCropPhotoPath(directory, prefix);
if (opencv_imgcodecs.imwrite(filename, cropped, parampng)) {
System.out.println("CropBestMat success, saved as " + filename);
Wait(500);
return filename;
} //else System.out.println("CropBestMat failed, Unable to Save BestMat");
} //else System.out.println("CropBestMat failed, Unable to Crop BestMat");
} //else System.out.println("CropBestMat failed, ROI is outside BestMat");
} //else System.out.println("CropBestMat failed, ROI is invalid");
} //else System.out.println("CropBestMat failed, BestMat is empty");
return null;
}
public String CropReducedMat(String directory, String prefix, Rect ROI){
if (!ReducedMat.empty()){
if (ValidROI(ROI)){
if (ROIInsideUMat(ROI,ReducedMat)){
UMat cropped = CropUMat(ReducedMat, ROI);
if (cropped!=null){
String filename = GetReducedCropPhotoPath(directory, prefix);
if (opencv_imgcodecs.imwrite(filename, cropped, paramjpeg)){
System.out.println("CropReducedMat success, saved as "+filename);
Wait(100);
return filename;
} //else System.out.println("CropReducedMat failed, Unable to Save ReducedMat");
} //else System.out.println("CropReducedMat failed, Unable to Crop ReducedMat");
} //else System.out.println("CropReducedMat failed, ROI is outside ReducedMat");
} //else System.out.println("CropReducedMat failed, ROI is invalid");
} //else System.out.println("CropReducedMat failed, ReducedMat is empty");
return null;
}
@@ -660,6 +781,33 @@ public class Cameradetail {
IsGrabbingLiveView.set(false); IsGrabbingLiveView.set(false);
} }
public Rect GetFace(UMat mat, boolean isfrontal){
if (!mat.empty()){
Mat originalmat = new Mat();
mat.copyTo(originalmat);
Mat graymat = new Mat();
opencv_imgproc.cvtColor(originalmat,graymat, COLOR_BGR2GRAY); // convert to grayscale
int size = Math.min(graymat.cols(), graymat.rows());
int minsize = (int) (size * 0.4);
int maxsize = (int) (size * 0.9);
System.out.println("GetFace size = "+size+" minsize = "+minsize+" maxsize = "+maxsize);
RectVector faces = isfrontal ? Detectors.DetectFrontalFace(graymat, minsize, maxsize) : Detectors.DetectProfileFace(graymat, minsize, maxsize);
if (faces.size()>0){
Rect result = null;
for(Rect xx : faces.get()){
if (result==null){
result = xx;
} else {
if (xx.area()>result.area()){
result = xx;
}
}
}
return result;
}
} else raise_log("GetFace failed, Mat is empty");
return null;
}
public boolean StartLiveView(LiveCamEvent event, String cameratitle, final boolean use_qr , final boolean use_face) { public boolean StartLiveView(LiveCamEvent event, String cameratitle, final boolean use_qr , final boolean use_face) {
this.event = event; this.event = event;
@@ -669,8 +817,13 @@ public class Cameradetail {
if (use_qr) raise_log("QR Reader loaded"); if (use_qr) raise_log("QR Reader loaded");
if (use_face) raise_log("Face detector loaded"); if (use_face) raise_log("Face detector loaded");
// capture with best resolution // capture with best resolution
setFrameHeight(BestSize.height()); if (IsPortrait){
setFrameWidth(BestSize.width()); setFrameHeight(BestSize.width());
setFrameWidth(BestSize.height());
} else {
setFrameHeight(BestSize.height());
setFrameWidth(BestSize.width());
}
LiveFPS = 0; LiveFPS = 0;
mGrabber.start(); mGrabber.start();
@@ -749,10 +902,8 @@ public class Cameradetail {
if (use_qr){ if (use_qr){
String qr = DetectQRFromMat(graymat); String qr = DetectQRFromMat(graymat);
if (ValidBarCode(qr)){ if (ValidBarCode(qr)){
if (!qr.equals(qrtext)){ qrtext = qr;
qrtext = qr; if (event!=null) event.onDetectedQRCode(qrtext);
if (event!=null) event.onDetectedQRCode(qrtext);
}
} }
} }
if (use_face){ if (use_face){
@@ -803,7 +954,12 @@ public class Cameradetail {
no_face_counter = 0; no_face_counter = 0;
if (event!=null) event.onFrontalFaceDetector(true, _face_width, _face_height); if (event!=null) event.onFrontalFaceDetector(true, _face_width, _face_height);
LiveMatROI = theface.getFace();
if (theface.getFace()!=null){
LiveMatROI = new Rect(theface.getFace().x(), theface.getFace().y(), theface.getFace().width(), theface.getFace().height());
//System.out.println("Frontal Face Detected from camera "+cameratitle+" "+RectToString(LiveMatROI));
}
if (theface.haveEyes()){ if (theface.haveEyes()){
// ada mata (buka mata) // ada mata (buka mata)
if (eye_state==0){ if (eye_state==0){
@@ -838,12 +994,8 @@ public class Cameradetail {
} else if (have_left_45_face ){ } else if (have_left_45_face ){
no_face_counter = 0; no_face_counter = 0;
LiveMatROI = theface.getFace();
if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height); if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height);
} else { } else {
// no face detected, but let's not cancel the previous state immediately // no face detected, but let's not cancel the previous state immediately
@@ -917,30 +1069,58 @@ public class Cameradetail {
/** /**
* Remap LiveMatROI to BestMatROI and ReducedMatROI Resolution * Remap LiveMatROI to BestMatROI and ReducedMatROI Resolution
* @param scale scale factor, 1.0 for 100%, 0.5 for 50%, etc * @param scaleX scale factor for width
* @param scaleY scale factor for height
*/ */
public void RemapROI(double scale){ public void RemapROI(double scaleX, double scaleY){
BestMatROI = null;
ReducedMatROI = null;
if (ValidROI(LiveMatROI)){ if (ValidROI(LiveMatROI)){
if (ROIInsideUMat(LiveMatROI, LiveMat)){ if (ROIInsideUMat(LiveMatROI, LiveMat)){
System.out.println("LiveMatROI camera "+cameratitle.getText()+" = "+RectToString(LiveMatROI)); System.out.println("LiveMatROI camera "+cameratitle.getText()+" = "+RectToString(LiveMatROI));
double scaleXBest = scale*BestSize.width()/LiveSize.width(); double scaleXBest = 1.0*BestSize.width()/LiveSize.width();
double scaleYBest = scale*BestSize.height()/LiveSize.height(); 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);
System.out.println("scaleXBest = "+scaleXBest+" scaleYBest = "+scaleYBest); System.out.println("scaleXBest = "+scaleXBest+" scaleYBest = "+scaleYBest);
double scaleXReduced = scale*ReducedSize.width()/LiveSize.width();
double scaleYReduced = scale*ReducedSize.height()/LiveSize.height();
System.out.println("scaleXReduced = "+scaleXReduced+" scaleYReduced = "+scaleYReduced);
BestMatROI = ResizeRect(LiveMatROI, scaleXBest, scaleYBest, 50,250);
System.out.println("BestMatROI camera "+cameratitle.getText()+" = "+RectToString(BestMatROI)); System.out.println("BestMatROI camera "+cameratitle.getText()+" = "+RectToString(BestMatROI));
ReducedMatROI = ResizeRect(LiveMatROI, scaleXReduced, scaleYReduced, 50,250);
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);
System.out.println("scaleXReduced = "+scaleXReduced+" scaleYReduced = "+scaleYReduced);
System.out.println("ReducedMatROI camera "+cameratitle.getText()+" = "+RectToString(ReducedMatROI)); System.out.println("ReducedMatROI camera "+cameratitle.getText()+" = "+RectToString(ReducedMatROI));
} else { } //else System.out.println("LiveMatROI is Outside LiveMat for camera "+cameratitle.getText());
System.out.println("LiveMatROI is Outside LiveMat for camera "+cameratitle.getText()); } //else System.out.println("LiveMatROI is invalid for camera "+cameratitle.getText());
LiveMatROI = null;
}
} else System.out.println("LiveMatROI is invalid for camera "+cameratitle.getText());
} }

View File

@@ -4,6 +4,7 @@ import BASS.AudioPlayer;
import BASS.PlaybackStatus; import BASS.PlaybackStatus;
import Camera.*; import Camera.*;
import Config.CameraConfigEnum; import Config.CameraConfigEnum;
import Config.SomeCodes;
import Database.PhotoReviewClass; import Database.PhotoReviewClass;
import Database.Sqlite; import Database.Sqlite;
import ErhaAPI.ErhaAPI; import ErhaAPI.ErhaAPI;
@@ -172,206 +173,262 @@ public class CaptureView {
ExecutorService executor = Executors.newFixedThreadPool(5); ExecutorService executor = Executors.newFixedThreadPool(5);
// face detection Rect ROI to head detection Rect ROI Callable<PhotoResult> task1 = ()->{
// head is bigger than face, so we need to scale it
final double face_to_head_scale = 1.2;
Rect bestsize = new Rect(0,0,0,0);
Rect reducedsize = new Rect(0,0,0,0);
if (image1!=null) {
image1.RemapROI(face_to_head_scale);
if (image1.getBestMatROI()!=null && image1.getBestMatROI().width()>bestsize.width()) {
bestsize = image1.getBestMatROI();
System.out.println("BestSize: "+bestsize.width()+"x"+bestsize.height());
}
if (image1.getReducedMatROI()!=null && image1.getReducedMatROI().width()>reducedsize.width()) {
reducedsize = image1.getReducedMatROI();
System.out.println("ReducedSize: "+reducedsize.width()+"x"+reducedsize.height());
}
}
if (image2!=null) {
image2.RemapROI(face_to_head_scale);
if (image2.getBestMatROI()!=null && image2.getBestMatROI().width()>bestsize.width()) {
bestsize = image2.getBestMatROI();
System.out.println("BestSize: "+bestsize.width()+"x"+bestsize.height());
}
if (image2.getReducedMatROI()!=null && image2.getReducedMatROI().width()>reducedsize.width()) {
reducedsize = image2.getReducedMatROI();
System.out.println("ReducedSize: "+reducedsize.width()+"x"+reducedsize.height());
}
}
if (image3!=null) {
image3.RemapROI(face_to_head_scale);
if (image3.getBestMatROI()!=null && image3.getBestMatROI().width()>bestsize.width()) {
bestsize = image3.getBestMatROI();
System.out.println("BestSize: "+bestsize.width()+"x"+bestsize.height());
}
if (image3.getReducedMatROI()!=null && image3.getReducedMatROI().width()>reducedsize.width()) {
reducedsize = image3.getReducedMatROI();
System.out.println("ReducedSize: "+reducedsize.width()+"x"+reducedsize.height());
}
}
if (image4!=null) {
image4.RemapROI(face_to_head_scale);
if (image4.getBestMatROI()!=null && image4.getBestMatROI().width()>bestsize.width()) {
bestsize = image4.getBestMatROI();
System.out.println("BestSize: "+bestsize.width()+"x"+bestsize.height());
}
if (image4.getReducedMatROI()!=null && image4.getReducedMatROI().width()>reducedsize.width()) {
reducedsize = image4.getReducedMatROI();
System.out.println("ReducedSize: "+reducedsize.width()+"x"+reducedsize.height());
}
}
if (image5!=null) {
image5.RemapROI(face_to_head_scale);
if (image5.getBestMatROI()!=null && image5.getBestMatROI().width()>bestsize.width()) {
bestsize = image5.getBestMatROI();
System.out.println("BestSize: "+bestsize.width()+"x"+bestsize.height());
}
if (image5.getReducedMatROI()!=null && image5.getReducedMatROI().width()>reducedsize.width()) {
reducedsize = image5.getReducedMatROI();
System.out.println("ReducedSize: "+reducedsize.width()+"x"+reducedsize.height());
}
}
// find biggest BestROI and ReducedROI
final Rect finalbestsize = bestsize;
final Rect finalreducedsize = reducedsize;
Callable<String> task1 = ()->{
if (image1!=null) { if (image1!=null) {
image1.RemapROI(face_to_head_scale); image1.RemapROI(0.1,0.3);
PhotoResult p1 = image1.TakePhoto(directory,prefix, finalbestsize, finalreducedsize); PhotoResult p1 = image1.TakePhoto(directory,prefix);
if (ValidFile(p1.getFullres())) { //System.out.println("PhotoResult P1 :");
prc.setFileLeft90(p1.getFullres()); //System.out.println(p1);
String thumb1 = MakeThumbfile(p1.getFullres(), thumbsize); if (ValidFile(p1.getFullres())){
if (ValidFile(thumb1)) { if (ValidFile(p1.getCompressedfile())){
prc.setThumbLeft90(thumb1); return p1;
} }
} else System.out.println("Image1 ValidFile is false");
if (ValidFile(p1.getCompressedfile())){
prc.setCompressedLeft90(p1.getCompressedfile());
}
if (ValidFile(p1.getFullcrop())){
prc.setCroppedLeft90(p1.getFullcrop());
}
if (ValidFile(p1.getCompressedcrop())){
prc.setCompressedCropLeft90(p1.getCompressedcrop());
} }
} else System.out.println("Image1 is null"); } else System.out.println("Image1 is null");
return "Task 1 Done"; return null;
}; };
Callable<String> task2 = ()->{ Callable<PhotoResult> task2 = ()->{
if (image2!=null) { if (image2!=null) {
image2.RemapROI(face_to_head_scale); image2.RemapROI(0.1,0.3);
PhotoResult p2 = image2.TakePhoto(directory,prefix, finalbestsize, finalreducedsize); PhotoResult p2 = image2.TakePhoto(directory,prefix);
if (ValidFile(p2.getFullres())) { //System.out.println("PhotoResult P2 :");
prc.setFileLeft45(p2.getFullres()); //System.out.println(p2);
String thumb2 = MakeThumbfile(p2.getFullres(), thumbsize); if (ValidFile(p2.getFullres())){
if (ValidFile(thumb2)) prc.setThumbLeft45(thumb2); if (ValidFile(p2.getCompressedfile())){
} else System.out.println("Image2 ValidFile is false"); return p2;
if (ValidFile(p2.getCompressedfile())){ }
prc.setCompressedLeft45(p2.getCompressedfile());
}
if (ValidFile(p2.getFullcrop())){
prc.setCroppedLeft45(p2.getFullcrop());
}
if (ValidFile(p2.getCompressedcrop())){
prc.setCompressedCropLeft45(p2.getCompressedcrop());
} }
} else System.out.println("Image2 is null"); } else System.out.println("Image2 is null");
return "Task 2 Done"; return null;
}; };
Callable<String> task3 = ()->{ Callable<PhotoResult> task3 = ()->{
if (image3!=null) { if (image3!=null) {
image3.RemapROI(face_to_head_scale); image3.RemapROI(0.1,0.3);
PhotoResult p3 = image3.TakePhoto(directory,prefix, finalbestsize, finalreducedsize); PhotoResult p3 = image3.TakePhoto(directory,prefix);
if (ValidFile(p3.getFullres())) { //System.out.println("PhotoResult P3 :");
prc.setFileCenter(p3.getFullres()); //System.out.println(p3);
String thumb3 = MakeThumbfile(p3.getFullres(), thumbsize); if (ValidFile(p3.getFullres())){
if (ValidFile(thumb3)) prc.setThumbCenter(thumb3); if (ValidFile(p3.getCompressedfile())){
} else System.out.println("Image3 ValidFile is false"); return p3;
if (ValidFile(p3.getCompressedfile())){ }
prc.setCompressedCenter(p3.getCompressedfile());
}
if (ValidFile(p3.getFullcrop())){
prc.setCroppedCenter(p3.getFullcrop());
}
if (ValidFile(p3.getCompressedcrop())){
prc.setCompressedCropCenter(p3.getCompressedcrop());
} }
} else System.out.println("Image3 is null"); } else System.out.println("Image3 is null");
return "Task 3 Done"; return null;
}; };
Callable<String> task4 = ()->{ Callable<PhotoResult> task4 = ()->{
if (image4!=null) { if (image4!=null) {
image4.RemapROI(face_to_head_scale); image4.RemapROI(0.1,0.3);
PhotoResult p4 = image4.TakePhoto(directory,prefix, finalbestsize, finalreducedsize); PhotoResult p4 = image4.TakePhoto(directory,prefix);
if (ValidFile(p4.getFullres())) { //System.out.println("PhotoResult P4 :");
prc.setFileRight45(p4.getFullres()); //System.out.println(p4);
String thumb4 = MakeThumbfile(p4.getFullres(), thumbsize); if (ValidFile(p4.getFullres())){
if (ValidFile(thumb4)) prc.setThumbRight45(thumb4); if (ValidFile(p4.getCompressedfile())){
} else System.out.println("Image4 ValidFile is false"); return p4;
if (ValidFile(p4.getCompressedfile())){ }
prc.setCompressedRight45(p4.getCompressedfile());
}
if (ValidFile(p4.getFullcrop())){
prc.setCroppedRight45(p4.getFullcrop());
}
if (ValidFile(p4.getCompressedcrop())){
prc.setCompressedCropRight45(p4.getCompressedcrop());
} }
} else System.out.println("Image4 is null"); } else System.out.println("Image4 is null");
return "Task 4 Done"; return null;
}; };
Callable<String> task5 = ()->{ Callable<PhotoResult> task5 = ()->{
if (image5!=null) { if (image5!=null) {
image5.RemapROI(face_to_head_scale); image5.RemapROI(0.1,0.3);
PhotoResult p5 = image5.TakePhoto(directory,prefix, finalbestsize, finalreducedsize); PhotoResult p5 = image5.TakePhoto(directory,prefix);
if (ValidFile(p5.getFullres())) { //System.out.println("PhotoResult P5 :");
prc.setFileRight90(p5.getFullres()); //System.out.println(p5);
String thumb5 = MakeThumbfile(p5.getFullres(), thumbsize); if (ValidFile(p5.getFullres())){
if (ValidFile(thumb5)) prc.setThumbRight90(thumb5); if (ValidFile(p5.getCompressedfile())){
} else System.out.println("Image5 ValidFile is false"); return p5;
if (ValidFile(p5.getCompressedfile())){ }
prc.setCompressedRight90(p5.getCompressedfile());
}
if (ValidFile(p5.getFullcrop())){
prc.setCroppedRight90(p5.getFullcrop());
}
if (ValidFile(p5.getCompressedcrop())){
prc.setCompressedCropRight90(p5.getCompressedcrop());
} }
} else System.out.println("Image5 is null"); } else System.out.println("Image5 is null");
return "Task 5 Done"; return null;
}; };
PhotoResult p1 = null;
PhotoResult p2 = null;
PhotoResult p3 = null;
PhotoResult p4 = null;
PhotoResult p5 = null;
try{ try{
Future<String> f1 = executor.submit(task1); Future<PhotoResult> f1 = executor.submit(task1);
Future<String> f2 = executor.submit(task2); Future<PhotoResult> f2 = executor.submit(task2);
Future<String> f3 = executor.submit(task3); Future<PhotoResult> f3 = executor.submit(task3);
Future<String> f4 = executor.submit(task4); Future<PhotoResult> f4 = executor.submit(task4);
Future<String> f5 = executor.submit(task5); Future<PhotoResult> f5 = executor.submit(task5);
p1 = f1.get();
p2 = f2.get();
p3 = f3.get();
p4 = f4.get();
p5 = f5.get();
f1.get();
f2.get();
f3.get();
f4.get();
f5.get();
} catch (Exception e){ } catch (Exception e){
Logger.error("Error TakePhotos: " + e.getMessage()); Logger.error("Error TakePhotos: " + e.getMessage());
} finally { } finally {
executor.shutdown(); executor.shutdown();
} }
String timestamp = SomeCodes.GetDateTimeString();
System.out.println("Creating timestamp: "+timestamp);
Rect bestroi = null;
Rect reducedroi = null;
if (p1!=null && p1.getBestROI()!=null){
bestroi = p1.getBestROI();
reducedroi = p1.getReducedROI();
}
if (p2!=null && p2.getBestROI()!=null){
if (bestroi==null)
bestroi = p2.getBestROI();
else if (p2.getBestROI().area()>bestroi.area())
bestroi = p2.getBestROI();
if (reducedroi==null)
reducedroi = p2.getReducedROI();
else if (p2.getReducedROI().area()>reducedroi.area())
reducedroi = p2.getReducedROI();
}
if (p3!=null && p3.getBestROI()!=null){
if (bestroi==null)
bestroi = p3.getBestROI();
else if (p3.getBestROI().area()>bestroi.area())
bestroi = p3.getBestROI();
if (reducedroi==null)
reducedroi = p3.getReducedROI();
else if (p3.getReducedROI().area()>reducedroi.area())
reducedroi = p3.getReducedROI();
}
if (p4!=null && p4.getBestROI()!=null){
if (bestroi==null)
bestroi = p4.getBestROI();
else if (p4.getBestROI().area()>bestroi.area())
bestroi = p4.getBestROI();
if (reducedroi==null)
reducedroi = p4.getReducedROI();
else if (p4.getReducedROI().area()>reducedroi.area())
reducedroi = p4.getReducedROI();
}
if (p5!=null && p5.getBestROI()!=null){
if (bestroi==null)
bestroi = p5.getBestROI();
else if (p5.getBestROI().area()>bestroi.area())
bestroi = p5.getBestROI();
if (reducedroi==null)
reducedroi = p5.getReducedROI();
else if (p5.getReducedROI().area()>reducedroi.area())
reducedroi = p5.getReducedROI();
}
prc.setFileLeft90(p1.getFullres());
prc.setFileLeft45(p2.getFullres());
prc.setFileCenter(p3.getFullres());
prc.setFileRight45(p4.getFullres());
prc.setFileRight90(p5.getFullres());
prc.setCompressedLeft90(p1.getCompressedfile());
prc.setCompressedLeft45(p2.getCompressedfile());
prc.setCompressedCenter(p3.getCompressedfile());
prc.setCompressedRight45(p4.getCompressedfile());
prc.setCompressedRight90(p5.getCompressedfile());
if (ValidFile(p1.getFullcrop())){
// ada crop
prc.setCroppedLeft90(p1.getFullcrop());
} else {
String xx = image1.CropBestMat(directory,prefix, bestroi);
if (ValidFile(xx)) prc.setCroppedLeft90(xx);
}
if (ValidFile(p2.getFullcrop())){
// ada crop
prc.setCroppedLeft45(p2.getFullcrop());
} else {
String xx = image2.CropBestMat(directory,prefix, bestroi);
if (ValidFile(xx)) prc.setCroppedLeft45(xx);
}
if (ValidFile(p3.getFullcrop())){
// ada crop
prc.setCroppedCenter(p3.getFullcrop());
} else {
String xx = image3.CropBestMat(directory,prefix, bestroi);
if (ValidFile(xx)) prc.setCroppedCenter(xx);
}
if (ValidFile(p4.getFullcrop())){
// ada crop
prc.setCroppedRight45(p4.getFullcrop());
} else {
String xx = image4.CropBestMat(directory,prefix, bestroi);
if (ValidFile(xx)) prc.setCroppedRight45(xx);
}
if (ValidFile(p5.getFullcrop())){
// ada crop
prc.setCroppedRight90(p5.getFullcrop());
} else {
String xx = image5.CropBestMat(directory,prefix, bestroi);
if (ValidFile(xx)) prc.setCroppedRight90(xx);
}
if (ValidFile(p1.getCompressedcrop())){
prc.setCompressedCropLeft90(p1.getCompressedcrop());
} else {
String xx =image1.CropReducedMat(directory,prefix, reducedroi);
if (ValidFile(xx)) prc.setCompressedCropLeft90(xx);
}
if (ValidFile(p2.getCompressedcrop())){
prc.setCompressedCropLeft45(p2.getCompressedcrop());
} else {
String xx = image2.CropReducedMat(directory,prefix, reducedroi);
if (ValidFile(xx)) prc.setCompressedCropLeft45(xx);
}
if (ValidFile(p3.getCompressedcrop())){
prc.setCompressedCropCenter(p3.getCompressedcrop());
} else {
String xx = image3.CropReducedMat(directory,prefix, reducedroi);
if (ValidFile(xx)) prc.setCompressedCropCenter(xx);
}
if (ValidFile(p4.getCompressedcrop())){
prc.setCompressedCropRight45(p4.getCompressedcrop());
} else {
String xx = image4.CropReducedMat(directory,prefix, reducedroi);
if (ValidFile(xx)) prc.setCompressedCropRight45(xx);
}
if (ValidFile(p5.getCompressedcrop())){
prc.setCompressedCropRight90(p5.getCompressedcrop());
} else {
String xx= image5.CropReducedMat(directory,prefix, reducedroi);
if (ValidFile(xx)) prc.setCompressedCropRight90(xx);
}
String thumb1 = MakeThumbfile(p1.getFullres(), thumbsize);
if (ValidFile(thumb1)) prc.setThumbLeft90(thumb1);
String thumb2 = MakeThumbfile(p2.getFullres(), thumbsize);
if (ValidFile(thumb2)) prc.setThumbLeft45(thumb2);
String thumb3 = MakeThumbfile(p3.getFullres(), thumbsize);
if (ValidFile(thumb3)) prc.setThumbCenter(thumb3);
String thumb4 = MakeThumbfile(p4.getFullres(), thumbsize);
if (ValidFile(thumb4)) prc.setThumbRight45(thumb4);
String thumb5 = MakeThumbfile(p5.getFullres(), thumbsize);
if (ValidFile(thumb5)) prc.setThumbRight90(thumb5);
long duration = (System.nanoTime() - nanostart) / 1000000; // in milliseconds long duration = (System.nanoTime() - nanostart) / 1000000; // in milliseconds
System.out.println("TakePhotos duration: "+duration+" ms"); System.out.println("TakePhotos duration: "+duration+" ms");
Platform.runLater(()->{
progressanchor.getChildren().clear();
barcodeData.setText("");
medicalRecordID.setText("");
PatientName.setText("");
isTakingPhoto.set(false);
});
if (audioPlayer!=null && audioPlayer.isInited()){ if (audioPlayer!=null && audioPlayer.isInited()){
if (!audioPlayer.getCurrentFile().equals(audio_pengambilan_berhasil)) { if (!audioPlayer.getCurrentFile().equals(audio_pengambilan_berhasil)) {
audioPlayer.StopCurrentPlayback(); audioPlayer.StopCurrentPlayback();
@@ -382,6 +439,8 @@ public class CaptureView {
String[] files = prc.compressed(); String[] files = prc.compressed();
if (files.length>0){ if (files.length>0){
InsertSQL(prc); InsertSQL(prc);
@@ -435,6 +494,7 @@ public class CaptureView {
} }
audioPlayer.PlayFile(audio_upload_gagal, ps); audioPlayer.PlayFile(audio_upload_gagal, ps);
audioPlayer.WaitUntilFinished(); audioPlayer.WaitUntilFinished();
} }
}); });
@@ -442,10 +502,8 @@ public class CaptureView {
new Thread(uploadtask).start(); new Thread(uploadtask).start();
progressanchor.getChildren().clear();
barcodeData.setText("");
medicalRecordID.setText("");
PatientName.setText("");
// new Thread(()-> { // new Thread(()-> {
@@ -505,7 +563,7 @@ public class CaptureView {
} }
isTakingPhoto.set(false);
} }
private void UpdateBtnTakePhoto(){ private void UpdateBtnTakePhoto(){
@@ -843,9 +901,12 @@ public class CaptureView {
checkpatientID.setOnSucceeded(event -> { checkpatientID.setOnSucceeded(event -> {
PatientRecord pr = checkpatientID.getValue(); PatientRecord pr = checkpatientID.getValue();
if (pr!=null){ if (pr!=null){
int medrecid = toInt(pr.medical_record_detail_id); Platform.runLater(()->{
medicalRecordID.setText(medrecid+""); int medrecid = toInt(pr.medical_record_detail_id);
PatientName.setText(pr.name); medicalRecordID.setText(medrecid+"");
PatientName.setText(pr.name);
});
if (audioPlayer!=null && audioPlayer.isInited()){ if (audioPlayer!=null && audioPlayer.isInited()){
if (!audioPlayer.getCurrentFile().equals(audio_posisikan_muka)) { if (!audioPlayer.getCurrentFile().equals(audio_posisikan_muka)) {
audioPlayer.StopCurrentPlayback(); audioPlayer.StopCurrentPlayback();
@@ -858,9 +919,13 @@ public class CaptureView {
}); });
checkpatientID.setOnFailed(event -> { checkpatientID.setOnFailed(event -> {
medicalRecordID.setText(""); Platform.runLater(()->{
PatientName.setText(""); medicalRecordID.setText("");
barcodeData.setText(""); PatientName.setText("");
barcodeData.setText("");
isTakingPhoto.set(false);
});
System.out.println("checkpatientID failed"); System.out.println("checkpatientID failed");
}); });

View File

@@ -2,10 +2,7 @@ package id.co.gtc.erhacam;
import Config.SomeCodes; import Config.SomeCodes;
import lombok.NonNull; import lombok.NonNull;
import org.bytedeco.opencv.opencv_core.Rect; import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_core.RectVector;
import org.bytedeco.opencv.opencv_core.Size;
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;
@@ -79,7 +76,7 @@ public class Detectors {
} }
private static void LoadFrontalFaceDetector(){ private static void LoadFrontalFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml"); String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
if (filename!=null) { if (filename!=null) {
Logger.info("Face Detector file : " + filename); Logger.info("Face Detector file : " + filename);
if (frontalfaceDetector==null) { if (frontalfaceDetector==null) {
@@ -234,6 +231,21 @@ public class Detectors {
return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize); return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
} }
public static RectVector DetectFrontalFace(Mat graymat, int minsize, int maxsize){
Size min = new Size(minsize, minsize);
Size max = new Size(maxsize, maxsize);
RectVector rect = new RectVector();
frontalfaceDetector.detectMultiScale(graymat, rect,scaleFactor, minNeighbors, flags, min, max);
return rect;
}
public static RectVector DetectProfileFace(Mat graymat, int minsize, int maxsize){
Size min = new Size(minsize, minsize);
Size max = new Size(maxsize, maxsize);
RectVector rect = new RectVector();
profilefaceDetector.detectMultiScale(graymat, rect,scaleFactor, minNeighbors, flags, min, max);
return rect;
}
/** /**

View File

@@ -35,7 +35,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 17022025-103"); stage.setTitle("MultiCam Capture App for ERHA 18022025-032");
stage.setScene(scene); stage.setScene(scene);
stage.setResizable(true); stage.setResizable(true);
stage.setMaximized(true); stage.setMaximized(true);