Improvement 21/01/2025

This commit is contained in:
2025-01-21 10:53:41 +07:00
parent 30660b9afb
commit f80662a453
24 changed files with 210383 additions and 25739 deletions

View File

@@ -1,4 +1,4 @@
#Wed Jan 15 10:18:31 WIB 2025
#Mon Jan 20 17:42:44 WIB 2025
AudioPhase1=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase1.mp3
AudioPhase2=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase2.mp3
AudioPhase3=C\:\\Users\\rdkar\\OneDrive\\Documents\\IntelliJ Project\\ErhaCam\\audio\\phase3.mp3

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

29690
haarcascade_profileface.xml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

101
pom.xml
View File

@@ -40,12 +40,111 @@
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.10</version>
<exclusions>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>leptonica-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>artoolkitplus-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libdc1394-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect2-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense2-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>tesseract-platform</artifactId>
</exclusion>
<!-- platform dibuangin semua, kemudian tambah sendiri linux-arm64, windows-x86_64, linux-x86_64 -->
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flandmark-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>openblas-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>videoinput-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>opencv-platform</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>videoinput</artifactId>
<version>0.200-1.5.9</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.10</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.10</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>

View File

@@ -3,5 +3,7 @@ package Camera;
public interface LiveCamEvent {
void onDetectedQRCode(String qrCode);
void onFaceDetector(boolean hasface, int width, int height);
void onEyeDetector(boolean hasEye, int width, int height);
void onLog(String log);
void onBlink(int counter);
}

View File

