Trial 11022025

This commit is contained in:
2025-02-11 09:10:36 +07:00
parent 30ef123832
commit 00f9852fa8
29 changed files with 596 additions and 281 deletions

View File

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

View File

@@ -602,6 +602,7 @@ public class ConfigFile {
Detectors.setScaleFactor(cascadeScaleFactor);
Logger.info("Config Loaded");
MakeDirectories();
return;
} else {
Logger.info("Config File Not Correct, Creating Default");
@@ -647,14 +648,15 @@ public class ConfigFile {
SetDefaultCameraConfig(ConfigRight90);
cascadeScaleFactor = 1.1;
cascadeMinNeighbors = 3;
cascadeMinSize = 200;
cascadeMaxSize = 400;
cascadeMinSize = 250;
cascadeMaxSize = 500;
Detectors.setFaceMaxSize(cascadeMaxSize);
Detectors.setFaceMinSize(cascadeMinSize);
Detectors.setScaleFactor(cascadeScaleFactor);
Logger.info("Default Config Created");
needsave = true;
Save();
MakeDirectories();
}
private void SetDefaultCameraConfig(CameraConfig cc){
@@ -714,4 +716,23 @@ public class ConfigFile {
Logger.error("Error Save Config: " + e.getMessage());
}
}
private @Getter String FullQualityDirectory;
private @Getter String FullQualityCropDirectory;
private @Getter String CompressedDirectory;
private @Getter String CompressedCropDirectory;
private @Getter String ThumbsDirectory;
private void MakeDirectories(){
String FullQualityDirectory = Path.of(PhotoDirectory,"FullQuality").toString();
String FullQualityCropDirectory = Path.of(PhotoDirectory,"FullQualityCrop").toString();
String CompressedDirectory = Path.of(PhotoDirectory,"Compressed").toString();
String CompressedCropDirectory = Path.of(PhotoDirectory,"CompressedCrop").toString();
String ThumbsDirectory = Path.of(PhotoDirectory,"thumbs").toString();
MakeDirectory(FullQualityDirectory);
MakeDirectory(FullQualityCropDirectory);
MakeDirectory(CompressedDirectory);
MakeDirectory(CompressedCropDirectory);
MakeDirectory(ThumbsDirectory);
}
}

View File

