YOLODetector is working (25/02/2025)

This commit is contained in:
2025-02-25 13:56:57 +07:00
parent ce5c8d5946
commit 5f8d1946c0
6 changed files with 248 additions and 433 deletions

BIN
onnx/yolov8m.onnx Normal file

Binary file not shown.

205
pom.xml
View File

@@ -15,169 +15,62 @@
</repository> </repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.11</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.10.0-1.5.11</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.10.0-1.5.11</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>7.1-1.5.11</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>7.1-1.5.11</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.28-1.5.11</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.28-1.5.11</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency> <dependency>
<groupId>org.bytedeco</groupId> <groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId> <artifactId>tensorrt</artifactId>
<version>1.5.8</version> <version>8.6-1.5.10</version>
<exclusions>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>leptonica</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>leptonica-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>artoolkitplus</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>artoolkitplus-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libdc1394</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libdc1394-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect2</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>libfreenect2-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense2</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>librealsense2-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>videoinput</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>videoinput-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>tesseract</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>javacpp-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>openblas-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>opencv-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flandmark</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco</groupId>
<artifactId>flandmark-platform</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- manual tambah untuk platform windows-x86_64 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.6.0-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.21-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>5.1.2-1.5.8</version>
<classifier>windows-x86_64</classifier>
</dependency>
<!-- manual tambah untuk platform linux-arm64-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.6.0-1.5.8</version>
<classifier>linux-arm64</classifier> <classifier>linux-arm64</classifier>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bytedeco</groupId> <groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId> <artifactId>cuda</artifactId>
<version>1.5.8</version> <version>12.6-9.5-1.5.11</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.21-1.5.8</version>
<classifier>linux-arm64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>5.1.2-1.5.8</version>
<classifier>linux-arm64</classifier> <classifier>linux-arm64</classifier>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.corundumstudio.socketio</groupId> <groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId> <artifactId>netty-socketio</artifactId>
@@ -186,7 +79,7 @@
<dependency> <dependency>
<groupId>io.javalin</groupId> <groupId>io.javalin</groupId>
<artifactId>javalin</artifactId> <artifactId>javalin</artifactId>
<version> 6.3.0</version> <version> 6.4.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.java.dev.jna</groupId> <groupId>net.java.dev.jna</groupId>
@@ -201,7 +94,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.34</version> <version>1.18.36</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>

View File