@@ -278,16 +278,7 @@ public class SomeCodes {
}
}
public static CascadeClassifier faceDetector;
public static void LoadFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_frontalface_alt.xml");
if (filename!=null) {
if (faceDetector==null) {
faceDetector = new CascadeClassifier(filename);
Logger.info("FaceDetector loaded");
}
}
}
public static String[] MakeArray(String... args){
if (args!=null && args.length>0){

View File

@@ -23,8 +23,10 @@ import javafx.scene.image.WritableImage;
import javafx.scene.layout.AnchorPane;
import lombok.Getter;
import lombok.Setter;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*;
@@ -42,6 +44,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.faceDetector;
import static id.co.gtc.erhacam.Detectors.eyeDetector;
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_imgcodecs.imwrite;
@@ -49,6 +53,15 @@ import static org.bytedeco.opencv.global.opencv_imgproc.*;
@SuppressWarnings({"unused"})
public class Cameradetail {
private static final boolean isCudaAvailable ;
static{
isCudaAvailable = opencv_core.getCudaEnabledDeviceCount()>0;
if (isCudaAvailable){
System.out.println("CUDA is available");
} else {
System.out.println("CUDA is not available");
}
}
private final AtomicBoolean Capturing = new AtomicBoolean(false);
private final AtomicBoolean TakingPhoto = new AtomicBoolean(false);
private final AtomicBoolean IsGrabbingLiveView = new AtomicBoolean(false);
@@ -87,7 +100,6 @@ public class Cameradetail {
@FXML
private Slider exposureSlider;
private final UMat BestMat = new UMat();
private final UMat LiveMat = new UMat();
private final UMat ReducedMat = new UMat();
@@ -95,6 +107,14 @@ public class Cameradetail {
private Size ReducedSize = new Size(1280, 720);
private Size BestSize = new Size(1920, 1080);
public int getBestWidth(){
return BestSize.width();
}
public int getBestHeight(){
return BestSize.height();
}
private void setSliderValue(Slider sld, CameraProperty prop, double value){
if (sld!=null){
sld.setMin(prop.Min);
@@ -621,6 +641,9 @@ public class Cameradetail {
protected Image call() {
// repeat until capturing is false
AtomicInteger fps = new AtomicInteger(0);
AtomicBoolean eye_was_closed = new AtomicBoolean(false);
AtomicInteger blink_counter = new AtomicInteger(0);
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
@@ -640,8 +663,8 @@ public class Cameradetail {
IsGrabbingLiveView.set(true);
Frame frame = mGrabber.grab(); // grab frame
Mat mat = matconverter.convert(frame); // convert to Mat
if (mat.empty()) continue; // kalau gak ada data, continue
int counter = fps.incrementAndGet();
if (mat.empty()) continue; // kalau gak ada data, continue
if (counter % 5 != 0) continue; // frame skip to 6 fps
mat.copyTo(BestMat); // copy to BestMat for using OpenCL
@@ -664,12 +687,47 @@ public class Cameradetail {
if (use_face){
RectVector face = DetectFace(graymat);
if (face!=null && face.size()>0){
// ada muka
if (event!=null) event.onFaceDetector(true, BestSize.width(), BestSize.height());
for(int i=0; i<face.size(); i++){
Rect rect = face.get(i);
rectangle(LiveMat, rect, Scalar.GREEN);
}
} else if (event!=null) event.onFaceDetector(false, BestSize.width(), BestSize.height());
// kalau detect muka, baru coba detect mata
RectVector eye = DetectEye(graymat);
if (eye!=null && eye.size()>=2){
// ada mata
if (eye_was_closed.get()){
eye_was_closed.set(false);
if (blink_counter.get()>=2){
blink_counter.set(0);
if (event!=null) event.onBlink(blink_counter.get());
}
}
if (event!=null) event.onEyeDetector(true, BestSize.width(), BestSize.height());
for(int i=0; i<eye.size(); i++){
Rect rect = eye.get(i);
rectangle(LiveMat, rect, Scalar.RED);
}
} else {
// mata tidak ada
if (!eye_was_closed.get()){
eye_was_closed.set(true);
blink_counter.incrementAndGet();
}
if (event!=null) event.onEyeDetector(false, BestSize.width(), BestSize.height());
}
} else {
eye_was_closed.set(false);
blink_counter.set(0);
// tidak ada muka, tidak ada mata
if (event!=null) event.onFaceDetector(false, BestSize.width(), BestSize.height());
if (event!=null) event.onEyeDetector(false, BestSize.width(), BestSize.height());
}
}
@@ -747,6 +805,15 @@ public class Cameradetail {
return null;
}
private RectVector DetectEye(UMat graymat){
if (eyeDetector!=null){
RectVector eye = new RectVector();
eyeDetector.detectMultiScale(graymat, eye);
return eye;
}
return null;
}
private double getBrightnessFromGrayMat(Mat graymat){
Scalar mean = mean(graymat);
return mean.get(0);

View File

@@ -68,6 +68,8 @@ public class CaptureView {
private List<String> cams;
private final AtomicBoolean[] have_face = new AtomicBoolean[5];
private final AtomicBoolean[] have_eyes = new AtomicBoolean[5];
private final AtomicBoolean isTakingPhoto = new AtomicBoolean(false);
@FXML
private void ChangeDirectory(){
@@ -116,6 +118,7 @@ public class CaptureView {
String prefix = RemoveSpaces(prefixfile.getText()) ;
if (ValidDirectory(directory)){
if (ValidString(prefix)){
isTakingPhoto.set(true);
//audioPlayer.PlayFile(audio_posisi_diam, ps);
PhotoReviewClass prc = new PhotoReviewClass();
prc.setPrefix(prefix);
@@ -211,6 +214,8 @@ public class CaptureView {
long duration = (System.nanoTime() - nanostart) / 1000000; // in milliseconds
System.out.println("TakePhotos duration: "+duration+" ms");
// TODO test taruh sini
isTakingPhoto.set(false);
audioPlayer.PlayFile(audio_foto_selesai, ps);
String[] files = prc.files();
@@ -458,6 +463,14 @@ public class CaptureView {
case CameraConfigRight90 -> have_face[4];
};
final AtomicBoolean _have_eye = switch (image.getCameraConfigEnum()){
case CameraConfigCenter -> have_eyes[2];
case CameraConfigLeft45 -> have_eyes[1];
case CameraConfigLeft90 -> have_eyes[0];
case CameraConfigRight45 -> have_eyes[3];
case CameraConfigRight90 -> have_eyes[4];
};
Platform.runLater(()-> image.setCameraTitle(title));
if (devicenumber!=-1){
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(devicenumber);
@@ -497,13 +510,9 @@ public class CaptureView {
}
image.SetGrabber(grabber, livewidth,liveheight,photowidth,photoheight,reducewidth,reduceheight);
//TODO reconfirm requirement again
boolean use_face_detector = true;
boolean use_qr_detector = true;
LiveCamEvent lce = new LiveCamEvent() {
@Override
public void onDetectedQRCode(String qrCode) {
@@ -513,13 +522,14 @@ public class CaptureView {
@Override
public void onFaceDetector(boolean hasface, int width, int height) {
Platform.runLater(()-> {
String ss = hasface ? String.format("Camera Started, %dx%d@%d, Face Detected", width, height, image.getLiveFPS()) : String.format("Camera Started, %dx%d@%d", width, height, image.getLiveFPS());
image.setCameraStatus(ss);
_have_face.set(hasface);
update_status(image);
}
//if (ValidString(qr) && hasface) audioPlayer.PlayFile(audio_posisikan_muka, ps);
});
@Override
public void onEyeDetector(boolean hasEye, int width, int height) {
_have_eye.set(hasEye);
update_status(image);
}
@Override
@@ -527,6 +537,31 @@ public class CaptureView {
String ss = String.format("[%s] : %s", title, log);
Logger.info(ss);
}
@Override
public void onBlink(int counter) {
String prefix = prefixfile.getText();
if (!prefix.isEmpty()){
if (isTakingPhoto.get()) return; // other camera already detect blinking
btnTakePhoto.fire();
}
}
private void update_status(Cameradetail image){
Platform.runLater(()-> {
StringBuilder sb = new StringBuilder();
sb.append("Camera Started, ");
sb.append(image.getBestWidth());
sb.append("x");
sb.append(image.getBestHeight());
sb.append("@");
sb.append(image.getLiveFPS());
if (_have_face.get()) sb.append(", Face Detected");
if (_have_eye.get()) sb.append(", Eye Detected");
image.setCameraStatus(sb.toString());
});
}
};
Platform.runLater(()-> image.setCameraStatus("Camera Starting"));
@@ -542,7 +577,7 @@ public class CaptureView {
try{
have_face[camid-1] = new AtomicBoolean(false);
have_eyes[camid-1] = new AtomicBoolean(false);
FXMLLoader loader = new FXMLLoader(getClass().getResource("cameradetail.fxml"));
AnchorPane child = loader.load();

View File

@@ -0,0 +1,44 @@
package id.co.gtc.erhacam;
import Config.SomeCodes;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import org.bytedeco.opencv.opencv_objdetect.CvHaarClassifierCascade;
import org.tinylog.Logger;
public class Detectors {
public static CascadeClassifier faceDetector;
public static CascadeClassifier eyeDetector;
public static void LoadFaceDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_profileface.xml");
if (filename!=null) {
System.out.println("Face Detector file : " + filename);
if (faceDetector==null) {
try{
faceDetector = new CascadeClassifier(filename);
Logger.info("FaceDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading FaceDetector : " + e.getMessage());
}
} else Logger.info("FaceDetector already loaded");
} else Logger.error("Unable to extract face detector file");
}
public static void LoadEyeDetector(){
String filename = SomeCodes.ExtractResource("/haarcascade_eye_tree_eyeglasses.xml");
if (filename!=null) {
System.out.println("Eye Detector file : " + filename);
if (eyeDetector==null) {
try{
eyeDetector = new CascadeClassifier(filename);
Logger.info("EyeDetector loaded");
} catch (Exception e){
Logger.error("Exception on loading EyeDetector : " + e.getMessage());
}
} else Logger.info("EyeDetector already loaded");
} else Logger.error("Unable to extract eye detector file");
}
}

View File

@@ -32,7 +32,8 @@ public class MainApplication extends Application {
Logger.info("Application closed");
});
SomeCodes.LoadQRReader();
SomeCodes.LoadFaceDetector();
Detectors.LoadFaceDetector();
Detectors.LoadEyeDetector();
stage.show();
Logger.info("Application started");
}

View File

@@ -0,0 +1,8 @@
package id.co.gtc.erhacam;
import org.bytedeco.opencv.opencv_core.Mat;
public interface MatType {
void CopyFrom(Mat src);
void CopyTo(Mat dest);
}

View File

@@ -39,6 +39,7 @@ import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicBoolean;
import static Config.SomeCodes.*;
import static id.co.gtc.erhacam.Detectors.faceDetector;
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_imgcodecs.imwrite;

View File

@@ -1,4 +1,5 @@
writer = rolling file
#writer = rolling file
writer = console
writer.file = logs/{date:yyyy-MM-dd}.log
writer.format = {date:yyyy-MM-dd HH:mm:ss} {level}: {class}.{method}() {message}
//writer.format = {date:yyyy-MM-dd HH:mm:ss} {level}: {message}