@@ -10,7 +10,9 @@ import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Rect;
import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_core.UMat;
import org.tinylog.Logger;
import java.awt.image.BufferedImage;
@@ -96,6 +98,14 @@ public class SomeCodes {
}
public static String RectToString(Rect rect){
if (rect!=null){
return "X:"+rect.x()+",Y:"+rect.y()+",W:"+rect.width()+",H:"+rect.height();
}
return "";
}
/**
* Find thumbfile in thumbs directory
* @param sourcejpg source jpg file
@@ -103,12 +113,7 @@ public class SomeCodes {
*/
public static String FindThumbfile(String sourcejpg){
File sourcefile = new File(sourcejpg);
Path thumbpath = Path.of(sourcefile.getParent(), "thumbs");
try{
if (!Files.exists(thumbpath)) Files.createDirectories(thumbpath);
} catch (Exception e){
Logger.error("Error creating thumbs directory: "+thumbpath+", Msg : "+e.getMessage());
}
Path thumbpath = Path.of(config.getThumbsDirectory());
Path thumbfile = thumbpath.resolve(sourcefile.getName());
if (Files.exists(thumbfile)){
return thumbfile.toString();
@@ -116,6 +121,22 @@ public class SomeCodes {
return null;
}
public static void Wait(int millis){
try{
Thread.sleep(millis);
} catch (Exception e){
Logger.error("Error waiting: "+e.getMessage());
}
}
public static Rect ScaleRect(Rect original, double scaleX, double scaleY){
if (original!=null){
return new Rect((int)(original.x()*scaleX), (int)(original.y()*scaleY),
(int)(original.width()*scaleX), (int)(original.height()*scaleY));
}
return null;
}
/**
* Make thumbfile from source jpg file
* @param sourcejpg source jpg file
@@ -126,23 +147,22 @@ public class SomeCodes {
try{
File ff = new File(sourcejpg);
if (ff.exists()){
Path thumbpath = Path.of(ff.getParent(), "thumbs");
if (!Files.exists(thumbpath)) Files.createDirectories(thumbpath);
String thumbfile = thumbpath.resolve(ff.getName()).toString();
String thumbfile = Path.of(config.getPhotoDirectory(),"thumbs", ff.getName()).toString();
File thumb = new File(thumbfile);
if (thumb.exists()) return thumbfile;
if (thumb.exists()) {
return thumbfile;
}
Mat source = opencv_imgcodecs.imread(sourcejpg);
if (source!=null && !source.empty()){
Mat resized = new Mat();
opencv_imgproc.resize(source, resized, thumbsize);
opencv_imgcodecs.imwrite(thumbfile, resized);
Logger.info("Thumbfile created: "+thumbfile);
return thumbfile;
} else Logger.info("MakeThumbfile failed, Source File not valid image : "+sourcejpg);
} else Logger.info("MakeThumbfile failed, Source File not found: "+sourcejpg);
}
}
} catch (Exception e){
Logger.error("Error making thumbfile: "+sourcejpg+", Msg : "+e.getMessage());
System.out.println("Error making thumbfile: "+sourcejpg+", Msg : "+e.getMessage());
}
return null;
}
@@ -290,8 +310,80 @@ public class SomeCodes {
return new String[0];
}
/**
* Check if Valid PatientID found
* Patient ID is 10 digits number
* @param patientid Patient ID
* @return true if valid, false if not valid
*/
public static boolean ValidPatientID(String patientid){
if (patientid!=null && patientid.length()==10){
boolean valid = true;
for(int i=0; i<patientid.length(); i++){
if (!Character.isDigit(patientid.charAt(i))){
valid = false;
break;
}
}
return valid;
} else return false;
}
public static boolean ValidROI(Rect ROI){
if (ROI!=null){
if (ROI.width()>0){
if (ROI.height()>0){
return true;
}
}
}
return false;
}
public static boolean ROIInsideUMat(Rect ROI, UMat mat){
if (ValidROI(ROI)){
if (mat!=null){
return ROI.x()>=0 && ROI.y()>=0 &&
ROI.x()+ROI.width()<=mat.cols() &&
ROI.y()+ROI.height()<=mat.rows();
}
}
return false;
}
public static boolean IsSameROI(Rect ROI1, Rect ROI2){
if (ValidROI(ROI1) && ValidROI(ROI2)){
return ROI1.x()==ROI2.x() && ROI1.y()==ROI2.y() &&
ROI1.width()==ROI2.width() && ROI1.height()==ROI2.height();
}
return false;
}
public static boolean IsInsideRect(Rect smaller, Rect bigger){
if (smaller!=null && bigger!=null){
return smaller.x()>=bigger.x() && smaller.y()>=bigger.y() &&
smaller.x()+smaller.width()<=bigger.x()+bigger.width() &&
smaller.y()+smaller.height()<=bigger.y()+bigger.height();
}
return false;
}
/**
* Make directory if not exists
* @param path directory path
*/
public static void MakeDirectory(String path){
if (ValidString(path)){
File ff = new File(path);
if (!ff.isDirectory()){
try{
Files.createDirectories(ff.toPath());
System.out.println("Directory created: "+path);
} catch (Exception e){
System.out.println("Error creating directory: "+path+", Msg : "+e.getMessage());
}
} else System.out.println("Directory exists: "+path);
}
}
}

View File

@@ -104,10 +104,18 @@ public class Cameradetail {
private final UMat BestMat = new UMat();
private final UMat LiveMat = new UMat();
private final UMat ReducedMat = new UMat();
private @Getter Rect BestMatROI;
private @Getter Rect ReducedMatROI;
private @Getter Rect LiveMatROI;
private Size LiveSize = new Size(640, 360);
private Size ReducedSize = new Size(1280, 720);
private Size BestSize = new Size(1920, 1080);
//TODO ini angka dari Erha, cek apakah masih cocok atau tidak
private @Getter @Setter Size FullCropSize = new Size(1036,1036);
public int getBestWidth(){
return BestSize.width();
}
@@ -116,6 +124,8 @@ public class Cameradetail {
return BestSize.height();
}
private void setSliderValue(Slider sld, CameraProperty prop, double value){
if (sld!=null){
sld.setMin(prop.Min);
@@ -531,12 +541,15 @@ public class Cameradetail {
* Take Photo from Camera
* @param directory directory to save the photo, if null, will use default directory
* @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
*/
@SuppressWarnings("BusyWait")
public String TakePhoto(String directory, String prefix) throws InterruptedException {
public String TakePhoto(String directory, String prefix, Rect ROI_Full, Rect ROI_Compressed) throws InterruptedException {
String result = null;
if (!ValidDirectory(directory)) directory = currentDirectory;
if (mGrabber!=null){
while(IsGrabbingLiveView.get()){
Thread.sleep(10);
@@ -562,18 +575,36 @@ public class Cameradetail {
int[] parampng = {opencv_imgcodecs.IMWRITE_PNG_COMPRESSION, 0};
// save BestMat at quality 9 PNG
String filename = Path.of(directory, makeFileName(prefix,".png")).toString();
String filename = Path.of(directory, "FullQuality", makeFileName(prefix,".png")).toString();
if (imwrite(filename, BestMat, parampng)){
raise_log("TakePhoto success, Photo saved to " + filename);
result = filename;
} else raise_log("TakePhoto failed, Unable to Save Photo");
} else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+cameratitle.getText());
if (ROIInsideUMat(ROI_Full, BestMat)){
// save ROI_Full at 100% JPEG
String roifilename = Path.of(directory, "FullQualityCrop", makeFileName(prefix,".png")).toString();
UMat ROI = new UMat(BestMat, ROI_Full);
if (!imwrite(roifilename, ROI, paramjpeg)){
System.out.println("TakePhoto failed, Unable to Save FullQUalityCrop for camera "+cameratitle.getText());
}
} else System.out.println("ROI_Full is outside of BestMat for camera "+cameratitle.getText());
// save ReducedMat at 100% JPEG
String reducedfilename = Path.of(directory, makeReducedFileName(prefix,".jpg")).toString();
String reducedfilename = Path.of(directory, "Compressed", makeReducedFileName(prefix,".jpg")).toString();
opencv_imgproc.resize(BestMat, ReducedMat, ReducedSize);
if (imwrite(reducedfilename, ReducedMat, paramjpeg)){
raise_log("TakePhoto success, Reduced Photo saved to " + reducedfilename);
} else raise_log("TakePhoto failed, Unable to Save Reduced Photo");
if (!imwrite(reducedfilename, ReducedMat, paramjpeg)){
System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+cameratitle.getText());
}
if (ROIInsideUMat(ROI_Compressed, ReducedMat)){
// save ROI_Compressed at 100% JPEG
String roifilename = Path.of(directory, "CompressedCrop", makeReducedFileName(prefix,".jpg")).toString();
UMat ROI = new UMat(ReducedMat, ROI_Compressed);
if (!imwrite(roifilename, ROI, paramjpeg)){
System.out.println("TakePhoto failed, Unable to Save CompressedCrop for camera "+cameratitle.getText());
}
} else System.out.println("ROI_Compressed is outside of ReducedMat for camera "+cameratitle.getText());
} else raise_log("TakePhoto failed, Live View is Empty");
} else raise_log("TakePhoto failed, Grabber is null");
@@ -642,7 +673,8 @@ public class Cameradetail {
protected Image call() {
// repeat until capturing is false
AtomicInteger fps = new AtomicInteger(0);
boolean eye_was_closed = false;
// eye state = -1 means unknown, 0 means closed, 1 means open
int eye_state = -1;
boolean waiting_for_second_blink = false;
long last_blink = 0;
@@ -667,6 +699,7 @@ public class Cameradetail {
int _face_height;
boolean have_palm = false;
boolean have_fist = false;
long no_face_counter = 0;
while (Capturing.get()) {
try {
@@ -690,11 +723,11 @@ public class Cameradetail {
opencv_imgproc.cvtColor(LiveMat,graymat, COLOR_BGR2GRAY); // convert to grayscale
if (use_qr){
String qr = DetectQRFromMat(graymat);
if (qr!=null) {
if (ValidPatientID(qr)){
if (!qr.equals(qrtext)){
qrtext = qr;
raise_log("QR Detected: " + qr);
if (event!=null) event.onDetectedQRCode(qr);
raise_log("QR Detected: " + qrtext);
if (event!=null) event.onDetectedQRCode(qrtext);
}
}
}
@@ -709,7 +742,7 @@ public class Cameradetail {
if (!frontalfaces.isEmpty()){
for(DetectorResult rect : frontalfaces){
if (rect.haveFace()){
if (rect.haveFace() ){
rect.FaceRectangle(LiveMat);
rect.EyesRectangle(LiveMat);
if (rect.getFaceWidth()>_face_width) _face_width = rect.getFaceWidth();
@@ -737,61 +770,79 @@ public class Cameradetail {
}
if (have_frontal_face){
no_face_counter = 0;
if (event!=null) event.onFrontalFaceDetector(true, _face_width, _face_height);
LiveMatROI = theface.getFace();
if (theface.haveEyes()){
// ada mata (buka mata)
if (eye_was_closed){
eye_was_closed = false;
if (eye_state==0){
// transisi dari tutup mata ke buka mata
//System.out.println("Eye Open Detected from camera "+cameratitle);
long now = System.currentTimeMillis();
if (waiting_for_second_blink){
long diff = now - last_blink;
// kalau beda waktu antara blink 1 dan blink 2 kurang dari 2 detik
if (diff<=2000){
// kalau beda waktu antara blink 1 dan blink 2 kurang dari 10 detik
if (diff<=10000){
waiting_for_second_blink = false;
System.out.println("Blink Detected from camera "+cameratitle);
if (event!=null) event.onBlink(2);
//System.out.println("Double Blink Detected from camera "+cameratitle);
if (event!=null) event.onBlink((int)diff);
}
} else {
last_blink = now;
waiting_for_second_blink = true;
//System.out.println("First Blink Detected from camera "+cameratitle);
}
last_blink = now;
}
eye_state = 1;
} else {
// tidak ada mata
// ada muka, tidak ada mata
// transisi dari buka mata ke tutup mata
if (!eye_was_closed){
eye_was_closed = true;
if (eye_state!=0){
//System.out.println("Eye Closed Detected from camera "+cameratitle);
}
eye_state = 0;
}
} else if (have_left_45_face ){
no_face_counter = 0;
LiveMatROI = theface.getFace();
if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height);
} else {
// no face at all
// no face detected, but lets not cancel the previous state immediately
if (no_face_counter>30){
// kalau tidak ada face selama 30 frame, reset state
// 30 frame approximately 2 second
eye_state = -1;
last_blink = 0;
waiting_for_second_blink = false;
if (event!=null) {
event.onFrontalFaceDetector(false, _face_width, _face_height);
event.onProfileFaceDetector(false, _face_width, _face_height);
}
} else no_face_counter++;
if (event!=null) {
event.onFrontalFaceDetector(false, _face_width, _face_height);
event.onProfileFaceDetector(false, _face_width, _face_height);
}
}
}
if (HavePalm(graymat)) {
if (!have_palm){
have_fist = false;
have_palm = true;
System.out.println("Palm Detected from camera " + cameratitle);
}
}
if (HaveFist(graymat)) {
if (!have_fist) {
have_palm = false;
have_fist = true;
System.out.println("Fist Detected from camera "+cameratitle);
}
}
// if (HavePalm(graymat)) {
// if (!have_palm){
// have_fist = false;
// have_palm = true;
// System.out.println("Palm Detected from camera " + cameratitle);
// }
// }
// if (HaveFist(graymat)) {
// if (!have_fist) {
// have_palm = false;
// have_fist = true;
// System.out.println("Fist Detected from camera "+cameratitle);
// }
// }
UMat rgbmat = new UMat(LiveMat.size(), CV_8UC3);
cvtColor(LiveMat, rgbmat, COLOR_BGR2RGB);
@@ -829,6 +880,27 @@ public class Cameradetail {
return false;
}
public void RemapROI(){
if (ValidROI(LiveMatROI)){
if (ROIInsideUMat(LiveMatROI, LiveMat)){
System.out.println("LiveMatROI camera "+cameratitle.getText()+" = "+RectToString(LiveMatROI));
double scaleXBest = 1.0*BestSize.width()/LiveSize.width();
double scaleYBest = 1.0*BestSize.height()/LiveSize.height();
double scaleXReduced = 1.0*ReducedSize.width()/LiveSize.width();
double scaleYReduced = 1.0*ReducedSize.height()/LiveSize.height();
BestMatROI = ScaleRect(LiveMatROI, scaleXBest, scaleYBest);
ReducedMatROI = ScaleRect(LiveMatROI, scaleXReduced, scaleYReduced);
} else {
System.out.println("LiveMatROI is Outside LiveMat for camera "+cameratitle.getText());
LiveMatROI = null;
}
} else System.out.println("LiveMatROI is invalid for camera "+cameratitle.getText());
}
/**
* Detect QR Code from Mat
* @param graymat Mat in Gray Scale

View File

@@ -22,9 +22,7 @@ import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@@ -55,15 +53,21 @@ public class CaptureView {
private TextArea directorypath, prefixfile;
@FXML
private Button btnTakePhoto;
@FXML
private Button btnAutoFocus;
@FXML
private AnchorPane progressanchor;
private AudioPlayer audioPlayer;
private String audio_posisikan_muka = "satu.wav";
private String audio_posisi_diam = "dua.wav";
private String audio_foto_selesai = "tiga.wav";
private String audio_ke_ruangtunggu = "empat.wav";
private String audio_posisikan_muka = "posisikan_wajah.wav";
private String audio_scan_barcode = "scan_barcode.wav";
private String audio_pengambilan_gagal = "pengambilan_gagal.wav";
private String audio_pengambilan_berhasil = "pengambilan_berhasil.wav";
private String audio_upload_berhasil = "upload_berhasil.wav";
private String audio_upload_gagal = "upload_gagal.wav";
private String audio_countdown = "countdown321.wav";
private List<String> cams;
@@ -114,166 +118,191 @@ public class CaptureView {
@FXML
private void TakePhotos(){
boolean has_face = Arrays.stream(have_face).anyMatch(AtomicBoolean::get);
if (!has_face){
audioPlayer.PlayFile(audio_posisikan_muka, ps);
return;
}
Size thumbsize = new Size(160,120);
String directory = directorypath.getText();
String prefix = RemoveSpaces(prefixfile.getText()) ;
if (ValidDirectory(directory)){
if (ValidString(prefix)){
isTakingPhoto.set(true);
//audioPlayer.PlayFile(audio_posisi_diam, ps);
PhotoReviewClass prc = new PhotoReviewClass();
prc.setPrefix(prefix);
if (has_face){
if (audioPlayer.isPlaying()) audioPlayer.StopCurrentPlayback();
audioPlayer.PlayFile(audio_countdown, ps);
long nanostart = System.nanoTime(); // for performance measurement
btnAutoFocus.fire();
ExecutorService executor = Executors.newFixedThreadPool(5);
Size thumbsize = new Size(160,120);
String directory = directorypath.getText();
String prefix = RemoveSpaces(prefixfile.getText()) ;
if (ValidDirectory(directory)){
if (ValidPatientID(prefix)){
Callable<String> task1 = ()->{
if (image1!=null) {
String p1 = image1.TakePhoto(directory,prefix);
if (ValidFile(p1)) {
Platform.runLater(()->image1.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p1)));
PhotoReviewClass prc = new PhotoReviewClass();
prc.setPrefix(prefix);
prc.setFileLeft90(p1);
String thumb1 = MakeThumbfile(p1, thumbsize);
if (ValidFile(thumb1)) prc.setThumbLeft90(thumb1);
long nanostart = System.nanoTime(); // for performance measurement
ExecutorService executor = Executors.newFixedThreadPool(5);
Callable<String> task1 = ()->{
if (image1!=null) {
image1.RemapROI();
String p1 = image1.TakePhoto(directory,prefix, image1.getBestMatROI(), image1.getReducedMatROI());
if (ValidFile(p1)) {
Platform.runLater(()->image1.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p1)));
prc.setFileLeft90(p1);
String thumb1 = MakeThumbfile(p1, thumbsize);
if (ValidFile(thumb1)) {
prc.setThumbLeft90(thumb1);
}
} else System.out.println("Image1 ValidFile is false");
} else System.out.println("Image1 is null");
return "Task 1 Done";
};
Callable<String> task2 = ()->{
if (image2!=null) {
image2.RemapROI();
String p2 = image2.TakePhoto(directory,prefix, image2.getBestMatROI(), image2.getReducedMatROI());
if (ValidFile(p2)) {
Platform.runLater(()->image2.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p2)));
prc.setFileLeft45(p2);
String thumb2 = MakeThumbfile(p2, thumbsize);
if (ValidFile(thumb2)) prc.setThumbLeft45(thumb2);
} else System.out.println("Image2 ValidFile is false");
} else System.out.println("Image2 is null");
return "Task 2 Done";
};
Callable<String> task3 = ()->{
if (image3!=null) {
image3.RemapROI();
String p3 = image3.TakePhoto(directory,prefix, image3.getBestMatROI(), image3.getReducedMatROI());
if (ValidFile(p3)) {
Platform.runLater(()->image3.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p3)));
prc.setFileCenter(p3);
String thumb3 = MakeThumbfile(p3, thumbsize);
if (ValidFile(thumb3)) prc.setThumbCenter(thumb3);
} else System.out.println("Image3 ValidFile is false");
} else System.out.println("Image3 is null");
return "Task 3 Done";
};
Callable<String> task4 = ()->{
if (image4!=null) {
image4.RemapROI();
String p4 = image4.TakePhoto(directory,prefix, image4.getBestMatROI(), image4.getReducedMatROI());
if (ValidFile(p4)) {
Platform.runLater(()->image4.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p4)));
prc.setFileRight45(p4);
String thumb4 = MakeThumbfile(p4, thumbsize);
if (ValidFile(thumb4)) prc.setThumbRight45(thumb4);
} else System.out.println("Image4 ValidFile is false");
} else System.out.println("Image4 is null");
return "Task 4 Done";
};
Callable<String> task5 = ()->{
if (image5!=null) {
image5.RemapROI();
String p5 = image5.TakePhoto(directory,prefix, image5.getBestMatROI(), image5.getReducedMatROI());
if (ValidFile(p5)) {
Platform.runLater(()->image5.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p5)));
prc.setFileRight90(p5);
String thumb5 = MakeThumbfile(p5, thumbsize);
if (ValidFile(thumb5)) prc.setThumbRight90(thumb5);
} else System.out.println("Image5 ValidFile is false");
} else System.out.println("Image5 is null");
return "Task 5 Done";
};
try{
Future<String> f1 = executor.submit(task1);
Future<String> f2 = executor.submit(task2);
Future<String> f3 = executor.submit(task3);
Future<String> f4 = executor.submit(task4);
Future<String> f5 = executor.submit(task5);
f1.get();
f2.get();
f3.get();
f4.get();
f5.get();
} catch (Exception e){
Logger.error("Error TakePhotos: " + e.getMessage());
} finally {
executor.shutdown();
}
long duration = (System.nanoTime() - nanostart) / 1000000; // in milliseconds
System.out.println("TakePhotos duration: "+duration+" ms");
if (audioPlayer.isPlaying()) {
if (!audio_pengambilan_berhasil.equals((audioPlayer.getCurrentFile()))){
audioPlayer.StopCurrentPlayback();
}
}
return "Task 1 Done";
};
Callable<String> task2 = ()->{
if (image2!=null) {
String p2 = image2.TakePhoto(directory,prefix);
if (ValidFile(p2)) {
Platform.runLater(()->image2.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p2)));
audioPlayer.PlayFile(audio_pengambilan_berhasil, ps);
String[] files = prc.files();
if (files!=null && files.length>0){
InsertSQL(prc);
prc.setFileLeft45(p2);
String thumb2 = MakeThumbfile(p2, thumbsize);
if (ValidFile(thumb2)) prc.setThumbLeft45(thumb2);
}
progressanchor.getChildren().clear();
prefixfile.setText("");
//TODO ganti ke API upload
// new Thread(()-> {
// try{
// InetAddress target = InetAddress.getByName(config.getFTPHost());
// int port = toInt(config.getFTPPort());
// if (target.isReachable(2000)){
// Socket socket = new Socket();
// InetSocketAddress isa = new InetSocketAddress(target, port);
// socket.connect(isa,2000);
// socket.close();
// // sampai sini berarti FTP Host reachable
// UploadToFTP(files);
// } else throw new Exception("FTP Host not reachable");
// } catch (Exception e){
// Logger.error("Error UploadToFTP: "+e.getMessage());
// Platform.runLater(()->{
// Alert alert = new Alert(AlertType.ERROR);
// alert.setTitle("Error");
// alert.setHeaderText("Upload to FTP Failed");
// alert.setContentText("Error: "+e.getMessage());
// alert.showAndWait();
// });
//
// }
// }).start();
} else {
Alert Alert = new Alert(AlertType.ERROR);
Alert.setTitle("Error");
Alert.setHeaderText("No Photos Taken");
Alert.setContentText("No Photos Taken, please check camera");
Alert.showAndWait();
}
return "Task 2 Done";
};
Callable<String> task3 = ()->{
if (image3!=null) {
String p3 = image3.TakePhoto(directory,prefix);
if (ValidFile(p3)) {
Platform.runLater(()->image3.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p3)));
prc.setFileCenter(p3);
String thumb3 = MakeThumbfile(p3, thumbsize);
if (ValidFile(thumb3)) prc.setThumbCenter(thumb3);
}
}
return "Task 3 Done";
};
Callable<String> task4 = ()->{
if (image4!=null) {
String p4 = image4.TakePhoto(directory,prefix);
if (ValidFile(p4)) {
Platform.runLater(()->image4.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p4)));
prc.setFileRight45(p4);
String thumb4 = MakeThumbfile(p4, thumbsize);
if (ValidFile(thumb4)) prc.setThumbRight45(thumb4);
}
}
return "Task 4 Done";
};
Callable<String> task5 = ()->{
if (image5!=null) {
String p5 = image5.TakePhoto(directory,prefix);
if (ValidFile(p5)) {
Platform.runLater(()->image5.setCameraStatus("Photo: "+ SomeCodes.GetFileName(p5)));
prc.setFileRight90(p5);
String thumb5 = MakeThumbfile(p5, thumbsize);
if (ValidFile(thumb5)) prc.setThumbRight90(thumb5);
}
}
return "Task 5 Done";
};
try{
Future<String> f1 = executor.submit(task1);
Future<String> f2 = executor.submit(task2);
Future<String> f3 = executor.submit(task3);
Future<String> f4 = executor.submit(task4);
Future<String> f5 = executor.submit(task5);
f1.get();
f2.get();
f3.get();
f4.get();
f5.get();
} catch (Exception e){
Logger.error("Error TakePhotos: " + e.getMessage());
} finally {
executor.shutdown();
}
long duration = (System.nanoTime() - nanostart) / 1000000; // in milliseconds
System.out.println("TakePhotos duration: "+duration+" ms");
// TODO test taruh sini
isTakingPhoto.set(false);
audioPlayer.PlayFile(audio_foto_selesai, ps);
String[] files = prc.files();
if (files!=null && files.length>0){
InsertSQL(prc);
progressanchor.getChildren().clear();
prefixfile.setText("");
new Thread(()-> {
try{
InetAddress target = InetAddress.getByName(config.getFTPHost());
int port = toInt(config.getFTPPort());
if (target.isReachable(2000)){
Socket socket = new Socket();
InetSocketAddress isa = new InetSocketAddress(target, port);
socket.connect(isa,2000);
socket.close();
// sampai sini berarti FTP Host reachable
UploadToFTP(files);
} else throw new Exception("FTP Host not reachable");
} catch (Exception e){
Logger.error("Error UploadToFTP: "+e.getMessage());
Platform.runLater(()->{
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Upload to FTP Failed");
alert.setContentText("Error: "+e.getMessage());
alert.showAndWait();
});
}
}).start();
} else {
Alert Alert = new Alert(AlertType.ERROR);
Alert.setTitle("Error");
Alert.setHeaderText("No Photos Taken");
Alert.setContentText("No Photos Taken, please check camera");
Alert.setHeaderText("Invalid Prefix");
Alert.setContentText("Please input valid prefix or scan QR Code");
Alert.showAndWait();
}
} else {
Alert Alert = new Alert(AlertType.ERROR);
Alert.setTitle("Error");
Alert.setHeaderText("Invalid Prefix");
Alert.setContentText("Please input valid prefix or scan QR Code");
Alert.setHeaderText("Invalid Directory");
Alert.setContentText("Please select valid directory");
Alert.showAndWait();
}
} else {
Alert Alert = new Alert(AlertType.ERROR);
Alert.setTitle("Error");
Alert.setHeaderText("Invalid Directory");
Alert.setContentText("Please select valid directory");
Alert.showAndWait();
if (audioPlayer.isPlaying()) {
if (!audio_posisikan_muka.equals((audioPlayer.getCurrentFile()))){
audioPlayer.StopCurrentPlayback();
}
}
audioPlayer.PlayFile(audio_posisikan_muka, ps);
}
isTakingPhoto.set(false);
}
private void UpdateBtnTakePhoto(){
@@ -283,10 +312,13 @@ public class CaptureView {
@FXML
public void initialize(){
audio_posisikan_muka = ExtractResource("/satu.wav");
audio_posisi_diam = ExtractResource("/dua.wav");
audio_foto_selesai = ExtractResource("/tiga.wav");
audio_ke_ruangtunggu = ExtractResource("/empat.wav");
audio_posisikan_muka = ExtractResource("/posisikan_wajah.wav");
audio_pengambilan_berhasil = ExtractResource("/pengambilan_berhasil.wav");
audio_pengambilan_gagal = ExtractResource("/pengambilan_gagal.wav");
audio_scan_barcode = ExtractResource("/scan_barcode.wav");
audio_upload_berhasil = ExtractResource("/upload_berhasil.wav");
audio_upload_gagal = ExtractResource("/upload_gagal.wav");
audio_countdown = ExtractResource("/countdown321.wav");
audioPlayer = new AudioPlayer(1,48000);
Logger.info("Audio Player : "+(audioPlayer.isInited()? "Inited" : "Not Inited"));
@@ -416,12 +448,16 @@ public class CaptureView {
public void onPlaybackStarted(String filename) {
if (filename.contains(audio_posisikan_muka)){
Logger.info("Audio Positikan Muka Started");
} else if (filename.contains(audio_posisi_diam)){
Logger.info("Audio Posisi Diam Started");
} else if (filename.contains(audio_foto_selesai)){
Logger.info("Audio Foto Selesai Started");
} else if (filename.contains(audio_ke_ruangtunggu)){
Logger.info("Audio Ke Ruang Tunggu Started");
} else if (filename.contains(audio_pengambilan_berhasil)){
Logger.info("Audio Pengambilan Berhasil Started");
} else if (filename.contains(audio_pengambilan_gagal)){
Logger.info("Audio Pengambilan Gagal Started");
} else if (filename.contains(audio_scan_barcode)){
Logger.info("Audio Scan Barcode Started");
} else if (filename.contains(audio_upload_berhasil)){
Logger.info("Audio Upload Berhasil Started");
} else if (filename.contains(audio_upload_gagal)){
Logger.info("Audio Upload Gagal Started");
}
}
@@ -429,12 +465,16 @@ public class CaptureView {
public void onPlaybackFinished(String filename) {
if (filename.contains(audio_posisikan_muka)){
Logger.info("Audio Positikan Muka Finished");
} else if (filename.contains(audio_posisi_diam)){
Logger.info("Audio Posisi Diam Finished");
} else if (filename.contains(audio_foto_selesai)){
Logger.info("Audio Foto Selesai Finished");
} else if (filename.contains(audio_ke_ruangtunggu)){
Logger.info("Audio Ke Ruang Tunggu Finished");
} else if (filename.contains(audio_scan_barcode)){
Logger.info("Audio Scan Barcode Finished");
} else if (filename.contains(audio_upload_berhasil)){
Logger.info("Audio Upload Berhasil Finished");
} else if (filename.contains(audio_upload_gagal)){
Logger.info("Audio Upload Gagal Finished");
} else if (filename.contains(audio_pengambilan_berhasil)){
Logger.info("Audio Pengambilan Berhasil Finished");
} else if (filename.contains(audio_pengambilan_gagal)){
Logger.info("Audio Pengambilan Gagal Finished");
}
}
@@ -442,12 +482,16 @@ public class CaptureView {
public void onPlaybackFailure(String filename) {
if (filename.contains(audio_posisikan_muka)){
Logger.info("Audio Positikan Muka Failure");
} else if (filename.contains(audio_posisi_diam)){
Logger.info("Audio Posisi Diam Failure");
} else if (filename.contains(audio_foto_selesai)){
Logger.info("Audio Foto Selesai Failure");
} else if (filename.contains(audio_ke_ruangtunggu)){
Logger.info("Audio Ke Ruang Tunggu Failure");
} else if (filename.contains(audio_upload_gagal)){
Logger.info("Audio Upload Gagal Failure");
} else if (filename.contains(audio_upload_berhasil)){
Logger.info("Audio Upload Berhasil Failure");
} else if (filename.contains(audio_pengambilan_berhasil)){
Logger.info("Audio Pengambilan Berhasil Failure");
} else if (filename.contains(audio_pengambilan_gagal)){
Logger.info("Audio Pengambilan Gagal Failure");
} else if (filename.contains(audio_scan_barcode)){
Logger.info("Audio Scan Barcode Failure");
}
}
};
@@ -564,50 +608,72 @@ public class CaptureView {
LiveCamEvent lce = new LiveCamEvent() {
@Override
public void onDetectedQRCode(String qrCode) {
Platform.runLater(()->prefixfile.setText(RemoveSpaces(qrCode)));
//if (ValidString(qrCode)) audioPlayer.PlayFile(audio_posisikan_muka, ps);
qrCode = RemoveSpaces(qrCode);
if (ValidPatientID(qrCode)){
String prefix = prefixfile.getText();
if (!qrCode.equals(prefix)){
String finalQrCode = qrCode;
System.out.println("PatientID detected: "+finalQrCode);
Platform.runLater(()->prefixfile.setText(finalQrCode));
if (audioPlayer.isPlaying()) {
if (!audio_posisikan_muka.equals((audioPlayer.getCurrentFile()))){
audioPlayer.StopCurrentPlayback();
}
}
audioPlayer.PlayFile(audio_posisikan_muka, ps);
}
}
}
@Override
public void onFrontalFaceDetector(boolean hasface, int width, int height) {
_have_face.set(hasface);
update_status(image);
if (hasface!= _have_face.get()){
_have_face.set(hasface);
update_status(image);
}
}
@Override
public void onProfileFaceDetector(boolean hasface, int width, int height) {
_have_profile.set(hasface);
update_status(image);
if (hasface!= _have_profile.get()){
_have_profile.set(hasface);
update_status(image);
}
}
@Override
public void onEyeDetector(boolean hasEye, int width, int height) {
_have_eye.set(hasEye);
update_status(image);
// _have_eye.set(hasEye);
// update_status(image);
}
@Override
public void onLeftEarDetector(boolean hasLeftEar, int width, int height) {
_have_left_ear.set(hasLeftEar);
update_status(image);
// _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);
// _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);
// _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);
// _have_right_eye.set(hasRightEye);
// update_status(image);
}
@Override
@@ -618,23 +684,26 @@ public class CaptureView {
@Override
public void onBlink(int counter) {
if (isTakingPhoto.get()) return; // other camera is taking picture
System.out.println("Blink detected at camera "+title+" delay= "+counter);
isTakingPhoto.set(true);
Platform.runLater(()->{
// System.out.println("Blink detected at camera "+title+" counter: "+counter);
// Platform.runLater(()->{
// Alert Alert = new Alert(AlertType.INFORMATION);
// Alert.setTitle("Blink Detected");
// Alert.setHeaderText("Blink Detected");
// Alert.setContentText("Blink Detected at Camera "+title+" counter: "+counter);
// Alert.show();
//
// String prefix = prefixfile.getText();
// //TODO Pastikan Nomor Pelanggan 8 digit
// if (prefix.length()>=8){
// if (isTakingPhoto.get()) return; // other camera already detect blinking
// btnTakePhoto.fire();
// }
// });
String prefix = prefixfile.getText();
if (prefix.length()==10){
System.out.println("Prefix valid, taking photo");
btnTakePhoto.fire();
} else {
System.out.println("Prefix not valid, not taking photo");
isTakingPhoto.set(false);
if (audioPlayer.isPlaying()) {
if (!audio_scan_barcode.equals((audioPlayer.getCurrentFile()))){
audioPlayer.StopCurrentPlayback();
}
}
audioPlayer.PlayFile(audio_scan_barcode, ps);
}
});
}
@@ -739,6 +808,7 @@ public class CaptureView {
}
}
@Deprecated
private void UploadToFTP(String[] files){
final double uploadprogressheight = 50;
@@ -846,7 +916,8 @@ public class CaptureView {
public void onUploadFinished(int total, int success, int failed, String[] files) {
Logger.info("Upload Finished, Total: {}, Success: {}, Failed: {}", total, success, failed);
Platform.runLater(()->{
audioPlayer.PlayFile(audio_ke_ruangtunggu, ps);
if (audioPlayer.isPlaying()) audioPlayer.StopCurrentPlayback();
audioPlayer.PlayFile(audio_upload_berhasil, ps);
Alert Alert = new Alert(AlertType.INFORMATION);
Alert.setTitle("Upload Finished");
Alert.setHeaderText("Upload Finished");

View File

@@ -51,4 +51,9 @@ public class DetectorResult {
public boolean haveEyes(){
return Eyes != null && !Eyes.isEmpty();
}
public int getEyesCount(){
if (!haveEyes()) return 0;
return Eyes.size();
}
}

View File

@@ -12,6 +12,8 @@ import org.tinylog.Logger;
import java.util.ArrayList;
import java.util.List;
import static Config.SomeCodes.IsInsideRect;
public class Detectors {
public static CascadeClassifier frontalfaceDetector;
private static CascadeClassifier eyeDetector;
@@ -20,7 +22,18 @@ public class Detectors {
private static CascadeClassifier palmDetector;
private static CascadeClassifier fistDetector;
private static double scaleFactor = 1.1;
private final static int minNeighbors = 3;
private final static int flags = 0;
private static Size FaceminSize;
private static Size FacemaxSize;
private static final int EyetoFaceRatio = 6;
private static Size EyeminSize;
private static Size EyemaxSize;
public static void LoadAllDetectors(){
LoadFrontalFaceDetector();
LoadEyeDetector();
@@ -146,10 +159,7 @@ public class Detectors {
dr.setFace(face);
if (eyes!=null && eyes.size()>=2){
for(Rect eye : eyes.get()){
if (eye.x() < face.x() || eye.y() < face.y() || eye.x() + eye.width() > face.x() + face.width() || eye.y() + eye.height() > face.y() + face.height()){
continue;
}
dr.AddEye(eye);
if (IsInsideRect(eye, face)) dr.AddEye(eye);
}
}
result.add(dr);
@@ -169,10 +179,7 @@ public class Detectors {
dr.setFace(face);
if (eyes!=null && eyes.size()>0){
for(Rect eye : eyes.get()){
if (eye.x() < face.x() || eye.y() < face.y() || eye.x() + eye.width() > face.x() + face.width() || eye.y() + eye.height() > face.y() + face.height()){
continue;
}
dr.AddEye(eye);
if (IsInsideRect(eye, face)) dr.AddEye(eye);
}
}
result.add(dr);
@@ -183,32 +190,43 @@ public class Detectors {
private static double scaleFactor = 1.1;
private final static int minNeighbors = 3;
private final static int flags = 0;
private static Size FaceminSize = new Size(200,200);
private static Size FacemaxSize = new Size(500,500);
private static final int EyetoFaceRatio = 6;
private static Size EyeminSize = new Size(FaceminSize.width()/EyetoFaceRatio,FaceminSize.height()/EyetoFaceRatio);
private static Size EyemaxSize = new Size(FacemaxSize.width()/EyetoFaceRatio,FacemaxSize.height()/EyetoFaceRatio);
public static void setScaleFactor(double value){
if (scaleFactor!=value) scaleFactor = value;
}
public static void setFaceMinSize(int value){
if (FaceminSize.width()!=value || FaceminSize.height()!=value) {
if (FaceminSize!=null){
if (FaceminSize.width()!=value || FaceminSize.height()!=value) {
FaceminSize = new Size(value, value);
EyeminSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
System.out.println("FaceMinSize changed to : " + FaceminSize.width());
System.out.println("EyeMinSize changed to : " + EyeminSize.width());
}
} else {
FaceminSize = new Size(value, value);
EyeminSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
System.out.println("FaceMinSize created with value : " + FaceminSize.width());
System.out.println("EyeMinSize created with value : " + EyeminSize.width());
}
}
public static void setFaceMaxSize(int value){
if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) {
if (FacemaxSize!=null){
if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) {
FacemaxSize = new Size(value, value);
EyemaxSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
System.out.println("FaceMaxSize changed to : " + FacemaxSize.width());
System.out.println("EyeMaxSize changed to : " + EyemaxSize.width());
}
} else {
FacemaxSize = new Size(value, value);
EyemaxSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
System.out.println("FaceMaxSize created with value : " + FacemaxSize.width());
System.out.println("EyeMaxSize created with value : " + EyemaxSize.width());
}
}

View File

@@ -21,7 +21,7 @@ public class MainApplication extends Application {
Screen screen = Screen.getPrimary();
Rectangle2D screenbound = screen.getVisualBounds();
Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight());
stage.setTitle("MultiCam Capture App for ERHA 03022025-033");
stage.setTitle("MultiCam Capture App for ERHA 03022025-070");
stage.setScene(scene);
stage.setResizable(true);
stage.setMaximized(true);
@@ -37,6 +37,8 @@ public class MainApplication extends Application {
stage.show();
Logger.info("Application started");
}
public static void main(String[] args) {

View File

@@ -78,7 +78,7 @@
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<Button layoutX="72.0" layoutY="35.0" mnemonicParsing="false" onAction="#AutoFocus" prefHeight="70.0" prefWidth="171.0" text="Auto Focus" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
<Button fx:id="btnAutoFocus" layoutX="72.0" layoutY="35.0" mnemonicParsing="false" onAction="#AutoFocus" prefHeight="70.0" prefWidth="171.0" text="Auto Focus" wrapText="true" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2">