@@ -9,7 +9,10 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber; import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.opencv.opencv_core.Mat; import org.bytedeco.javacv.OpenCVFrameConverter;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.tinylog.Logger; import org.tinylog.Logger;
public class GrabbingTask implements Runnable { public class GrabbingTask implements Runnable {
@@ -98,30 +101,52 @@ public class GrabbingTask implements Runnable {
isGrabbing.set(false); isGrabbing.set(false);
} }
private void processFrame(Frame fr){ private void processFrame(Frame fr){
if (fr!=null){ if (fr!=null && fr.image!=null && fr.imageWidth>0 && fr.imageHeight>0){
try(var converter = new OpenCVFrameConverter.ToOrgOpenCvCoreMat()){
org.opencv.core.Mat mat = converter.convert(fr);
if (mat.cols()>0 && mat.rows()>0){
updateHQFrame(fr); updateHQFrame(fr);
updateHQBase64(SomeCodes.FrameToBase64(fr)); updateHQBase64(SomeCodes.MatToBase64(mat));
Frame resized = SomeCodes.ResizeFrame(fr, lowquality_width, lowquality_height); Size lowsize = new Size(lowquality_width, lowquality_height);
updateLQFrame(resized); Mat resized = new Mat();
updateLQBase64(SomeCodes.FrameToBase64(resized)); Imgproc.resize(mat, resized, lowsize);
} else updateMessage("processFrame have null frame"); if (resized.cols()>0 && resized.rows()>0){
Frame resizedFrame = SomeCodes.CoreMatConverter.convert(resized);
updateLQFrame(resizedFrame);
updateLQBase64(SomeCodes.MatToBase64(resized));
} else System.out.println("processFrame resized size is 0");
DetectYolo(mat);
resized.release();
} else System.out.println("processFrame Mat size is 0");
mat.release();
} catch (Exception e){
Logger.error("Error processing frame: "+e.getMessage());
} }
//TODO masih trouble di sini } else {
private void DetectYolo(Frame frame){ System.out.println("processFrame have null frame");
if (frame!=null){ updateMessage("processFrame have null frame");
}
}
private void DetectYolo(Mat mat){
if (mat!=null && mat.cols()>0 && mat.rows()>0){
//System.out.println("DetectYolo mat cols = "+mat.cols()+", rows = "+mat.rows());
try{ try{
Mat processed = yolo.Detect(frame); Mat[] processed = yolo.Detect(mat);
Frame yoloFrame = SomeCodes.CoreMatConverter.convert(processed); Mat yolomat = yolo.Process(mat, processed[0], processed[1]);
Frame yoloFrame = SomeCodes.CoreMatConverter.convert(yolomat);
updateYoloFrame(yoloFrame); updateYoloFrame(yoloFrame);
updateYoloBase64(SomeCodes.FrameToBase64(yoloFrame)); updateYoloBase64(SomeCodes.MatToBase64(yolomat));
} catch (Exception e){ } catch (Exception e){
System.out.println("error processing YOLO, Message : "+e.getMessage()); System.out.println("error processing YOLO, Message : "+e.getMessage());
updateYoloFrame(null); updateYoloFrame(null);
updateYoloBase64(""); updateYoloBase64("");
} }
} } else System.out.println("DetectYolo mat is null");
} }
@@ -150,7 +175,6 @@ public class GrabbingTask implements Runnable {
if (framecount<Integer.MAX_VALUE) framecount++; else framecount = 0; if (framecount<Integer.MAX_VALUE) framecount++; else framecount = 0;
if (framecount % skippedframes == 0) { if (framecount % skippedframes == 0) {
processFrame(frame); processFrame(frame);
DetectYolo(frame);
} }
} catch (Exception e){ } catch (Exception e){
Logger.error("Error grabbing frame: "+e.getMessage()); Logger.error("Error grabbing frame: "+e.getMessage());

View File

@@ -2,23 +2,15 @@ package Camera;
import Other.SomeCodes; import Other.SomeCodes;
import lombok.Getter; import lombok.Getter;
import org.bytedeco.javacv.Frame;
import org.bytedeco.opencv.global.opencv_dnn; import org.opencv.core.*;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Rect;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_dnn.*;
import org.opencv.core.MatOfFloat;
import org.opencv.core.MatOfInt;
import org.opencv.core.MatOfRect2d;
import org.opencv.dnn.Dnn; import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.imgproc.Imgproc;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileReader; import java.io.FileReader;
import java.nio.FloatBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -28,11 +20,9 @@ public class YoloDetector {
private Net net; private Net net;
private @Getter boolean NetLoaded; private @Getter boolean NetLoaded;
private List<String> classes ; private List<String> classes ;
// YOLO expect image in 640 x 640
private final int input_width = 640;
private final int input_height = 640;
// minimum confidence for detections // minimum confidence for detections
private final float confidence_threshold = 0.5f; private final float confidence_threshold = 0.4f;
// Non-maximum suppression threshold // Non-maximum suppression threshold
private final float nms_threshold = 0.4f; private final float nms_threshold = 0.4f;
@@ -44,11 +34,13 @@ public class YoloDetector {
String namesfile = SomeCodes.ExtractResource("/coco.names", SomeCodes.currentDirectory); String namesfile = SomeCodes.ExtractResource("/coco.names", SomeCodes.currentDirectory);
if (SomeCodes.ValidFile(onnxfile)){ if (SomeCodes.ValidFile(onnxfile)){
if (SomeCodes.ValidFile(namesfile)){ if (SomeCodes.ValidFile(namesfile)){
net = opencv_dnn.readNetFromONNX(onnxfile); net = Dnn.readNetFromONNX(onnxfile);
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV); net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
net.setPreferableTarget(Dnn.DNN_TARGET_CPU); net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
classes = new ArrayList<>(); classes = new ArrayList<>();
if (namesfile!=null){
try(BufferedReader br = new BufferedReader(new FileReader(namesfile))) { try(BufferedReader br = new BufferedReader(new FileReader(namesfile))) {
String line; String line;
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
@@ -57,6 +49,7 @@ public class YoloDetector {
} catch (Exception e){ } catch (Exception e){
System.out.println("Error: reading names file"); System.out.println("Error: reading names file");
} }
}
if (!net.empty()){ if (!net.empty()){
if (!classes.isEmpty()){ if (!classes.isEmpty()){
@@ -67,26 +60,65 @@ public class YoloDetector {
} else System.out.println("Error: onnx file not found"); } else System.out.println("Error: onnx file not found");
} }
public Mat Detect(Frame frame){ public Mat[] Detect(Mat frame){
Mat mat = SomeCodes.CoreMatConverter.convertToMat(frame);
return Detect(mat);
}
public Mat Detect(Mat frame){
if (NetLoaded){ if (NetLoaded){
Mat blob = opencv_dnn.blobFromImage(frame, 1.0/255.0, new Size(input_width, input_height), new Scalar(0) , true, false, CV_32F); Size inputSize = new Size(640, 640);
Scalar mean = new Scalar(0, 0, 0, 0);
float scaleFactor = 1.0f/255.0f;
boolean swapRB = true;
boolean crop = true;
Mat blob = Dnn.blobFromImage(frame, scaleFactor, inputSize, mean , swapRB, crop, CV_32F);
//Mat blob = Dnn.blobFromImage(frame, scaleFactor, inputSize);
net.setInput(blob); net.setInput(blob);
Mat detections = net.forward(); Mat predict = net.forward();
return detections; Mat mask = predict.reshape(0,1).reshape(0, predict.size(1));
return new Mat[]{predict,mask};
} else { } else {
System.out.println("Error: Net not loaded"); System.out.println("Error: Net not loaded");
return new Mat(); return new Mat[0];
} }
} }
private Mat ProcessDetection(Mat frame, Mat output){ public Mat Process(Mat frame, Mat predict, Mat mask){
double width = frame.cols() / 640.0;
double height = frame.rows() / 640.0;
Rect2d[] rect2d = new Rect2d[mask.cols()];
float[] scoref = new float[mask.cols()];
int[] classid = new int[mask.cols()];
for(int i=0;i<mask.cols();i++){
double[] x = mask.col(i).get(0, 0);
double[] y = mask.col(i).get(1, 0);
double[] w = mask.col(i).get(2, 0);
double[] h = mask.col(i).get(3, 0);
rect2d[i] = new Rect2d((x[0]-w[0]/2)*width, (y[0]-h[0]/2)*height, w[0]*width, h[0]*height);
Mat score = mask.col(i).submat(4, predict.size(1)-1,0,1) ;
Core.MinMaxLocResult mm = Core.minMaxLoc(score);
scoref[i] = (float)mm.maxVal;
classid[i] = (int)mm.maxLoc.y;
}
MatOfRect2d bboxes = new MatOfRect2d(rect2d);
MatOfFloat scores = new MatOfFloat(scoref);
MatOfInt indices = new MatOfInt();
Dnn.NMSBoxes(bboxes, scores, confidence_threshold, nms_threshold, indices);
int[] idx = indices.toArray();
for(int ii : idx){
//System.out.println("Detected ["+ii+"] ClassID: "+classid[ii]+" Label: "+classes.get(classid[ii])+" Confidence: "+scoref[ii]);
Rect rr = new Rect(rect2d[ii].tl(), rect2d[ii].size());
Imgproc.rectangle(frame, rr, new Scalar(0, 255, 0), 2);
Imgproc.putText(frame, classes.get(classid[ii])+" "+String.format("%.2f", scoref[ii]), rr.tl(), Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(0, 0, 255));
}
return frame;
}
public Mat processDetection(Mat frame, Mat output){
int rows = output.rows(); int rows = output.rows();
int cols = output.cols(); int cols = output.cols();
List<Rect> boxes = new ArrayList<>(); List<Rect> boxes = new ArrayList<>();
@@ -95,73 +127,78 @@ public class YoloDetector {
for (int i = 0; i < rows; i++){ for (int i = 0; i < rows; i++){
Mat row = output.row(i); Mat row = output.row(i);
float confidence = row.getFloatBuffer().get(4); Mat scores = row.colRange(5, cols);
if (confidence >= confidence_threshold){ Core.MinMaxLocResult mm = Core.minMaxLoc(scores);
FloatBuffer data = row.getFloatBuffer(); float confidence = (float)mm.maxVal;
int classid = 0; Point classIdPoint = mm.maxLoc;
float maxscore = 0; if (confidence>confidence_threshold){
for(int j = 5; j< cols; j++){ int centerX = (int)(row.get(0, 0)[0] * frame.cols());
float score = data.get(j); int centerY = (int)(row.get(0, 1)[0] * frame.rows());
if (score > maxscore){ int width = (int)(row.get(0, 2)[0] * frame.cols());
maxscore = score; int height = (int)(row.get(0, 3)[0] * frame.rows());
classid = j-5; int left = centerX - width / 2;
} int top = centerY - height / 2;
} boxes.add(new Rect(left, top, width, height));
if (maxscore>= confidence_threshold){ confidences.add(confidence);
int x = (int)(data.get(0) * frame.cols()); classIds.add((int)classIdPoint.x);
int y = (int)(data.get(1) * frame.rows());
int width = (int)(data.get(2) * frame.cols());
int height = (int)(data.get(3) * frame.rows());
boxes.add(new Rect(x-width/2, y-height/2, width, height));
confidences.add(maxscore);
classIds.add(classid);
}
} }
} }
Rect[] rr = new Rect[boxes.size()]; MatOfRect2d rects = new MatOfRect2d(ToRect2D(boxes));
for(int ii = 0; ii<boxes.size(); ii++){ MatOfFloat conf = new MatOfFloat(ToFloatArray(confidences));
rr[ii] = boxes.get(ii); MatOfInt ids = new MatOfInt();
}
MatOfRect2d rects = new MatOfRect2d(ListToRectArray(boxes));
MatOfFloat conf = new MatOfFloat(ListToArray(confidences)); Dnn.NMSBoxes(rects, conf, confidence_threshold, nms_threshold, ids);
MatOfInt indices = new MatOfInt(); int[] indices = ids.toArray();
if (indices.length>0){
for (int idx : indices){
if (!boxes.isEmpty()){ Rect box = boxes.get(idx);
Dnn.NMSBoxes(rects, conf, confidence_threshold, nms_threshold, indices); int classId = classIds.get(idx);
} float confidence = confidences.get(idx);
int[] idx = indices.toArray();
for(int i : idx){
Rect box = boxes.get(i);
int classId = classIds.get(i);
float confidence = confidences.get(i);
String label = classes.get(classId); String label = classes.get(classId);
opencv_imgproc.rectangle(frame, box, Scalar.RED); System.out.println("Detect ["+idx+"] ClassID: "+classId+" Label: "+label+" Confidence: "+confidence);
Imgproc.rectangle(frame, box, new Scalar(0, 255, 0), 2);
String text = label + " " + String.format("%.2f", confidence);
int[] baseLine = new int[1];
Size labelSize = Imgproc.getTextSize(text, Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, 1, baseLine);
Imgproc.rectangle(frame, new Point(box.x, box.y - labelSize.height),
new Point(box.x + labelSize.width, box.y + baseLine[0]),
new Scalar(255, 255, 255), Imgproc.FILLED);
Imgproc.putText(frame, text, new Point(box.x, box.y),
Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(0, 0, 0));
} }
} else System.out.println("No detections");
return frame; return frame;
} }
private org.opencv.core.Rect2d[] ListToRectArray(List<Rect> list){ private Rect2d[] ToRect2D(List<Rect> list){
org.opencv.core.Rect2d[] arr = new org.opencv.core.Rect2d[list.size()]; if (list!=null && list.size()>0){
Rect2d array[] = new Rect2d[list.size()];
for (int i = 0; i < list.size(); i++){ for (int i = 0; i < list.size(); i++){
Rect r = list.get(i); Rect r = list.get(i);
arr[i] = new org.opencv.core.Rect2d(r.x(), r.y(), r.width(), r.height()); array[i] = new Rect2d(r.x, r.y, r.width, r.height);
} }
return arr; return array;
}
return new Rect2d[0];
} }
private float[] ListToArray(List<Float> list){ private float[] ToFloatArray(List<Float> list){
float[] arr = new float[list.size()]; if (list!=null && list.size()>0){
float array[] = new float[list.size()];
for (int i = 0; i < list.size(); i++){ for (int i = 0; i < list.size(); i++){
arr[i] = list.get(i); array[i] = list.get(i);
} }
return arr; return array;
}
return new float[0];
} }
} }

View File

@@ -3,10 +3,9 @@ package Other;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.bytedeco.javacpp.Loader; import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter; import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.global.opencv_core; import org.bytedeco.opencv.global.opencv_core;
import org.bytedeco.opencv.global.opencv_dnn; import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc; import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*; import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_java; import org.bytedeco.opencv.opencv_java;
@@ -16,16 +15,11 @@ import org.opencv.imgcodecs.Imgcodecs;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.io.*; import java.io.*;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.file.*; import java.nio.file.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64; import java.util.Base64;
import java.util.Properties; import java.util.Properties;
@SuppressWarnings("unused")
public class SomeCodes { public class SomeCodes {
static{ static{
Loader.load(opencv_java.class); Loader.load(opencv_java.class);
@@ -33,12 +27,8 @@ public class SomeCodes {
public final static String currentDirectory = System.getProperty("user.dir"); public final static String currentDirectory = System.getProperty("user.dir");
public final static Path audioPath = Path.of(currentDirectory, "audiofiles"); public final static Path audioPath = Path.of(currentDirectory, "audiofiles");
private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final OpenCVFrameConverter.ToMat matConverter = new OpenCVFrameConverter.ToMat();
public static final OpenCVFrameConverter.ToOrgOpenCvCoreMat CoreMatConverter = new OpenCVFrameConverter.ToOrgOpenCvCoreMat(); public static final OpenCVFrameConverter.ToOrgOpenCvCoreMat CoreMatConverter = new OpenCVFrameConverter.ToOrgOpenCvCoreMat();
public static final Java2DFrameConverter frameConverter = new Java2DFrameConverter();
public static final Path logsPath = Path.of(currentDirectory, "logs");
public static final boolean haveOpenCL = opencv_core.haveOpenCL(); public static final boolean haveOpenCL = opencv_core.haveOpenCL();
public static boolean useOpenCL; public static boolean useOpenCL;
private static final Base64.Encoder base64encoder = java.util.Base64.getEncoder(); private static final Base64.Encoder base64encoder = java.util.Base64.getEncoder();
@@ -47,6 +37,7 @@ public class SomeCodes {
public static final double MB_threshold = 1024.0 * 1024.0; public static final double MB_threshold = 1024.0 * 1024.0;
public static final double GB_threshold = 1024.0 * 1024.0 * 1024.0; public static final double GB_threshold = 1024.0 * 1024.0 * 1024.0;
@SuppressWarnings("resource")
public static String[] GetAudioFiles(){ public static String[] GetAudioFiles(){
try{ try{
return Files.list(audioPath).map(f -> f.getFileName().toString()).toArray(String[]::new); return Files.list(audioPath).map(f -> f.getFileName().toString()).toArray(String[]::new);
@@ -57,10 +48,6 @@ public class SomeCodes {
return new String[0]; return new String[0];
} }
public static String LocalDateTimeToString(LocalDateTime x){
return x.format(dtf);
}
public static String ExtractResource(String filename, String targetdirectory){ public static String ExtractResource(String filename, String targetdirectory){
try { try {
File destination = new File(targetdirectory, filename); File destination = new File(targetdirectory, filename);
@@ -88,13 +75,7 @@ public class SomeCodes {
public static boolean ValidDirectory(String path){
if (ValidString(path)){
File ff = new File(path);
return ff.isDirectory();
}
return false;
}
public static boolean ValidFile(String filename){ public static boolean ValidFile(String filename){
if (ValidString(filename)){ if (ValidString(filename)){
@@ -143,41 +124,12 @@ public class SomeCodes {
} }
} }
public static boolean ValidIPV4(String ipaddress){ public static String MatToBase64(Mat mat){
if (ValidString(ipaddress)){ if (mat!=null){
try{ if (mat.cols()>0 && mat.rows()>0){
InetAddress inet = InetAddress.getByName(ipaddress); byte[] mob = new byte[mat.cols()*mat.rows()*mat.channels()];
if (inet instanceof Inet4Address){ opencv_imgcodecs.imencode(".jpg", mat, mob);
if (inet.getHostAddress().equals(ipaddress)){ return base64encoder.encodeToString(mob);
return true;
}
}
} catch (Exception ignored) {
}
}
return false;
}
public static boolean ValidIPV6(String ipaddress){
if (ValidString(ipaddress)){
try{
InetAddress inet = InetAddress.getByName(ipaddress);
if (inet instanceof Inet6Address){
if (inet.getHostAddress().equals(ipaddress)){
return true;
}
}
} catch (Exception ignored) {
}
}
return false;
}
public static String GetFileName(String filepath){
if (ValidString(filepath)){
File ff = new File(filepath);
if (ff.isFile()){
return ff.getName();
} }
} }
return ""; return "";
@@ -185,27 +137,31 @@ public class SomeCodes {
public static String MatToBase64(org.opencv.core.Mat mat){ public static String MatToBase64(org.opencv.core.Mat mat){
if (mat!=null){ if (mat!=null){
if (!mat.empty()){ if (mat.cols()>0 && mat.rows()>0){
MatOfByte mob = new MatOfByte(); MatOfByte mob = new MatOfByte();
Imgcodecs.imencode(".jpg", mat, mob); Imgcodecs.imencode(".jpg", mat, mob);
byte[] jpgdata = mob.toArray(); String base64 = base64encoder.encodeToString(mob.toArray());
mob.release(); mob.release();
mat.release(); return base64;
return base64encoder.encodeToString(jpgdata);
} }
} }
return ""; return "";
} }
// Function ini pakai opencv, bukan javacv, jadi perlu Loader.load(opencv_java.class) di awal // Function ini pakai opencv, bukan javacv, jadi perlu Loader.load(opencv_java.class) di awal
// lebih optimal untuk konversi frame ke base64 // lebih optimal untuk konversi frame ke base64
public static String FrameToBase64(Frame frame){ public static String FrameToBase64(Frame frame){
if (frame!=null){ if (frame!=null && frame.imageWidth>0 && frame.imageHeight>0){
org.opencv.core.Mat converted = CoreMatConverter.convert(frame); org.opencv.core.Mat converted = CoreMatConverter.convert(frame);
if (converted!=null){ if (converted!=null && converted.cols()>0 && converted.rows()>0){
//System.out.println("FrameToBase64 use converted Mat, cols: "+converted.cols()+", rows: "+converted.rows());
return MatToBase64(converted); return MatToBase64(converted);
} }
Mat xx = CoreMatConverter.convertToMat(frame);
if (xx!=null && xx.cols()>0 && xx.rows()>0){
//System.out.println("FrameToBase64 use xx Mat, cols: "+xx.cols()+", rows: "+xx.rows());
return MatToBase64(xx);
}
} }
return ""; return "";
} }
@@ -253,6 +209,7 @@ public class SomeCodes {
return config.getProperty(key, null); return config.getProperty(key, null);
} }
@Deprecated
public static Mat ResizeMat(Mat source, int width, int height){ public static Mat ResizeMat(Mat source, int width, int height){
Size sz = new Size(width, height); Size sz = new Size(width, height);
Mat dest = new Mat(); Mat dest = new Mat();
@@ -260,7 +217,6 @@ public class SomeCodes {
UMat src = new UMat(); UMat src = new UMat();
source.copyTo(src); source.copyTo(src);
UMat dst = new UMat(); UMat dst = new UMat();
opencv_imgproc.resize(src, dst, sz); opencv_imgproc.resize(src, dst, sz);
dst.copyTo(dest); dst.copyTo(dest);
} else { } else {
@@ -269,11 +225,6 @@ public class SomeCodes {
return dest; return dest;
} }
public static Frame ResizeFrame(Frame source, int width, int height){
Mat mat = matConverter.convertToMat(source);
Mat resized = ResizeMat(mat, width, height);
return matConverter.convert(resized);
}
/** /**
* check if an ip address is reachable * check if an ip address is reachable
@@ -298,97 +249,5 @@ public class SomeCodes {
} }
} }
public static Mat ResizeForYolo(Mat image) {
int targetSize = 640; // YOLOv8 input size (640x640)
// Get original dimensions
int originalWidth = image.cols();
int originalHeight = image.rows();
// Compute new dimensions while keeping aspect ratio
float scale = Math.min((float) targetSize / originalWidth, (float) targetSize / originalHeight);
int newWidth = Math.round(originalWidth * scale);
int newHeight = Math.round(originalHeight * scale);
// Resize while keeping aspect ratio
Mat resizedImage = new Mat();
opencv_imgproc.resize(image, resizedImage, new Size(newWidth, newHeight));
// Create a black 640x640 image and place the resized image in the center (padding)
Mat paddedImage = new Mat(targetSize, targetSize, image.type(), new Scalar(0, 0, 0,0));
int xOffset = (targetSize - newWidth) / 2;
int yOffset = (targetSize - newHeight) / 2;
Rect roi = new Rect(xOffset, yOffset, newWidth, newHeight);
Mat regionOfInterest = paddedImage.apply(roi);
resizedImage.copyTo(regionOfInterest);
// Convert to blob (normalize to [0,1])
//Mat blob = new Mat();
//opencv_dnn.blobFromImage(paddedImage, blob, 1.0 / 255.0, new Size(targetSize, targetSize), new Scalar(0, 0, 0), true, false);
return paddedImage;
}
public static Mat preprocessForYOLO(Mat image) {
int targetSize = 640; // YOLO input size
// Original size
int originalWidth = image.cols();
int originalHeight = image.rows();
// Scale to fit 640x640 while maintaining aspect ratio
float scale = Math.min((float) targetSize / originalWidth, (float) targetSize / originalHeight);
int newWidth = Math.round(originalWidth * scale);
int newHeight = Math.round(originalHeight * scale);
// Resize image
Mat resizedImage = new Mat();
opencv_imgproc.resize(image, resizedImage, new Size(newWidth, newHeight));
// Create black canvas (640x640)
Mat paddedImage = new Mat(targetSize, targetSize, image.type(), new Scalar());
// Center the resized image on the black background
int xOffset = (targetSize - newWidth) / 2;
int yOffset = (targetSize - newHeight) / 2;
Rect roi = new Rect(xOffset, yOffset, newWidth, newHeight);
resizedImage.copyTo(paddedImage.apply(roi));
// Convert to blob (normalize to [0,1])
Mat blob = new Mat();
opencv_dnn.blobFromImage(paddedImage);
return blob;
}
public static Mat resizeAndPad(Frame fr, int targetWidth, int targetHeight) {
Mat image = matConverter.convertToMat(fr);
int originalWidth = image.cols();
int originalHeight = image.rows();
// Scale factor for resizing while maintaining aspect ratio
float scale = Math.min((float) targetWidth / originalWidth, (float) targetHeight / originalHeight);
int newWidth = Math.round(originalWidth * scale);
int newHeight = Math.round(originalHeight * scale);
// Resize the image
Mat resizedImage = new Mat();
opencv_imgproc.resize(image, resizedImage, new Size(newWidth, newHeight));
// Create a new black (zero-filled) Mat of target size
Mat paddedImage = new Mat(targetHeight, targetWidth, image.type(), new Scalar());
// Calculate padding
int xOffset = (targetWidth - newWidth) / 2;
int yOffset = (targetHeight - newHeight) / 2;
// Place resized image into center of the black canvas
Rect roi = new Rect(xOffset, yOffset, newWidth, newHeight);
Mat regionOfInterest = paddedImage.apply(roi);
resizedImage.copyTo(regionOfInterest);
return paddedImage;
}
} }

View File

@@ -46,11 +46,11 @@ public class Main {
private static ExecutorService gpioExecutor = null; private static ExecutorService gpioExecutor = null;
private static I2C_BUS i2c_bus = null;
private static PCF8574 pcf8574 = null; private static PCF8574 pcf8574 = null;
// Application start from here // Application start from here
public static void main(String[] args) { public static void main(String[] args) {
System.setProperty("jna.debug_load", "false");
Runtime.getRuntime().addShutdownHook(new Thread(() -> { Runtime.getRuntime().addShutdownHook(new Thread(() -> {
if (audioPlayer!=null) audioPlayer.Unload(); if (audioPlayer!=null) audioPlayer.Unload();
if (webServer!=null) webServer.Stop(); if (webServer!=null) webServer.Stop();
@@ -82,6 +82,7 @@ public class Main {
System.out.println("Current Directory : "+currentDirectory); System.out.println("Current Directory : "+currentDirectory);
//init_gpio(); //init_gpio();
init_pcf8574(); init_pcf8574();
init_system_monitoring(); init_system_monitoring();
@@ -99,7 +100,7 @@ public class Main {
private static void init_pcf8574(){ private static void init_pcf8574(){
if (Platform.isLinux()){ if (Platform.isLinux()){
i2c_bus = new I2C_BUS(7); I2C_BUS i2c_bus = new I2C_BUS(7);
if (i2c_bus.Open_Bus()){ if (i2c_bus.Open_Bus()){
Logger.info("I2C Bus opened"); Logger.info("I2C Bus opened");
pcf8574 = new PCF8574(i2c_bus.getI2c_handle(), 0x27); pcf8574 = new PCF8574(i2c_bus.getI2c_handle(), 0x27);
@@ -123,6 +124,8 @@ public class Main {
} else System.out.println("PCF8574 not supported on this platform"); } else System.out.println("PCF8574 not supported on this platform");
} }
@Deprecated
@SuppressWarnings("unused")
private static void init_gpio(){ private static void init_gpio(){
if (Platform.isLinux()){ if (Platform.isLinux()){
if (GPIO.HaveGPIO()){ if (GPIO.HaveGPIO()){
@@ -562,16 +565,15 @@ public class Main {
// Live Streaming Related Commands // Live Streaming Related Commands
case "GET BASE64": case "GET BASE64":
if (rtspGrabber!=null){ if (rtspGrabber!=null){
switch (command.data){ return switch (command.data) {
case "HQ": case "YOLO" ->
return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastHQBase64(), rtspGrabber.HQStreamingStatus()); new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastHQBase64(), rtspGrabber.HQStreamingStatus());
case "LQ": case "LQ" ->
return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastLQBase64(), rtspGrabber.LQStreamingStatus()); new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastLQBase64(), rtspGrabber.LQStreamingStatus());
case "YOLO": case "HQ" ->
return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastYoloBase64(), rtspGrabber.HQStreamingStatus()); new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastYoloBase64(), rtspGrabber.HQStreamingStatus());
default: default -> new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
return new WebsocketReply("GET BASE64", "RTSP Grabber not initialized"); };
}
} else return new WebsocketReply("GET BASE64", "RTSP Grabber not initialized"); } else return new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
case "GET RESOLUTION": case "GET RESOLUTION":
if (vapixProtocol!=null){ if (vapixProtocol!=null){