commit 11/04/2025

This commit is contained in:
rdkartono
2025-04-11 14:19:39 +07:00
parent b6a3076993
commit 93b1079747
8 changed files with 457 additions and 9198 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -182,19 +182,16 @@ public class AutoCloseAlert {
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;
@@ -203,11 +200,6 @@ public class AutoCloseAlert {
clear();
}));
timeline.play();
System.out.println("showpicture timeline play");
currentAlertStage = alertStage;
shownTitle = "";

View File

@@ -12,7 +12,6 @@ import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
@@ -25,6 +24,7 @@ import lombok.Getter;
import lombok.Setter;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_imgcodecs;
@@ -42,13 +42,15 @@ import java.time.LocalDateTime;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.*;
import static org.bytedeco.opencv.global.opencv_core.CV_8UC3;
import static org.bytedeco.opencv.global.opencv_core.mean;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
@SuppressWarnings({"unused"})
@@ -65,17 +67,14 @@ public class Cameradetail {
}
private final AtomicBoolean Capturing = new AtomicBoolean(false);
private final AtomicBoolean TakingPhoto = new AtomicBoolean(false);
private final AtomicBoolean IsGrabbingLiveView = new AtomicBoolean(false);
private CountDownLatch TakingPhoto = null;
private final Semaphore IsGrabbingLiveView = new Semaphore(0);
private OpenCVFrameGrabber mGrabber = null;
private LiveCamEvent event = null;
private @Getter @Setter CameraConfigEnum cameraConfigEnum = CameraConfigEnum.CameraConfigCenter;
private @Getter int LiveFPS = 0;
/**
* Get detected QR text from Live View
*/
private @Getter String qrtext = null;
@FXML
private Label cameratitle;
@@ -145,12 +144,27 @@ public class Cameradetail {
int[] paramjpeg = {opencv_imgcodecs.IMWRITE_JPEG_QUALITY, 100};
int[] parampng = {opencv_imgcodecs.IMWRITE_PNG_COMPRESSION, 0};
private boolean use_qr = false;
private boolean use_face = false;
private void setSliderValue(Slider sld, CameraProperty prop, double value){
if (sld!=null){
sld.setMin(prop.Min);
sld.setMax(prop.Max);
sld.setValue(value);
if (prop!=null){
if (Platform.isFxApplicationThread()){
sld.setMin(prop.Min);
sld.setMax(prop.Max);
sld.setValue(value);
} else {
Platform.runLater(()->{
sld.setMin(prop.Min);
sld.setMax(prop.Max);
sld.setValue(value);
});
}
}
}
}
@@ -664,42 +678,49 @@ public class Cameradetail {
if (!ValidDirectory(directory)) directory = currentDirectory;
if (mGrabber!=null){
while(IsGrabbingLiveView.get()){
Wait(10);
try{
// wait if the camera is still capturing
IsGrabbingLiveView.acquire();
TakingPhoto = new CountDownLatch(1);
if (!BestMat.empty()){
// save BestMat at quality 9 PNG
String filename = GetFullQualityPhotoPath(directory, prefix);
if (opencv_imgcodecs.imwrite(filename, BestMat, parampng)){
result.setFullres(filename);
} else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+cameratitle.getText());
String xx = CropBestMat(directory, prefix, BestMatROI);
if (ValidFile(xx)) {
result.setFullcrop(xx);
result.setBestROI(new Rect(BestMatROI.x(), BestMatROI.y(), BestMatROI.width(), BestMatROI.height()));
}
// save ReducedMat at 100% JPEG
String reducedfilename = GetReducedPhotoPath(directory, prefix);
opencv_imgproc.resize(BestMat, ReducedMat, ReducedSize);
if (!opencv_imgcodecs.imwrite(reducedfilename, ReducedMat, paramjpeg)){
System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+cameratitle.getText());
} else result.setCompressedfile(reducedfilename);
String xy = CropReducedMat(directory, prefix, ReducedMatROI);
if (ValidFile(xy)){
result.setCompressedcrop(xy);
result.setReducedROI(new Rect(ReducedMatROI.x(), ReducedMatROI.y(), ReducedMatROI.width(), ReducedMatROI.height()));
}
} else raise_log("TakePhoto failed, Live View is Empty");
} catch (InterruptedException e){
System.out.println("TakePhoto IsGrabbingLiveView interrupted");
}
TakingPhoto.set(true);
if (!BestMat.empty()){
// save BestMat at quality 9 PNG
String filename = GetFullQualityPhotoPath(directory, prefix);
TakingPhoto.countDown();
if (opencv_imgcodecs.imwrite(filename, BestMat, parampng)){
result.setFullres(filename);
} else System.out.println("TakePhoto failed, Unable to Save FullQUality Photo for camera "+cameratitle.getText());
String xx = CropBestMat(directory, prefix, BestMatROI);
if (ValidFile(xx)) {
result.setFullcrop(xx);
result.setBestROI(new Rect(BestMatROI.x(), BestMatROI.y(), BestMatROI.width(), BestMatROI.height()));
}
// save ReducedMat at 100% JPEG
String reducedfilename = GetReducedPhotoPath(directory, prefix);
opencv_imgproc.resize(BestMat, ReducedMat, ReducedSize);
if (!opencv_imgcodecs.imwrite(reducedfilename, ReducedMat, paramjpeg)){
System.out.println("TakePhoto failed, Unable to Save Reduced Photo for camera "+cameratitle.getText());
} else result.setCompressedfile(reducedfilename);
String xy = CropReducedMat(directory, prefix, ReducedMatROI);
if (ValidFile(xy)){
result.setCompressedcrop(xy);
result.setReducedROI(new Rect(ReducedMatROI.x(), ReducedMatROI.y(), ReducedMatROI.width(), ReducedMatROI.height()));
}
} else raise_log("TakePhoto failed, Live View is Empty");
} else raise_log("TakePhoto failed, Grabber is null");
TakingPhoto.set(false);
return result;
}
@@ -766,17 +787,320 @@ public class Cameradetail {
try{
mGrabber.close();
System.out.println("Camera "+cameratitle.getText()+" stopped");
Platform.runLater(()->setCameraStatus("Camera Stopped"));
setCameraStatus("Camera Stopped");
} catch (Exception e){
raise_log("StopLiveView failed, Unable to Stop Camera, Error: " + e.getMessage());
}
}
TakingPhoto.set(false);
IsGrabbingLiveView.set(false);
TakingPhoto = null;
IsGrabbingLiveView.drainPermits();
// stop FPS calculation
timer.cancel();
// stop camera capture thread
cam_capture.interrupt();
// stop qr detection thread
qr_detect.interrupt();
// stop face detection thread
face_detect.interrupt();
}
public boolean StartLiveView(LiveCamEvent event, String cameratitle, final boolean use_qr , final boolean use_face) {
Timer timer = new java.util.Timer();
// FPS Calculator
AtomicInteger fps = new AtomicInteger(0);
// use for locking
final Object lockObject = new Object();
// QR Detection Thread
Semaphore qr_semaphore = new Semaphore(0);
Thread qr_detect = new Thread(()->{
while(Capturing.get()){
try {
qr_semaphore.acquire();
UMat gray;
synchronized (lockObject){
gray = GrayMat;
}
String qr = DetectQRFromMat(gray);
if (ValidBarCode(qr)){
if (event!=null) event.onDetectedQRCode(qr);
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+" interrupted");
}
}
});
// Face Detection Thread
Semaphore face_semaphore = new Semaphore(0);
Thread face_detect = new Thread(()->{
// eye state = -1 means unknown, 0 means closed, 1 means open
final AtomicInteger eye_state = new AtomicInteger(-1);
final AtomicBoolean waiting_for_second_blink = new AtomicBoolean(false);
final AtomicLong last_blink = new AtomicLong(0);
final AtomicInteger no_face_counter = new AtomicInteger(0);
final AtomicInteger face_counter = new AtomicInteger(0);
final AtomicInteger blink_counter = new AtomicInteger(0);
final AtomicInteger no_eye_counter = new AtomicInteger(0);
final AtomicInteger have_eye_counter = new AtomicInteger(0);
while(Capturing.get()){
try {
face_semaphore.acquire();
UMat gray;
synchronized (lockObject){
gray = GrayMat;
}
DetectorResult theface = null;
boolean have_frontal_face = false;
boolean have_left_45_face = false;
int _face_width = 0;
int _face_height = 0;
List<DetectorResult> frontalfaces = HaveFrontalFace(gray);
if (!frontalfaces.isEmpty()){
for(DetectorResult rect : frontalfaces){
if (rect.haveFace() ){
rect.FaceRectangle(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 {
// gak punya frontal face
// coba cek punya profile left face 45 gak
List<DetectorResult> Left45Faces = HaveLeft45Face(gray);
if (!Left45Faces.isEmpty()){
for(DetectorResult rect : Left45Faces){
if (rect.haveFace()){
rect.FaceRectangle(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.EyesRectangle(LiveMat);
}
}
}
}
}
if (have_frontal_face){
if (face_counter.incrementAndGet()<5) continue;
no_face_counter.set(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.getEyesCount()>=2){
// ada mata (buka mata)
if (have_eye_counter.incrementAndGet()<5) continue;
no_eye_counter.set(0);
if (event!=null) event.onEyeDetector(true);
LabelVisible(eye_indicator,true);
//System.out.println("Valid Eye Detected from camera "+cameratitle);
// Valid eye condition
if (eye_state.get()!=1){
// transisi dari tutup mata ke buka mata
if (eye_state.get()==-1) {
System.out.println("First Eye Detected from camera "+cameratitle.getText());
eye_state.set(1);
} else {
System.out.println("Transition from close to open eyes");
eye_state.set(1);
blink_counter.incrementAndGet();
if (event!=null) event.onBlink(blink_counter.get());
LabelSetText(BlinkCounterLabel, String.valueOf(blink_counter.get()),null);
long now = System.currentTimeMillis();
if (waiting_for_second_blink.get()){
long diff = now - last_blink.get();
// kalau beda waktu antara blink 1 dan blink 2 kurang dari 3 detik
if (diff<=3000){
System.out.println("Double Blink Detected from camera "+cameratitle.getText());
if (event!=null) event.onDoubleBlink((int)diff);
}
waiting_for_second_blink.set(false);
} else {
waiting_for_second_blink.set(true);
System.out.println("First Blink Detected from camera "+cameratitle.getText());
}
last_blink.set(now);
}
}
} else {
// ada muka, tidak ada mata
// transisi dari buka mata ke tutup mata
if (no_eye_counter.incrementAndGet()<5) continue;
have_eye_counter.set(0);
if (event!=null) event.onEyeDetector(false);
LabelVisible(eye_indicator,false);
// Valid no eye condition
if (eye_state.get()!=0){
System.out.println("Transition from open to close eyes");
eye_state.set(0);
}
}
} else if (have_left_45_face ){
if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height);
LabelVisible(face_indicator,true);
} else {
// no face detected, but let's not cancel the previous state immediately
if (no_face_counter.incrementAndGet()<30) continue;
// beneran dianggap no face detected
eye_state.set(-1);
last_blink.set(0);
waiting_for_second_blink.set(false);
face_counter.set(0);
blink_counter.set(0);
no_eye_counter.set(0);
have_eye_counter.set(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.get());
LabelSetText(BlinkCounterLabel, "",null);
LabelVisible(face_indicator,false);
LabelVisible(eye_indicator,false);
}
}
UMat rgbmat = new UMat(LiveMat.size(), CV_8UC3);
cvtColor(LiveMat, rgbmat, COLOR_BGR2RGB);
Mat imgmat = new Mat();
rgbmat.copyTo(imgmat); // copy back to CPU
// Update Task Value usign matToWritableImage
setCameraStream(matToWritableImage(imgmat));
//updateValue(matToWritableImage(imgmat));
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+" interrupted");
}
}
});
// Camera Capture Thread
Thread cam_capture = new Thread(()->{
while (Capturing.get()) {
try {
// selama proses pengambilan foto, jangan ambil frame
if (TakingPhoto!=null) TakingPhoto.await();
IsGrabbingLiveView.drainPermits();
IsGrabbingLiveView.release();
//IsGrabbingLiveView.set(true);
Frame frame = null;
if (Capturing.get()) {
try{
frame = mGrabber.grab(); // grab frame
} catch (FrameGrabber.Exception e){
if (Capturing.get()){
// kalau ada exception padahal masih capturing. Kalau sudah tidak capturing, tidak peduli
if (ValidString(e.getMessage())){
String msg = e.getMessage();
System.out.println("Exception on "+Thread.currentThread().getName()+" :"+msg);
if (msg.contains("start() been called")){
if (Capturing.get()){
System.out.println("Camera "+Thread.currentThread().getName()+" has been stopped, restarting");
mGrabber.close();
//Wait(100);
mGrabber.start();
mGrabber.flush();
} else {
System.out.println("Camera "+Thread.currentThread().getName()+" has been stopped, not restarting");
}
}
}
}
}
}
//IsGrabbingLiveView.set(false);
if (frame==null) continue;
Mat mat = matconverter.convert(frame); // convert to Mat
fps.incrementAndGet();
UMat originalmat = new UMat();
mat.copyTo(originalmat); // copy to originalmat for using OpenCL
if (config.isMirrorCamera()){
// revisi 18/03/2025
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);
if (!BestMat.empty()) {
// LiveMat and GrayMat are synchronized
synchronized (lockObject){
opencv_imgproc.resize(BestMat, LiveMat, LiveSize); // resize to LiveSize
opencv_imgproc.cvtColor(LiveMat,GrayMat, COLOR_BGR2GRAY); // convert to grayscale
}
if (use_qr){
qr_semaphore.release();
}
if (use_face){
face_semaphore.release();
}
}
} catch ( FrameGrabber.Exception fe){
System.out.println("FrameGrabber Exception in" + Thread.currentThread().getName() + " : " + fe.getMessage());
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+" interrupted");
} catch (Exception e){
System.out.println(Thread.currentThread().getName()+" exception : "+e.getMessage());
}
}
});
public boolean StartLiveView(LiveCamEvent event, String cameratitle, boolean use_qr , boolean use_face) {
this.event = event;
if (mGrabber != null) {
try {
@@ -800,310 +1124,51 @@ public class Cameradetail {
Capturing.set(true);
if (event!=null) event.onStartCapturing();
Task<Image> task = new Task<>() {
TimerTask fpsTask = new TimerTask() {
@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
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
public void run() {
int fpsval = fps.getAndSet(0);
if (fpsval!=LiveFPS){
LiveFPS = fpsval;
if (event!=null) event.onIntervalUpdate();
AutoCloseAlert.ChangeCamStatus(switch (cameratitle){
case "01" -> 1;
case "02" -> 2;
case "03" -> 3;
case "04" -> 4;
case "05" -> 5;
default -> 0;
}, LiveFPS>0 );
}
}
};
Timer timer = new java.util.Timer();
timer.scheduleAtFixedRate(fpsTask, 1000, 1000);
while (Capturing.get()) {
try {
// selama proses pengambilan foto, jangan ambil frame
while(TakingPhoto.get() && Capturing.get()){
Wait(10);
}
if (!Capturing.get()) return null;
IsGrabbingLiveView.set(true);
Frame frame;
try{
frame = mGrabber.grab(); // grab frame
} catch (Exception e){
frame = null;
if (e.getMessage()!=null && !e.getMessage().isBlank()){
String msg = e.getMessage();
if (msg.contains("start() been called")){
if (Capturing.get()){
System.out.println("Camera "+cameratitle+" has been stopped, restarting");
mGrabber.close();
Wait(100);
mGrabber.start();
mGrabber.flush();
} else {
System.out.println("Camera "+cameratitle+" has been stopped, not restarting");
}
} else System.out.println("Exception on grab frame from camera "+cameratitle+", Message : "+e.getMessage());
}
}
if (frame==null) continue;
Mat mat = matconverter.convert(frame); // convert to Mat
fps.incrementAndGet();
UMat originalmat = new UMat();
mat.copyTo(originalmat); // copy to originalmat for using OpenCL
if (config.isMirrorCamera()){
// revisi 18/03/2025
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()) {
opencv_imgproc.resize(BestMat, LiveMat, LiveSize); // resize to LiveSize
opencv_imgproc.cvtColor(LiveMat,GrayMat, COLOR_BGR2GRAY); // convert to grayscale
if (use_qr){
String qr = DetectQRFromMat(GrayMat);
if (ValidBarCode(qr)){
qrtext = qr;
if (event!=null) event.onDetectedQRCode(qrtext);
}
}
if (use_face){
DetectorResult theface = null;
boolean have_frontal_face = false;
boolean have_left_45_face = false;
int _face_width = 0;
int _face_height = 0;
List<DetectorResult> frontalfaces = HaveFrontalFace(GrayMat);
if (!frontalfaces.isEmpty()){
for(DetectorResult rect : frontalfaces){
if (rect.haveFace() ){
rect.FaceRectangle(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 {
// gak punya frontal face
// coba cek punya profile left face 45 gak
List<DetectorResult> Left45Faces = HaveLeft45Face(GrayMat);
if (!Left45Faces.isEmpty()){
for(DetectorResult rect : Left45Faces){
if (rect.haveFace()){
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;
}
}
}
}
}
if (have_frontal_face){
if (face_counter[0]<5){
face_counter[0]++;
//System.out.println("Frontal Face Counter = "+face_counter+ " from camera "+cameratitle+" eye count = "+theface.getEyesCount());
//continue;
} else {
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 (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 ){
if (event!=null) event.onProfileFaceDetector(true, _face_width, _face_height);
//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[0]<60){
// toleransi no face selama 60 frame
no_face_counter[0]++;
continue;
} else {
// beneran dianggap no face detected
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[0]);
Platform.runLater(()->{
face_indicator.setVisible(false);
eye_indicator.setVisible(false);
BlinkCounterLabel.setText("");
});
//LabelSetText(BlinkCounterLabel, "",null);
//LabelVisible(face_indicator,false);
//LabelVisible(eye_indicator,false);
}
}
}
}
UMat rgbmat = new UMat(LiveMat.size(), CV_8UC3);
cvtColor(LiveMat, rgbmat, COLOR_BGR2RGB);
Mat imgmat = new Mat();
rgbmat.copyTo(imgmat); // copy back to CPU
// Update Task Value usign matToWritableImage
updateValue(matToWritableImage(imgmat));
}
} catch (Exception e) {
if (ValidString(e.getMessage())){
raise_log("Unable to Grab Frame, Error: " + e.getMessage());
}
//if (!Capturing.get()) Platform.runLater(this::StopLiveView);
public void run() {
if (Capturing.get()){
int fpsval = fps.getAndSet(0);
if (fpsval!=LiveFPS){
LiveFPS = fpsval;
if (event!=null) event.onIntervalUpdate();
AutoCloseAlert.ChangeCamStatus(switch (cameratitle){
case "01" -> 1;
case "02" -> 2;
case "03" -> 3;
case "04" -> 4;
case "05" -> 5;
default -> 0;
}, LiveFPS>0 );
}
} else {
fps.set(0);
this.cancel();
}
timer.cancel();
return null;
}
};
// value dari task, yaitu image, akan diupdate ke camerastream
task.valueProperty().addListener((obs, oldVal, newVal) -> {
if (newVal != null) {
setCameraStream(newVal);
}
});
timer.scheduleAtFixedRate(fpsTask, 1000, 1000);
// start task
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
this.use_qr = use_qr;
this.use_face = use_face;
cam_capture.setName("cam_capture "+cameratitle);
cam_capture.setDaemon(true);
cam_capture.start();
System.out.println("Starting cam_capture thread");
qr_detect.setName("qr_detect "+cameratitle);
qr_detect.setDaemon(true);
qr_detect.start();
System.out.println("Starting qr_detect thread");
face_detect.setName("face_detect "+cameratitle);
face_detect.setDaemon(true);
face_detect.start();
System.out.println("Starting face_detect thread");
return true;
} catch (Exception e) {
@@ -1204,14 +1269,6 @@ public class Cameradetail {
}
private double getBrightnessFromGrayMat(Mat graymat){
Scalar mean = mean(graymat);
return mean.get(0);
}
private WritableImage matToWritableImage(Mat mat){
int cols = mat.cols();
int rows = mat.rows();

View File

@@ -227,6 +227,35 @@ public class CaptureView {
}
static class CallablePhotoResult implements Callable<PhotoResult> {
private final String directory;
private final String prefix;
private final Cameradetail image;
public CallablePhotoResult(String directory, String prefix, Cameradetail image) {
this.directory = directory;
this.prefix = prefix;
this.image = image;
}
@Override
public PhotoResult call() {
if (image!=null){
image.RemapROI(0.1, 0.3, false);
double sharpness = CalculateSharpness(image.getGrayMat());
image.setSharpness_indicator(sharpness);
PhotoResult p = image.TakePhoto(directory, prefix);
p.setSharpscore(sharpness);
if (ValidFile(p.getFullres())){
if (ValidFile(p.getCompressedfile())){
return p;
}
}
}
return null;
}
}
private void take_photo_lanjutan(String directory, String prefix){
audioPlayer.PlayFile(audio_camera_shutter, null);
Size thumbsize = new Size(160,120);
@@ -238,91 +267,11 @@ public class CaptureView {
ExecutorService executor = Executors.newFixedThreadPool(5);
Callable<PhotoResult> task1 = ()->{
if (image1!=null) {
image1.RemapROI(0.1,0.3, false);
double sharpness = CalculateSharpness(image1.getGrayMat());
image1.setSharpness_indicator(sharpness);
PhotoResult p1 = image1.TakePhoto(directory,prefix);
p1.setSharpscore(sharpness);
if (ValidFile(p1.getFullres())){
if (ValidFile(p1.getCompressedfile())){
return p1;
}
}
} else System.out.println("Image1 is null");
return null;
};
Callable<PhotoResult> task2 = ()->{
if (image2!=null) {
image2.RemapROI(0.1,0.3, false);
double sharpness = CalculateSharpness(image2.getGrayMat());
image2.setSharpness_indicator(sharpness);
PhotoResult p2 = image2.TakePhoto(directory,prefix);
p2.setSharpscore(sharpness);
if (ValidFile(p2.getFullres())){
if (ValidFile(p2.getCompressedfile())){
return p2;
}
}
} else System.out.println("Image2 is null");
return null;
};
Callable<PhotoResult> task3 = ()->{
if (image3!=null) {
image3.RemapROI(0.1,0.3, false);
double sharpness = CalculateSharpness(image3.getGrayMat());
image3.setSharpness_indicator(sharpness);
PhotoResult p3 = image3.TakePhoto(directory,prefix);
p3.setSharpscore(sharpness);
if (ValidFile(p3.getFullres())){
if (ValidFile(p3.getCompressedfile())){
return p3;
}
}
} else System.out.println("Image3 is null");
return null;
};
Callable<PhotoResult> task4 = ()->{
if (image4!=null) {
image4.RemapROI(0.1,0.3, false);
double sharpness = CalculateSharpness(image4.getGrayMat());
image4.setSharpness_indicator(sharpness);
PhotoResult p4 = image4.TakePhoto(directory,prefix);
p4.setSharpscore(sharpness);
if (ValidFile(p4.getFullres())){
if (ValidFile(p4.getCompressedfile())){
return p4;
}
}
} else System.out.println("Image4 is null");
return null;
};
Callable<PhotoResult> task5 = ()->{
if (image5!=null) {
image5.RemapROI(0.1,0.3, false);
double sharpness = CalculateSharpness(image5.getGrayMat());
image5.setSharpness_indicator(sharpness);
PhotoResult p5 = image5.TakePhoto(directory,prefix);
p5.setSharpscore(sharpness);
if (ValidFile(p5.getFullres())){
if (ValidFile(p5.getCompressedfile())){
return p5;
}
}
} else System.out.println("Image5 is null");
return null;
};
CallablePhotoResult task1 = new CallablePhotoResult(directory, prefix, image1);
CallablePhotoResult task2 = new CallablePhotoResult(directory, prefix, image2);
CallablePhotoResult task3 = new CallablePhotoResult(directory, prefix, image3);
CallablePhotoResult task4 = new CallablePhotoResult(directory, prefix, image4);
CallablePhotoResult task5 = new CallablePhotoResult(directory, prefix, image5);
PhotoResult p1 = null;
PhotoResult p2 = null;
@@ -943,7 +892,6 @@ public class CaptureView {
PatientRecord pr = checkpatientID.getValue();
if (pr!=null){
int medrecid = toInt(pr.medical_record_detail_id);
System.out.println("checkpatientID.setOnSucceeded medrecid : "+medrecid);
TextAreaSetText(medicalRecordID,""+medrecid);
TextAreaSetText(PatientName, pr.name);
@@ -1051,25 +999,22 @@ public class CaptureView {
}
private void update_status(Cameradetail image){
Platform.runLater(()-> {
String sb = "Camera Started, " +
image.getBestWidth() +
"x" +
image.getBestHeight() +
"@" +
image.getLiveFPS();
String sb = "Camera Started, " +
image.getBestWidth() +
"x" +
image.getBestHeight() +
"@" +
image.getLiveFPS();
image.setCameraStatus(sb);
});
image.setCameraStatus(sb);
}
};
Platform.runLater(()-> image.setCameraStatus("Camera Starting"));
image.setCameraStatus("Camera Starting");
if (image.StartLiveView(lce, title, use_qr_detector, use_face_detector)){
//TODO Start Live View berhasil, apa lagi yang mau dikerjakan ?
} else Platform.runLater(()->image.setCameraStatus("Unable to Set Grabber"));
} else Platform.runLater(()->image.setCameraStatus("Camera not found, please check setting"));
} else image.setCameraStatus("Unable to Set Grabber");
} else image.setCameraStatus("Camera not found, please check setting");
}
}

View File

@@ -22,6 +22,9 @@ import static Config.SomeCodes.config;
public class MainApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
SecureDongle sd = new SecureDongle((short)0x4B30, (short)0xA66C, (short)0x3109, (short)0x37B1);
if (sd.Find()){
if (sd.Open()){
@@ -34,7 +37,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 10042025-005");
stage.setTitle("MultiCam Capture App for ERHA 11042025-003");
stage.setScene(scene);
stage.setResizable(true);
stage.setMaximized(true);