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

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);