commit 10/04/2025

This commit is contained in:
rdkartono
2025-04-10 16:21:56 +07:00
parent 7cdefa6f1d
commit b6a3076993
23 changed files with 420 additions and 119681 deletions

View File

@@ -3,6 +3,8 @@ package BASS;
import lombok.Getter;
import org.tinylog.Logger;
import static Config.SomeCodes.Wait;
@SuppressWarnings("unused")
public class AudioPlayer {
@@ -13,10 +15,7 @@ public class AudioPlayer {
public void WaitUntilFinished(){
while(currentFileHandle!=0){
try {
Thread.sleep(10);
} catch (InterruptedException ignored) {
}
Wait(10);
}
}
@@ -109,7 +108,7 @@ public class AudioPlayer {
if (bass.BASS_ChannelStart(filehandle)){
currentFile = filename;
currentFileHandle = filehandle;
new Thread(()->{
Thread pl = new Thread(() -> {
if (playbackstatus!=null) playbackstatus.onPlaybackStarted(filename);
boolean iscontinue = true;
while(iscontinue){
@@ -122,18 +121,17 @@ public class AudioPlayer {
iscontinue = false;
break;
default : {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
iscontinue = false;
}
Wait(100);
}
}
}
if (playbackstatus!=null) playbackstatus.onPlaybackFinished(filename);
currentFile = "";
currentFileHandle = 0;
}).start();
});
pl.setDaemon(true);
pl.start();
} else {
Logger.error("AudioPlayer PlayFile failed, BASS_ChannelStart failed, error code: "+bass.BASS_ErrorGetCode());
if (playbackstatus!=null) playbackstatus.onPlaybackFailure(filename);

View File

@@ -7,6 +7,8 @@ import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
@@ -19,7 +21,6 @@ import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_core.UMat;
import org.tinylog.Logger;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
@@ -512,9 +513,7 @@ public class SomeCodes {
if (ROI.x()>=0){
if (ROI.y()>=0){
if (ROI.width()>0){
if (ROI.height()>0){
return true;
}
return ROI.height() > 0;
}
}
}
@@ -523,7 +522,7 @@ public class SomeCodes {
}
public static void Print(String... x){
if (x!=null && x.length>0){
if (x != null){
for(String xx : x){
System.out.println(xx);
}
@@ -604,53 +603,72 @@ public class SomeCodes {
}
}
public static void SetText(Object obj, String text){
if (obj!=null && ValidString(text)){
if (Platform.isFxApplicationThread()){
if (obj instanceof Label lbl){
if (text.equals(lbl.getText())) return;
public static void LabelSetText(Label lbl, String text, String style){
if (lbl!=null){
if (text!=null){
if (text.equals(lbl.getText())) return;
if (Platform.isFxApplicationThread()){
lbl.setText(text);
} else if (obj instanceof TextArea ta){
if (text.equals(ta.getText())) return;
ta.setText(text);
} else if (obj instanceof TextField tf){
if (text.equals(tf.getText())) return;
tf.setText(text);
}
} else{
Platform.runLater(()->{
if (obj instanceof Label lbl){
if (text.equals(lbl.getText())) return;
lbl.setText(text);
} else if (obj instanceof TextArea ta){
if (text.equals(ta.getText())) return;
ta.setText(text);
} else if (obj instanceof TextField tf){
if (text.equals(tf.getText())) return;
tf.setText(text);
if (style!=null && !style.isBlank()){
lbl.setStyle(style);
}
});
} else{
Platform.runLater(()-> {
lbl.setText(text);
if (style!=null && !style.isBlank()){
lbl.setStyle(style);
}
});
}
}
}
}
public static void TextAreaSetText(TextArea ta, String text){
if (ta!=null){
if (text!=null){
if (text.equals(ta.getText())) return;
if (Platform.isFxApplicationThread()){
ta.setText(text);
} else{
Platform.runLater(()-> ta.setText(text));
}
}
}
}
public static void TextFieldSetText(TextField tf, String text){
if (tf!=null){
if (text!=null){
if (text.equals(tf.getText())) return;
if (Platform.isFxApplicationThread()){
tf.setText(text);
} else{
Platform.runLater(()-> tf.setText(text));
}
}
}
}
public static void LabelVisible(Label label, boolean visible){
if (label!=null){
if (visible){
if (Platform.isFxApplicationThread()){
label.setVisible(true);
} else{
Platform.runLater(()->{
label.setVisible(true);
});
Platform.runLater(()-> label.setVisible(true));
}
} else {
if (Platform.isFxApplicationThread()){
label.setVisible(false);
} else{
Platform.runLater(()->{
label.setVisible(false);
});
Platform.runLater(()-> label.setVisible(false));
}
}
}

View File

@@ -3,10 +3,8 @@ package SecureDongle;
import lombok.Getter;
import lombok.Setter;
import org.tinylog.Logger;
import java.util.function.Consumer;
import static Config.SomeCodes.ToShort;
import static Config.SomeCodes.Wait;
public class SecureDongle {
@@ -108,6 +106,7 @@ public class SecureDongle {
* Close SecureDongle
* @return true if success
*/
@SuppressWarnings("UnusedReturnValue")
public boolean Close(){
handle[0] = Handle;
short result = SD.SecureDongle(LibSecureDongle.SD_CLOSE, handle, lp1, lp2, p1, p2, p3, p4, buffer);
@@ -118,12 +117,40 @@ public class SecureDongle {
return false;
}
/**
* Write to User Data Zone (UDZ)
* @param StartAddress start address of UDZ, zero based
* @param length length of data to write, max 1000 bytes
* @param data data to write
* @return true if success
*/
@SuppressWarnings("unused")
public boolean Write(short StartAddress, short length, byte[] data){
if (Opened){
handle[0] = Handle;
p1[0] = StartAddress>=0 ? StartAddress : 0;
if (length<1) length=1;
if (length>1000) length=1000;
p2[0] = length;
System.arraycopy(data, 0, buffer, 0, length);
short result = SD.SecureDongle(LibSecureDongle.SD_WRITE, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" write success ");
return true;
} else if (event!=null) event.onDongleError("Write", result);
} //else System.out.println("SecureDongle not opened");
return false;
}
/**
* Read from User Data Zone (UDZ)
* @param StartAddress Start Address, zero based
* @param Length Length of data to read, max 1000 bytes
* @return byte array of data, length=0 if failed
*/
@SuppressWarnings("unused")
public byte[] Read(short StartAddress, short Length){
if (Opened){
handle[0] = Handle;
@@ -143,35 +170,11 @@ public class SecureDongle {
return new byte[0];
}
/**
* Write to User Data Zone (UDZ)
* @param StartAddress start address of UDZ, zero based
* @param length length of data to write, max 1000 bytes
* @param data data to write
* @return true if success
*/
public boolean Write(short StartAddress, short length, byte[] data){
if (Opened){
handle[0] = Handle;
p1[0] = StartAddress>=0 ? StartAddress : 0;
if (length<1) length=1;
if (length>1000) length=1000;
p2[0] = length;
System.arraycopy(data, 0, buffer, 0, length);
short result = SD.SecureDongle(LibSecureDongle.SD_WRITE, handle, lp1, lp2, p1, p2, p3, p4, buffer);
if (result== LibSecureDongle.ERR_SUCCESS){
//System.out.println("SecureDongle HardwareID="+HardwareID+" write success ");
return true;
} else if (event!=null) event.onDongleError("Write", result);
} //else System.out.println("SecureDongle not opened");
return false;
}
/**
* Generate Random Number
* @return short array of random number
*/
@SuppressWarnings("unused")
public short[] GenerateRandomNumber(){
short[] random = new short[4];
if (Opened){
@@ -195,6 +198,7 @@ public class SecureDongle {
* @param UserID UserID to write
* @return true if success
*/
@SuppressWarnings("unused")
public boolean WriteUserID(int UserID){
if (Opened){
handle[0] = Handle;
@@ -242,7 +246,7 @@ public class SecureDongle {
* if dongle missing, will raise event onDongleMissing
*/
public void StartMonitor(){
new Thread(()->{
Thread tx = new Thread(()->{
if (HardwareID==0) Find();
Open();
int firstUserID = ReadUserID();
@@ -251,11 +255,7 @@ public class SecureDongle {
ismonitoring = true;
Logger.info("Start Monitoring UserID="+Integer.toHexString(firstUserID));
while (ismonitoring){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Wait(5000);
Open();
int newUserID = ReadUserID();
Close();
@@ -267,7 +267,9 @@ public class SecureDongle {
System.out.println("Stop Monitoring");
} else System.out.println("Canceled Monitoring, UserID not found");
}).start();
});
tx.setDaemon(true);
tx.start();
}
}

View File

@@ -1,7 +1,14 @@
package id.co.gtc.erhacam;
import javafx.animation.KeyFrame;
import javafx.animation.PauseTransition;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
@@ -14,10 +21,7 @@ import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Modality;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.*;
import javafx.util.Duration;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -87,27 +91,8 @@ public class AutoCloseAlert {
clear();
}
/**
* Show an alert with a title, content, and automatically close after a few seconds
* @param title the title of the alert
* @param content the content of the alert
* @param seconds the number of seconds before the alert is closed, or put 0 to keep it open
* @param onClose What to do after auto close
*/
public static void show(String title, String content, int seconds, Consumer<String> onClose){
if (Platform.isFxApplicationThread()){
Stage alertStage = _showtext(title, "", content);
closeAlertStage(seconds, onClose, alertStage);
} else {
Platform.runLater(()->{
Stage alertStage = _showtext(title, "", content);
closeAlertStage(seconds, onClose, alertStage);
});
}
}
/**
@@ -150,6 +135,87 @@ public class AutoCloseAlert {
}
}
public static void showpictures(String[] pictures, int seconds, Consumer<String> onClose){
List<Image> images = new ArrayList<>();
if (pictures != null){
for(String pp : pictures){
Image ii = LoadImage(pp);
if (ii!=null) images.add(ii);
}
}
if (!images.isEmpty()){
Image[] source = images.toArray(new Image[0]);
if (Platform.isFxApplicationThread()){
_showpictures(source, seconds, onClose);
} else {
Platform.runLater(()-> _showpictures(source,seconds, onClose));
}
}
}
private static void _showpictures(Image[] pictures, int seconds, Consumer<String> onClose){
close();
Stage alertStage = new Stage();
alertStage.initModality(Modality.APPLICATION_MODAL);
alertStage.initStyle(StageStyle.UTILITY);
alertStage.setAlwaysOnTop(true);
alertStage.setResizable(false);
int width = (int) Screen.getPrimary().getBounds().getWidth();
int height = (int) Screen.getPrimary().getBounds().getHeight();
ImageView imageView = new ImageView();
imageView.setPreserveRatio(true);
imageView.setFitWidth(width);
imageView.setFitHeight(height);
BorderPane borderPane = new BorderPane();
borderPane.setCenter(imageView);
alertStage.setScene(new Scene(borderPane, width, height));
alertStage.centerOnScreen();
Timeline timeline = new Timeline();
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(0), event -> {
System.out.println("First timeline, showing the alertstage");
alertStage.show();
}));
for(int xx = 0; xx < pictures.length; xx++){
final int index = xx;
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(seconds*(index+1)), event -> {
System.out.println("showpicture timeline keyframe "+index);
imageView.setImage(pictures[index]);
}));
}
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(seconds* (pictures.length+1)), event -> {
System.out.println("showpicture timeline finished");
alertStage.close();
if (currentAlertStage == alertStage) {
currentAlertStage = null;
}
if (onClose!=null) onClose.accept(shownTitle);
clear();
}));
timeline.play();
System.out.println("showpicture timeline play");
currentAlertStage = alertStage;
shownTitle = "";
shownContent = "";
shownHeader = "";
}
private static Stage _showbanner(Image image){
close();

View File

@@ -242,33 +242,15 @@ public class Cameradetail {
public void setCameraTitle(String title){
if (ValidString(title)){
if (cameratitle!=null){
cameratitle.setText(title);
}
LabelSetText(cameratitle, title,null);
}
}
public void setSharpness_indicator(double value){
if (value >= config.getSharpnessThreshold()){
if (Platform.isFxApplicationThread()){
sharpness_indicator.setText("OK");
sharpness_indicator.setStyle("-fx-text-fill: green; -fx-border-color: black");
} else {
Platform.runLater(()->{
sharpness_indicator.setText("OK");
sharpness_indicator.setStyle("-fx-text-fill: green; -fx-border-color: black");
});
}
LabelSetText(sharpness_indicator, "OK","-fx-text-fill: green; -fx-border-color: black");
} else {
if (Platform.isFxApplicationThread()) {
sharpness_indicator.setText("BAD");
sharpness_indicator.setStyle("-fx-text-fill: red; -fx-border-color: black");
} else {
Platform.runLater(()->{
sharpness_indicator.setText("BAD");
sharpness_indicator.setStyle("-fx-text-fill: red; -fx-border-color: black");
});
}
LabelSetText(sharpness_indicator,"BAD","-fx-text-fill: red; -fx-border-color: black");
}
}
@@ -327,11 +309,7 @@ public class Cameradetail {
* @param status Status of the Camera
*/
public void setCameraStatus(String status){
if (ValidString(status)){
if (camerastatus!=null){
camerastatus.setText(status);
}
}
LabelSetText(camerastatus, status,null);
}
/**
@@ -352,7 +330,11 @@ public class Cameradetail {
public void setCameraStream(Image image){
if (image!=null){
if (camerastream!=null){
camerastream.setImage(image);
if (Platform.isFxApplicationThread()){
camerastream.setImage(image);
} else {
Platform.runLater(()->camerastream.setImage(image));
}
}
}
}
@@ -677,13 +659,13 @@ public class Cameradetail {
* @param prefix filename prefix
* @return filename path of the saved photo, or null if failed
*/
public PhotoResult TakePhoto(String directory, String prefix) throws InterruptedException {
public PhotoResult TakePhoto(String directory, String prefix) {
PhotoResult result = new PhotoResult(cameratitle.getText());
if (!ValidDirectory(directory)) directory = currentDirectory;
if (mGrabber!=null){
while(IsGrabbingLiveView.get()){
Thread.sleep(10);
Wait(10);
}
TakingPhoto.set(true);
if (!BestMat.empty()){
@@ -819,15 +801,18 @@ public class Cameradetail {
if (event!=null) event.onStartCapturing();
Task<Image> task = new Task<>() {
@SuppressWarnings("BusyWait")
@Override
protected Image call() {
// repeat until capturing is false
AtomicInteger fps = new AtomicInteger(0);
// 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;
final int[] eye_state = {-1};
final boolean[] waiting_for_second_blink = {false};
final long[] last_blink = {0};
final int[] no_face_counter = {0};
final int[] face_counter = {0};
final int[] blink_counter = {0};
TimerTask fpsTask = new TimerTask() {
@Override
@@ -857,23 +842,15 @@ public class Cameradetail {
timer.scheduleAtFixedRate(fpsTask, 1000, 1000);
boolean have_frontal_face;
boolean have_left_45_face;
int _face_width;
int _face_height;
boolean have_palm = false;
boolean have_fist = false;
int no_face_counter = 0;
int face_counter = 0;
int blink_counter = 0;
int have_eye_counter = 0;
int no_eye_counter = 0;
while (Capturing.get()) {
try {
// selama proses pengambilan foto, jangan ambil frame
while(TakingPhoto.get() && Capturing.get()){
Thread.sleep(10);
Wait(10);
}
if (!Capturing.get()) return null;
@@ -910,19 +887,19 @@ public class Cameradetail {
UMat flippedmat = new UMat();
opencv_core.flip(originalmat, flippedmat, 0); // flip vertical
flippedmat.copyTo(originalmat);
flippedmat.close();
}
if (config.isFlipCamera()){
// revisi 18/03/2025
UMat flippedmat = new UMat();
opencv_core.flip(originalmat, flippedmat, 1); // flip horizontal
flippedmat.copyTo(originalmat);
flippedmat.close();
}
// rotate 90 degree counter clockwise karena kamera potrait
opencv_core.rotate(originalmat, BestMat, opencv_core.ROTATE_90_COUNTERCLOCKWISE);
IsGrabbingLiveView.set(false);
if (!BestMat.empty()) {
@@ -937,23 +914,25 @@ public class Cameradetail {
}
}
if (use_face){
DetectorResult theface = null;
have_frontal_face = false;
have_left_45_face = false;
_face_width = 0;
_face_height = 0;
boolean have_frontal_face = false;
boolean have_left_45_face = false;
int _face_width = 0;
int _face_height = 0;
List<DetectorResult> frontalfaces = HaveFrontalFace(GrayMat);
if (!frontalfaces.isEmpty()){
for(DetectorResult rect : frontalfaces){
if (rect.haveFace() ){
rect.FaceRectangle(LiveMat);
rect.EyesRectangle(LiveMat);
if (rect.getFaceWidth()>_face_width) _face_width = rect.getFaceWidth();
if (rect.getFaceHeight()>_face_height) _face_height = rect.getFaceHeight();
theface = rect;
have_frontal_face = true;
if (rect.haveEyes()){
rect.EyesRectangle(LiveMat);
}
}
}
} else {
@@ -963,12 +942,13 @@ public class Cameradetail {
if (!Left45Faces.isEmpty()){
for(DetectorResult rect : Left45Faces){
if (rect.haveFace()){
rect.FaceRectangle(LiveMat);
rect.EyesRectangle(LiveMat);
if (rect.getFaceWidth()>_face_width) _face_width = rect.getFaceWidth();
if (rect.getFaceHeight()>_face_height) _face_height = rect.getFaceHeight();
have_left_45_face = true;
if (rect.haveEyes()){
rect.FaceRectangle(LiveMat);
rect.EyesRectangle(LiveMat);
if (rect.getFaceWidth()>_face_width) _face_width = rect.getFaceWidth();
if (rect.getFaceHeight()>_face_height) _face_height = rect.getFaceHeight();
have_left_45_face = true;
}
}
}
}
@@ -976,115 +956,116 @@ public class Cameradetail {
if (have_frontal_face){
if (face_counter<5){
face_counter++;
if (face_counter[0]<5){
face_counter[0]++;
//System.out.println("Frontal Face Counter = "+face_counter+ " from camera "+cameratitle+" eye count = "+theface.getEyesCount());
continue;
}
no_face_counter = 0;
if (event!=null) event.onFrontalFaceDetector(true, _face_width, _face_height);
LabelVisible(face_indicator,true);
if (theface.getFace()!=null){
LiveMatROI = new Rect(theface.getFace().x(), theface.getFace().y(), theface.getFace().width(), theface.getFace().height());
//System.out.println("Frontal Face Detected from camera "+cameratitle+" "+RectToString(LiveMatROI));
}
if (theface.haveEyes()){
// ada mata (buka mata)
// if (have_eye_counter<1){
// have_eye_counter++;
// continue;
// }
// no_eye_counter = 0;
//System.out.println("Valid Eye Detected from camera "+cameratitle);
if (event!=null) event.onEyeDetector(true);
LabelVisible(eye_indicator,true);
// Valid eye condition
if (eye_state!=1){
// transisi dari tutup mata ke buka mata
if (eye_state==-1) {
System.out.println("First Eye Detected from camera "+cameratitle);
eye_state=1;
continue;
}
System.out.println("Transition from close to open eyes");
eye_state = 1;
blink_counter++;
if (event!=null) event.onBlink(blink_counter);
SetText(BlinkCounterLabel, String.valueOf(blink_counter));
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 3 detik
if (diff<=3000){
System.out.println("Double Blink Detected from camera "+cameratitle);
if (event!=null) event.onDoubleBlink((int)diff);
}
waiting_for_second_blink = false;
} else {
waiting_for_second_blink = true;
System.out.println("First Blink Detected from camera "+cameratitle);
}
last_blink = now;
}
//continue;
} else {
// ada muka, tidak ada mata
// transisi dari buka mata ke tutup mata
// if (no_eye_counter<1){
// no_eye_counter++;
// continue;
// }
// have_eye_counter = 0;
//System.out.println("Valid No Eye Detected from camera "+cameratitle);
if (event!=null) event.onEyeDetector(false);
LabelVisible(eye_indicator,false);
// Valid no eye condition
no_face_counter[0] = 0;
if (event!=null) event.onFrontalFaceDetector(true, _face_width, _face_height);
//LabelVisible(face_indicator,true);
Platform.runLater(()-> face_indicator.setVisible(true));
if (eye_state!=0){
System.out.println("Transition from open to close eyes");
eye_state = 0;
if (theface.getFace()!=null){
LiveMatROI = new Rect(theface.getFace().x(), theface.getFace().y(), theface.getFace().width(), theface.getFace().height());
//System.out.println("Frontal Face Detected from camera "+cameratitle+" "+RectToString(LiveMatROI));
}
if (theface.haveEyes()){
// ada mata (buka mata)
if (event!=null) event.onEyeDetector(true);
//LabelVisible(eye_indicator,true);
Platform.runLater(()-> eye_indicator.setVisible(true));
//System.out.println("Valid Eye Detected from camera "+cameratitle);
// Valid eye condition
if (eye_state[0]!=1){
// transisi dari tutup mata ke buka mata
if (eye_state[0]==-1) {
System.out.println("First Eye Detected from camera "+cameratitle);
eye_state[0]=1;
continue;
} else {
System.out.println("Transition from close to open eyes");
eye_state[0] = 1;
blink_counter[0]++;
if (event!=null) event.onBlink(blink_counter[0]);
Platform.runLater(()-> BlinkCounterLabel.setText(blink_counter[0]+""));
//LabelSetText(BlinkCounterLabel, String.valueOf(blink_counter[0]),null);
long now = System.currentTimeMillis();
if (waiting_for_second_blink[0]){
long diff = now - last_blink[0];
// kalau beda waktu antara blink 1 dan blink 2 kurang dari 3 detik
if (diff<=3000){
System.out.println("Double Blink Detected from camera "+cameratitle);
if (event!=null) event.onDoubleBlink((int)diff);
}
waiting_for_second_blink[0] = false;
} else {
waiting_for_second_blink[0] = true;
System.out.println("First Blink Detected from camera "+cameratitle);
}
last_blink[0] = now;
}
}
} else {
// ada muka, tidak ada mata
// transisi dari buka mata ke tutup mata
if (event!=null) event.onEyeDetector(false);
//LabelVisible(eye_indicator,false);
Platform.runLater(()-> eye_indicator.setVisible(false));
// Valid no eye condition
if (eye_state[0]!=0){
System.out.println("Transition from open to close eyes");
eye_state[0] = 0;
}
}
}
} else if (have_left_45_face ){
no_face_counter = 0;
if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height);
LabelVisible(face_indicator,true);
//LabelVisible(face_indicator,true);
Platform.runLater(()-> face_indicator.setVisible(true));
} else {
// no face detected, but let's not cancel the previous state immediately
if (no_face_counter<60){
if (no_face_counter[0]<60){
// toleransi no face selama 60 frame
no_face_counter++;
no_face_counter[0]++;
continue;
} else {
// beneran dianggap no face detected
eye_state = -1;
last_blink = 0;
waiting_for_second_blink = false;
face_counter = 0;
blink_counter = 0;
no_eye_counter=0;
have_eye_counter=0;
eye_state[0] = -1;
last_blink[0] = 0;
waiting_for_second_blink[0] = false;
face_counter[0] = 0;
blink_counter[0] = 0;
if (event!=null) {
event.onFrontalFaceDetector(false, _face_width, _face_height);
event.onProfileFaceDetector(false, _face_width, _face_height);
event.onEyeDetector(false);
event.onBlink(blink_counter);
SetText(BlinkCounterLabel, "");
LabelVisible(face_indicator,false);
LabelVisible(eye_indicator,false);
event.onBlink(blink_counter[0]);
Platform.runLater(()->{
face_indicator.setVisible(false);
eye_indicator.setVisible(false);
BlinkCounterLabel.setText("");
});
//LabelSetText(BlinkCounterLabel, "",null);
//LabelVisible(face_indicator,false);
//LabelVisible(eye_indicator,false);
}
}
@@ -1098,7 +1079,7 @@ public class Cameradetail {
Mat imgmat = new Mat();
rgbmat.copyTo(imgmat); // copy back to CPU
// Update Task Value usign matToWritableImage
updateValue(matToWritableImage(imgmat, imgmat.cols(), imgmat.rows()));
updateValue(matToWritableImage(imgmat));
}
} catch (Exception e) {
if (ValidString(e.getMessage())){
@@ -1120,7 +1101,9 @@ public class Cameradetail {
});
// start task
new Thread(task).start();
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
return true;
} catch (Exception e) {
@@ -1229,11 +1212,13 @@ public class Cameradetail {
return mean.get(0);
}
private WritableImage matToWritableImage(Mat mat, int cols, int rows){
private WritableImage matToWritableImage(Mat mat){
int cols = mat.cols();
int rows = mat.rows();
WritableImage writableImage = new WritableImage(cols, rows);
ByteBuffer buffer = mat.createBuffer();
PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteRgbInstance();
writableImage.getPixelWriter().setPixels(0, 0, mat.cols(), mat.rows(), pixelFormat, buffer, mat.cols() * 3);
writableImage.getPixelWriter().setPixels(0, 0, cols, rows, pixelFormat, buffer, cols * 3);
return writableImage;
}

View File

@@ -114,21 +114,21 @@ public class CaptureView {
config.Save();
}
private void trigger_autofocus(Cameradetail image) throws InterruptedException {
private void trigger_autofocus(Cameradetail image) {
if (image!=null){
if (image.isCapturing()){
image.setAutoFocus(false);
Thread.sleep(5);
Wait(5);
image.setFocus(0.7);
Thread.sleep(5);
Wait(5);
image.setAutoFocus(true);
Thread.sleep(5);
Wait(5);
}
}
}
@FXML
private void AutoFocus() throws InterruptedException {
private void AutoFocus() {
trigger_autofocus(image1);
trigger_autofocus(image2);
trigger_autofocus(image3);
@@ -533,12 +533,8 @@ public class CaptureView {
long duration = (System.nanoTime() - nanostart) / 1000000; // in milliseconds
System.out.println("TakePhotos duration: "+duration+" ms");
//AutoCloseAlert.show("Photos Taken", "Photos Taken", "Photos Taken", 5, null);
if (AutoCloseAlert.banner_02!=null) {
System.out.println("Showing banner 02 after photo taken");
AutoCloseAlert.showbanner(AutoCloseAlert.banner_02, 0, null);
}
String[] files = prc.compressed();
if (files.length>0){
@@ -553,8 +549,17 @@ public class CaptureView {
@Override
public void onPlaybackFinished(String filename) {
UploadFiles(prc, prefix);
if (runningTask!=null) runningTask.cancel(false);
AutoCloseAlert.showpictures(prc.compressed(),2, (s)->{
if (AutoCloseAlert.banner_02!=null) {
System.out.println("Showing banner 02 after photo taken");
AutoCloseAlert.showbanner(AutoCloseAlert.banner_02, 0, null);
UploadFiles(prc, prefix);
if (runningTask!=null) runningTask.cancel(false);
}
});
}
@Override
@@ -615,7 +620,6 @@ public class CaptureView {
uploadtask.setOnSucceeded(e-> {
System.out.println("UploadTask succeeded");
clear();
AutoCloseAlert.close();
});
uploadtask.setOnFailed(e-> {
@@ -626,12 +630,12 @@ public class CaptureView {
audioPlayer.PlayFile(audio_upload_gagal, null);
}
}
AutoCloseAlert.show("Upload Failed", "Upload Failed", "Upload Failed", 5, s -> {
clear();
});
AutoCloseAlert.show("Upload Failed", "Upload Failed", "Upload Failed", 5, s -> clear());
});
new Thread(uploadtask).start();
Thread uploadThread = new Thread(uploadtask);
uploadThread.setDaemon(true);
uploadThread.start();
} else ShowAlert(AlertType.ERROR, "Error", "No Photos Taken", "No Photos Taken, please check camera");
}
@@ -713,7 +717,9 @@ public class CaptureView {
Logger.info("Left90 Index: "+indexleft90);
if (indexleft90!=-1){
final int finalindex = indexleft90;
new Thread(()-> SetupCameraWithController(image1, camleft90, finalindex)).start();
Thread c1 = new Thread(()-> SetupCameraWithController(image1, camleft90, finalindex));
c1.setDaemon(true);
c1.start();
}
}
}
@@ -725,7 +731,9 @@ public class CaptureView {
Logger.info("Left45 Index: "+indexleft45);
if (indexleft45!=-1) {
final int finalindex = indexleft45;
new Thread(()-> SetupCameraWithController(image2, camleft45, finalindex)).start();
Thread c2 = new Thread(()-> SetupCameraWithController(image2, camleft45, finalindex));
c2.setDaemon(true);
c2.start();
}
}
}
@@ -737,7 +745,9 @@ public class CaptureView {
Logger.info("Center Index: "+indexcenter);
if (indexcenter!=-1) {
final int finalindex = indexcenter;
new Thread(()-> SetupCameraWithController(image3, camcenter, finalindex)).start();
Thread c3 = new Thread(()-> SetupCameraWithController(image3, camcenter, finalindex));
c3.setDaemon(true);
c3.start();
}
}
}
@@ -749,7 +759,9 @@ public class CaptureView {
Logger.info("Right45 Index: "+indexright45);
if (indexright45!=-1) {
final int finalindex = indexright45;
new Thread(()-> SetupCameraWithController(image4, camright45, finalindex)).start();
Thread c4 = new Thread(()-> SetupCameraWithController(image4, camright45, finalindex));
c4.setDaemon(true);
c4.start();
}
}
@@ -762,7 +774,9 @@ public class CaptureView {
Logger.info("Right90 Index: "+indexright90);
if (indexright90!=-1) {
final int finalindex = indexright90;
new Thread(()-> SetupCameraWithController(image5, camright90, finalindex)).start();
Thread c5 = new Thread(()-> SetupCameraWithController(image5, camright90, finalindex));
c5.setDaemon(true);
c5.start();
}
}
}
@@ -776,11 +790,9 @@ public class CaptureView {
private void clear(){
isTakingPhoto.set(false);
Platform.runLater(()->{
medicalRecordID.setText("");
PatientName.setText("");
barcodeData.setText("");
});
TextAreaSetText(medicalRecordID,"");
TextAreaSetText(PatientName,"");
TextAreaSetText(barcodeData,"");
}
public void Unload(){
@@ -891,9 +903,7 @@ public class CaptureView {
String prefix = barcodeData.getText();
if (!barCode.equals(prefix)){
final String finalbarCode = barCode;
Platform.runLater(()->{
barcodeData.setText(finalbarCode);
});
TextAreaSetText(barcodeData, finalbarCode);
Task<PatientRecord> checkpatientID = new Task<>() {
@Override
protected PatientRecord call() throws Exception {
@@ -916,17 +926,14 @@ public class CaptureView {
}
} else {
Logger.error("Record associated with barcode ",finalbarCode," is empty");
//AutoCloseAlert.show("Data Tidak Ditemukan","Data dengan barcode "+finalbarCode+" ditemukan di server, tetapi kosong","Pastikan data barcode anda benar", 5);
throw new Exception("Data dengan barcode "+finalbarCode+" ditemukan di server, tetapi kosong");
}
} else {
Logger.error("Record associated with barcode ",finalbarCode," is not found");
//AutoCloseAlert.show("Data Tidak Ditemukan","Data dengan barcode "+finalbarCode+" tidak ditemukan di server","Pastikan data barcode anda benar",5);
throw new Exception("Data dengan barcode "+finalbarCode+" tidak ditemukan di server");
}
} else {
Logger.error("BarcodeResullt with barcode ",finalbarCode," is null");
//AutoCloseAlert.show("Data Tidak Ditemukan", "BarcodeResult dengan barcode "+finalbarCode+" menghasilkan null", "Pastikan data barcode anda benar", 5);
throw new Exception("BarcodeResult dengan barcode "+finalbarCode+" menghasilkan null");
}
}
@@ -937,13 +944,13 @@ public class CaptureView {
if (pr!=null){
int medrecid = toInt(pr.medical_record_detail_id);
System.out.println("checkpatientID.setOnSucceeded medrecid : "+medrecid);
Platform.runLater(()->{
medicalRecordID.setText(""+medrecid);
PatientName.setText(pr.name);
});
TextAreaSetText(medicalRecordID,""+medrecid);
TextAreaSetText(PatientName, pr.name);
runningTask = timeoutExecutor.schedule(()->{
// timeout
System.out.println("runningTask timeout after "+timeout+" seconds");
clear();
}, timeout, TimeUnit.SECONDS);
@@ -970,16 +977,13 @@ public class CaptureView {
System.out.println("checkpatientID.setOnFailed message : "+message);
AutoCloseAlert.show("Data Tidak Ditemukan", message, "Pastikan data barcode anda benar", 5, s -> {
clear();
});
AutoCloseAlert.show("Data Tidak Ditemukan", "Pastikan data barcode anda benar", message , 5, s -> clear());
});
new Thread(checkpatientID).start();
Thread checkpatientIDThread = new Thread(checkpatientID);
checkpatientIDThread.setDaemon(true);
checkpatientIDThread.start();
}
}

View File

@@ -61,4 +61,5 @@ public class DetectorResult {
if (!haveEyes()) return 0;
return Eyes.size();
}
}

View File

@@ -9,14 +9,10 @@ import org.tinylog.Logger;
import java.util.ArrayList;
import java.util.List;
import static Config.SomeCodes.IsInsideRect;
public class Detectors {
public static CascadeClassifier frontalfaceDetector;
private static CascadeClassifier eyeDetector;
private static CascadeClassifier profilefaceDetector;
//private static CascadeClassifier palmDetector;
//private static CascadeClassifier fistDetector;
private static double scaleFactor = 1.1;
private final static int minNeighbors = 3;
@@ -24,10 +20,6 @@ public class Detectors {
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();
@@ -35,47 +27,10 @@ public class Detectors {
LoadProfileFaceDetector();
//LoadFistDetector();
//LoadRightPalmDetector();
}
// private static void LoadFistDetector(){
// String filename = SomeCodes.ExtractResource("/fist.xml");
// if (filename!=null) {
// Logger.info("Fist Detector file : " + filename);
// if (fistDetector ==null) {
// try{
//
// fistDetector = new CascadeClassifier(filename);
// Logger.info("FistDetector loaded");
// } catch (Exception e){
// Logger.error("Exception on loading FistDetector : " + e.getMessage());
// }
//
// } else Logger.info("FistDetector already loaded");
// } else Logger.error("Unable to extract fist detector file");
// }
// private static void LoadRightPalmDetector(){
// String filename = SomeCodes.ExtractResource("/rpalm.xml");
// if (filename!=null) {
// Logger.info("Right Palm Detector file : " + filename);
// if (palmDetector ==null) {
// try{
//
// palmDetector = new CascadeClassifier(filename);
// Logger.info("RightPalmDetector loaded");
// } catch (Exception e){
// Logger.error("Exception on loading RightPalmDetector : " + e.getMessage());
// }
//
// } else Logger.info("RightPalmDetector already loaded");
// } else Logger.error("Unable to extract right palm detector file");
// }
private static void LoadFrontalFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_default.xml");
if (filename!=null) {
Logger.info("Face Detector file : " + filename);
if (frontalfaceDetector==null) {
@@ -123,22 +78,6 @@ public class Detectors {
} else Logger.error("Unable to extract eye detector file");
}
// public static boolean HavePalm(UMat graymat){
// RectVector palms = Detect(graymat, palmDetector);
// return palms!=null && palms.size()>0;
// }
//
// public static boolean HaveFist(UMat graymat){
// RectVector fists = Detect(graymat, fistDetector);
// return fists!=null && fists.size()>0;
// }
/**
* Detect if there is a frontal face, containing 2 eyes
* @param graymat Mat in Gray Scale
@@ -150,12 +89,12 @@ public class Detectors {
if (faces!=null && faces.size()>0){
for(Rect face : faces.get()){
RectVector eyes = DetectEye(graymat);
RectVector eyes = DetectEye(graymat, face.width());
DetectorResult dr = new DetectorResult();
dr.setFace(face);
if (eyes!=null && eyes.size()>=2){
for(Rect eye : eyes.get()){
if (IsInsideRect(eye, face)) dr.AddEye(eye);
if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye);
}
}
result.add(dr);
@@ -170,12 +109,12 @@ public class Detectors {
if (faces!=null && faces.size()>0){
for(Rect face : faces.get()){
RectVector eyes = DetectEye(graymat);
RectVector eyes = DetectEye(graymat, face.width());
DetectorResult dr = new DetectorResult();
dr.setFace(face);
if (eyes!=null && eyes.size()>0){
for(Rect eye : eyes.get()){
if (IsInsideRect(eye, face)) dr.AddEye(eye);
if (SomeCodes.IsInsideRect(eye, face)) dr.AddEye(eye);
}
}
result.add(dr);
@@ -195,34 +134,28 @@ public class Detectors {
if (FaceminSize!=null){
if (FaceminSize.width()!=value || FaceminSize.height()!=value) {
FaceminSize = new Size(value, value);
EyeminSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
Logger.info("FaceMinSize changed to : " + FaceminSize.width());
Logger.info("EyeMinSize changed to : " + EyeminSize.width());
//Logger.info("FaceMinSize changed to : " + FaceminSize.width());
}
} else {
FaceminSize = new Size(value, value);
EyeminSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
Logger.info("FaceMinSize created with value : " + FaceminSize.width());
Logger.info("EyeMinSize created with value : " + EyeminSize.width());
//Logger.info("FaceMinSize created with value : " + FaceminSize.width());
}
System.out.println("Face Min Size : " + FaceminSize.width());
}
public static void setFaceMaxSize(int value){
if (FacemaxSize!=null){
if (FacemaxSize.width()!=value || FacemaxSize.height()!=value) {
FacemaxSize = new Size(value, value);
EyemaxSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
Logger.info("FaceMaxSize changed to : " + FacemaxSize.width());
Logger.info("EyeMaxSize changed to : " + EyemaxSize.width());
//Logger.info("FaceMaxSize changed to : " + FacemaxSize.width());
}
} else {
FacemaxSize = new Size(value, value);
EyemaxSize = new Size(value/EyetoFaceRatio, value/EyetoFaceRatio);
Logger.info("FaceMaxSize created with value : " + FacemaxSize.width());
Logger.info("EyeMaxSize created with value : " + EyemaxSize.width());
//Logger.info("FaceMaxSize created with value : " + FacemaxSize.width());
}
System.out.println("Face Max Size : " + FacemaxSize.width());
}
@@ -230,23 +163,6 @@ public class Detectors {
return Detect(graymat, profilefaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
}
public static RectVector DetectFrontalFace(Mat graymat, int minsize, int maxsize){
Size min = new Size(minsize, minsize);
Size max = new Size(maxsize, maxsize);
RectVector rect = new RectVector();
frontalfaceDetector.detectMultiScale(graymat, rect,scaleFactor, minNeighbors, flags, min, max);
return rect;
}
public static RectVector DetectProfileFace(Mat graymat, int minsize, int maxsize){
Size min = new Size(minsize, minsize);
Size max = new Size(maxsize, maxsize);
RectVector rect = new RectVector();
profilefaceDetector.detectMultiScale(graymat, rect,scaleFactor, minNeighbors, flags, min, max);
return rect;
}
/**
* Detect Face from Mat
* @param graymat Mat in Gray Scale
@@ -256,18 +172,19 @@ public class Detectors {
return Detect(graymat, frontalfaceDetector, scaleFactor, minNeighbors, flags, FaceminSize, FacemaxSize);
}
/**
* Detect Eye from Mat
* If Eye detected, it will return RectVector with size is number of eyes detected
* @param graymat Mat in Gray Scale
* @return RectVector if eye detected, otherwise null
*/
public static RectVector DetectEye(UMat graymat){
//return Detect(graymat, eyeDetector, scaleFactor, minNeighbors, flags, EyeminSize, EyemaxSize);
return Detect(graymat, eyeDetector);
public static RectVector DetectEye(UMat graymat, int facewidth){
//return Detect(graymat, eyeDetector);
int minwidth = (int)(facewidth*0.2);
int maxwidth = (int)(facewidth*0.4);
Size minsize = new Size(minwidth, minwidth);
Size maxsize = new Size(maxwidth, maxwidth);
return Detect(graymat, eyeDetector, scaleFactor, minNeighbors, flags, minsize, maxsize);
}

View File

@@ -34,7 +34,7 @@ public class MainApplication extends Application {
Screen screen = Screen.getPrimary();
Rectangle2D screenbound = screen.getBounds();
Scene scene = new Scene(fxmlLoader.load(), screenbound.getWidth(), screenbound.getHeight());
stage.setTitle("MultiCam Capture App for ERHA 09042025-002");
stage.setTitle("MultiCam Capture App for ERHA 10042025-005");
stage.setScene(scene);
stage.setResizable(true);
stage.setMaximized(true);

View File

@@ -15,8 +15,7 @@ import org.tinylog.Logger;
import java.io.File;
import java.nio.file.Path;
import static Config.SomeCodes.ShowAlert;
import static Config.SomeCodes.config;
import static Config.SomeCodes.*;
public class PhotoRow {
@FXML
@@ -29,13 +28,11 @@ public class PhotoRow {
private final String borderstyle = "-fx-border-color: black; -fx-border-width: 1px;";
public void setDatetime(String datetime){
this.datetime.setText(datetime);
this.datetime.setStyle(borderstyle);
LabelSetText(this.datetime, datetime, borderstyle);
}
public void setPrefix(String prefix){
this.prefix.setText(prefix);
this.prefix.setStyle(borderstyle);
LabelSetText(this.prefix,prefix,borderstyle);
}
public void setPhotos(int width, int height, String... thumbnails){

View File

@@ -2,8 +2,6 @@ package id.co.gtc.erhacam;
import FTP.FTPCheck;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.CheckBox;
@@ -11,13 +9,9 @@ import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import lombok.val;
import org.bytedeco.javacv.VideoInputFrameGrabber;
import org.tinylog.Logger;
import java.io.File;
import java.util.Objects;
import static Config.SomeCodes.*;
public class SettingView {
@@ -78,7 +72,7 @@ public class SettingView {
config.SetPhotoDirectory(path);
config.Save();
PhotoDirectoryPath.setText(path);
TextFieldSetText(PhotoDirectoryPath,path);
}
@FXML
@@ -191,23 +185,23 @@ public class SettingView {
CameraRight45.setValue(config.getCameraRight45());
CameraRight90.setValue(config.getCameraRight90());
FTPHost.setText(config.getFTPHost());
FTPPort.setText(config.getFTPPort());
FTPUser.setText(config.getFTPUser());
FTPPass.setText(config.getFTPPass());
FTPPath.setText(config.getFTPPath());
TextFieldSetText(FTPHost,config.getFTPHost());
TextFieldSetText(FTPPort,config.getFTPPort());
TextFieldSetText(FTPUser,config.getFTPUser());
TextFieldSetText(FTPPass,config.getFTPPass());
TextFieldSetText(FTPPath,config.getFTPPath());
PhotoDirectoryPath.setText(config.getPhotoDirectory());
TextFieldSetText(PhotoDirectoryPath,config.getPhotoDirectory());
TextFieldSetText(cascadeScaleFactor,String.valueOf(config.getCascadeScaleFactor()));
TextFieldSetText(cascadeMinSize,String.valueOf(config.getCascadeMinSize()));
TextFieldSetText(cascadeMaxSize,String.valueOf(config.getCascadeMaxSize()));
cascadeScaleFactor.setText(String.valueOf(config.getCascadeScaleFactor()));
cascadeMinSize.setText(String.valueOf(config.getCascadeMinSize()));
cascadeMaxSize.setText(String.valueOf(config.getCascadeMaxSize()));
MirrorCamera.setSelected(config.isMirrorCamera());
FlipCamera.setSelected(config.isFlipCamera());
Sharpness.setText(String.valueOf(config.getSharpnessThreshold()));
TextFieldSetText(Sharpness,String.valueOf(config.getSharpnessThreshold()));
});
}

View File

@@ -8,6 +8,7 @@ import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import static Config.SomeCodes.LabelSetText;
import static Config.SomeCodes.ValidString;
public class UploadProgress {
@@ -31,9 +32,7 @@ public class UploadProgress {
* @param filename the filename to be displayed
*/
public void SetFile(String filename){
if (ValidString(filename)){
labelfile.setText(filename);
}
LabelSetText(this.labelfile, filename,null);
}
/**
@@ -41,9 +40,7 @@ public class UploadProgress {
* @param status the status to be displayed
*/
public void SetStatus(String status){
if (ValidString(status)){
labelstatus.setText(status);
}
LabelSetText(this.labelstatus, status,null);
}
/**

View File

@@ -197,11 +197,7 @@ public class Cameradetail_Arducam {
* @param title Title of the Camera
*/
public void setCameraTitle(String title){
if (ValidString(title)){
if (cameratitle!=null){
cameratitle.setText(title);
}
}
LabelSetText(this.cameratitle, title, null);
}
public void setSaturation(double value){
@@ -259,11 +255,7 @@ public class Cameradetail_Arducam {
* @param status Status of the Camera
*/
public void setCameraStatus(String status){
if (ValidString(status)){
if (camerastatus!=null){
camerastatus.setText(status);
}
}
LabelSetText(this.camerastatus, status,null);
}
/**
@@ -519,13 +511,12 @@ public class Cameradetail_Arducam {
* @param prefix filename prefix
* @return filename path of the saved photo, or null if failed
*/
@SuppressWarnings("BusyWait")
public String TakePhoto(String directory, String prefix){
if (!ValidDirectory(directory)) directory = currentDirectory;
if (mGrabber!=null){
try{
long nanos = System.nanoTime();
while(IsGrabbingLiveView.get()) Thread.sleep(10);
while(IsGrabbingLiveView.get()) Wait(10);
long delta = System.nanoTime() - nanos;
double ms = delta / 1000000.0;
if (event!=null) event.onLog("Waited IsGrabbingLiveView for "+ms+" miliseconds");
@@ -542,10 +533,10 @@ public class Cameradetail_Arducam {
setAutoWB(true);
Thread.sleep(1000);
Wait(1000);
setAutoExposure(true);
Thread.sleep(1000);
Wait(1000);
long delta3 = System.nanoTime() - nanos;
double ms3 = delta3 / 1000000.0;
@@ -673,14 +664,13 @@ public class Cameradetail_Arducam {
AutoWhiteBalance.setSelected(true);
val task = new Task<Image>() {
@SuppressWarnings("BusyWait")
@Override
protected Image call() {
while (Capturing.get()) {
try {
// selama proses pengambilan foto, jangan ambil frame
while(TakingPhoto.get() && Capturing.get()){
Thread.sleep(10);
Wait(10);
}
if (!Capturing.get()) return null;
@@ -737,7 +727,10 @@ public class Cameradetail_Arducam {
});
// start task
new Thread(task).start();
Thread taskThread = new Thread(task);
taskThread.setDaemon(true);
taskThread.start();
return true;
} catch (Exception e) {