YOLODetector is working (25/02/2025)
This commit is contained in:
BIN
onnx/yolov8m.onnx
Normal file
BIN
onnx/yolov8m.onnx
Normal file
Binary file not shown.
205
pom.xml
205
pom.xml
@@ -15,169 +15,62 @@
|
||||
</repository>
|
||||
</repositories>
|
||||
<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>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>javacv-platform</artifactId>
|
||||
<version>1.5.8</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>
|
||||
<artifactId>tensorrt</artifactId>
|
||||
<version>8.6-1.5.10</version>
|
||||
<classifier>linux-arm64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>javacpp</artifactId>
|
||||
<version>1.5.8</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>
|
||||
<artifactId>cuda</artifactId>
|
||||
<version>12.6-9.5-1.5.11</version>
|
||||
<classifier>linux-arm64</classifier>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.corundumstudio.socketio</groupId>
|
||||
<artifactId>netty-socketio</artifactId>
|
||||
@@ -186,7 +79,7 @@
|
||||
<dependency>
|
||||
<groupId>io.javalin</groupId>
|
||||
<artifactId>javalin</artifactId>
|
||||
<version> 6.3.0</version>
|
||||
<version> 6.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
@@ -201,7 +94,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.34</version>
|
||||
<version>1.18.36</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -9,7 +9,10 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
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;
|
||||
|
||||
public class GrabbingTask implements Runnable {
|
||||
@@ -98,30 +101,52 @@ public class GrabbingTask implements Runnable {
|
||||
isGrabbing.set(false);
|
||||
}
|
||||
|
||||
|
||||
private void processFrame(Frame fr){
|
||||
if (fr!=null){
|
||||
updateHQFrame(fr);
|
||||
updateHQBase64(SomeCodes.FrameToBase64(fr));
|
||||
Frame resized = SomeCodes.ResizeFrame(fr, lowquality_width, lowquality_height);
|
||||
updateLQFrame(resized);
|
||||
updateLQBase64(SomeCodes.FrameToBase64(resized));
|
||||
} else updateMessage("processFrame have null frame");
|
||||
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);
|
||||
updateHQBase64(SomeCodes.MatToBase64(mat));
|
||||
Size lowsize = new Size(lowquality_width, lowquality_height);
|
||||
Mat resized = new Mat();
|
||||
Imgproc.resize(mat, resized, lowsize);
|
||||
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());
|
||||
}
|
||||
|
||||
} else {
|
||||
System.out.println("processFrame have null frame");
|
||||
updateMessage("processFrame have null frame");
|
||||
}
|
||||
}
|
||||
|
||||
//TODO masih trouble di sini
|
||||
private void DetectYolo(Frame frame){
|
||||
if (frame!=null){
|
||||
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{
|
||||
Mat processed = yolo.Detect(frame);
|
||||
Frame yoloFrame = SomeCodes.CoreMatConverter.convert(processed);
|
||||
Mat[] processed = yolo.Detect(mat);
|
||||
Mat yolomat = yolo.Process(mat, processed[0], processed[1]);
|
||||
Frame yoloFrame = SomeCodes.CoreMatConverter.convert(yolomat);
|
||||
updateYoloFrame(yoloFrame);
|
||||
updateYoloBase64(SomeCodes.FrameToBase64(yoloFrame));
|
||||
updateYoloBase64(SomeCodes.MatToBase64(yolomat));
|
||||
|
||||
} catch (Exception e){
|
||||
System.out.println("error processing YOLO, Message : "+e.getMessage());
|
||||
updateYoloFrame(null);
|
||||
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 % skippedframes == 0) {
|
||||
processFrame(frame);
|
||||
DetectYolo(frame);
|
||||
}
|
||||
} catch (Exception e){
|
||||
Logger.error("Error grabbing frame: "+e.getMessage());
|
||||
|
||||
@@ -2,23 +2,15 @@ package Camera;
|
||||
|
||||
import Other.SomeCodes;
|
||||
import lombok.Getter;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.bytedeco.opencv.global.opencv_dnn;
|
||||
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.core.*;
|
||||
import org.opencv.dnn.Dnn;
|
||||
import org.opencv.dnn.Net;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -28,11 +20,9 @@ public class YoloDetector {
|
||||
private Net net;
|
||||
private @Getter boolean NetLoaded;
|
||||
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
|
||||
private final float confidence_threshold = 0.5f;
|
||||
private final float confidence_threshold = 0.4f;
|
||||
// Non-maximum suppression threshold
|
||||
private final float nms_threshold = 0.4f;
|
||||
|
||||
@@ -44,18 +34,21 @@ public class YoloDetector {
|
||||
String namesfile = SomeCodes.ExtractResource("/coco.names", SomeCodes.currentDirectory);
|
||||
if (SomeCodes.ValidFile(onnxfile)){
|
||||
if (SomeCodes.ValidFile(namesfile)){
|
||||
net = opencv_dnn.readNetFromONNX(onnxfile);
|
||||
net = Dnn.readNetFromONNX(onnxfile);
|
||||
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
|
||||
net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
|
||||
|
||||
|
||||
classes = new ArrayList<>();
|
||||
try(BufferedReader br = new BufferedReader(new FileReader(namesfile))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
classes.add(line);
|
||||
if (namesfile!=null){
|
||||
try(BufferedReader br = new BufferedReader(new FileReader(namesfile))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
classes.add(line);
|
||||
}
|
||||
} catch (Exception e){
|
||||
System.out.println("Error: reading names file");
|
||||
}
|
||||
} catch (Exception e){
|
||||
System.out.println("Error: reading names file");
|
||||
}
|
||||
|
||||
if (!net.empty()){
|
||||
@@ -67,101 +60,145 @@ public class YoloDetector {
|
||||
} else System.out.println("Error: onnx file not found");
|
||||
}
|
||||
|
||||
public Mat Detect(Frame frame){
|
||||
Mat mat = SomeCodes.CoreMatConverter.convertToMat(frame);
|
||||
return Detect(mat);
|
||||
|
||||
}
|
||||
|
||||
public Mat Detect(Mat frame){
|
||||
public Mat[] Detect(Mat frame){
|
||||
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);
|
||||
|
||||
Mat detections = net.forward();
|
||||
return detections;
|
||||
Mat predict = net.forward();
|
||||
Mat mask = predict.reshape(0,1).reshape(0, predict.size(1));
|
||||
|
||||
return new Mat[]{predict,mask};
|
||||
} else {
|
||||
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 cols = output.cols();
|
||||
List<Rect> boxes = new ArrayList<>();
|
||||
List<Float> confidences = new ArrayList<>();
|
||||
List<Integer> classIds = new ArrayList<>();
|
||||
|
||||
for(int i=0;i<rows;i++){
|
||||
for (int i = 0; i < rows; i++){
|
||||
Mat row = output.row(i);
|
||||
float confidence = row.getFloatBuffer().get(4);
|
||||
if (confidence >= confidence_threshold){
|
||||
FloatBuffer data = row.getFloatBuffer();
|
||||
int classid = 0;
|
||||
float maxscore = 0;
|
||||
for(int j = 5; j< cols; j++){
|
||||
float score = data.get(j);
|
||||
if (score > maxscore){
|
||||
maxscore = score;
|
||||
classid = j-5;
|
||||
}
|
||||
}
|
||||
if (maxscore>= confidence_threshold){
|
||||
int x = (int)(data.get(0) * frame.cols());
|
||||
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);
|
||||
}
|
||||
Mat scores = row.colRange(5, cols);
|
||||
Core.MinMaxLocResult mm = Core.minMaxLoc(scores);
|
||||
float confidence = (float)mm.maxVal;
|
||||
Point classIdPoint = mm.maxLoc;
|
||||
if (confidence>confidence_threshold){
|
||||
int centerX = (int)(row.get(0, 0)[0] * frame.cols());
|
||||
int centerY = (int)(row.get(0, 1)[0] * frame.rows());
|
||||
int width = (int)(row.get(0, 2)[0] * frame.cols());
|
||||
int height = (int)(row.get(0, 3)[0] * frame.rows());
|
||||
int left = centerX - width / 2;
|
||||
int top = centerY - height / 2;
|
||||
boxes.add(new Rect(left, top, width, height));
|
||||
confidences.add(confidence);
|
||||
classIds.add((int)classIdPoint.x);
|
||||
}
|
||||
}
|
||||
|
||||
Rect[] rr = new Rect[boxes.size()];
|
||||
for(int ii = 0; ii<boxes.size(); ii++){
|
||||
rr[ii] = boxes.get(ii);
|
||||
}
|
||||
MatOfRect2d rects = new MatOfRect2d(ListToRectArray(boxes));
|
||||
MatOfRect2d rects = new MatOfRect2d(ToRect2D(boxes));
|
||||
MatOfFloat conf = new MatOfFloat(ToFloatArray(confidences));
|
||||
MatOfInt ids = new MatOfInt();
|
||||
|
||||
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()){
|
||||
Dnn.NMSBoxes(rects, conf, confidence_threshold, nms_threshold, indices);
|
||||
}
|
||||
Rect box = boxes.get(idx);
|
||||
int classId = classIds.get(idx);
|
||||
float confidence = confidences.get(idx);
|
||||
String label = classes.get(classId);
|
||||
System.out.println("Detect ["+idx+"] ClassID: "+classId+" Label: "+label+" Confidence: "+confidence);
|
||||
|
||||
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);
|
||||
opencv_imgproc.rectangle(frame, box, Scalar.RED);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
private org.opencv.core.Rect2d[] ListToRectArray(List<Rect> list){
|
||||
org.opencv.core.Rect2d[] arr = new org.opencv.core.Rect2d[list.size()];
|
||||
for(int i=0;i<list.size();i++){
|
||||
Rect r = list.get(i);
|
||||
arr[i] = new org.opencv.core.Rect2d(r.x(), r.y(), r.width(), r.height());
|
||||
private Rect2d[] ToRect2D(List<Rect> list){
|
||||
if (list!=null && list.size()>0){
|
||||
Rect2d array[] = new Rect2d[list.size()];
|
||||
for (int i = 0; i < list.size(); i++){
|
||||
Rect r = list.get(i);
|
||||
array[i] = new Rect2d(r.x, r.y, r.width, r.height);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
return arr;
|
||||
return new Rect2d[0];
|
||||
}
|
||||
|
||||
private float[] ListToArray(List<Float> list){
|
||||
float[] arr = new float[list.size()];
|
||||
for(int i=0;i<list.size();i++){
|
||||
arr[i] = list.get(i);
|
||||
private float[] ToFloatArray(List<Float> list){
|
||||
if (list!=null && list.size()>0){
|
||||
float array[] = new float[list.size()];
|
||||
for (int i = 0; i < list.size(); i++){
|
||||
array[i] = list.get(i);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
return arr;
|
||||
return new float[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@ package Other;
|
||||
import com.google.gson.Gson;
|
||||
import org.bytedeco.javacpp.Loader;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.bytedeco.javacv.Java2DFrameConverter;
|
||||
import org.bytedeco.javacv.OpenCVFrameConverter;
|
||||
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.opencv_core.*;
|
||||
import org.bytedeco.opencv.opencv_java;
|
||||
@@ -16,16 +15,11 @@ import org.opencv.imgcodecs.Imgcodecs;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.file.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Base64;
|
||||
import java.util.Properties;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class SomeCodes {
|
||||
static{
|
||||
Loader.load(opencv_java.class);
|
||||
@@ -33,12 +27,8 @@ public class SomeCodes {
|
||||
|
||||
public final static String currentDirectory = System.getProperty("user.dir");
|
||||
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 Java2DFrameConverter frameConverter = new Java2DFrameConverter();
|
||||
public static final Path logsPath = Path.of(currentDirectory, "logs");
|
||||
public static final boolean haveOpenCL = opencv_core.haveOpenCL();
|
||||
public static boolean useOpenCL;
|
||||
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 GB_threshold = 1024.0 * 1024.0 * 1024.0;
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static String[] GetAudioFiles(){
|
||||
try{
|
||||
return Files.list(audioPath).map(f -> f.getFileName().toString()).toArray(String[]::new);
|
||||
@@ -57,10 +48,6 @@ public class SomeCodes {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
public static String LocalDateTimeToString(LocalDateTime x){
|
||||
return x.format(dtf);
|
||||
}
|
||||
|
||||
public static String ExtractResource(String filename, String targetdirectory){
|
||||
try {
|
||||
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){
|
||||
if (ValidString(filename)){
|
||||
@@ -143,41 +124,12 @@ public class SomeCodes {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean ValidIPV4(String ipaddress){
|
||||
if (ValidString(ipaddress)){
|
||||
try{
|
||||
InetAddress inet = InetAddress.getByName(ipaddress);
|
||||
if (inet instanceof Inet4Address){
|
||||
if (inet.getHostAddress().equals(ipaddress)){
|
||||
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();
|
||||
public static String MatToBase64(Mat mat){
|
||||
if (mat!=null){
|
||||
if (mat.cols()>0 && mat.rows()>0){
|
||||
byte[] mob = new byte[mat.cols()*mat.rows()*mat.channels()];
|
||||
opencv_imgcodecs.imencode(".jpg", mat, mob);
|
||||
return base64encoder.encodeToString(mob);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
@@ -185,27 +137,31 @@ public class SomeCodes {
|
||||
|
||||
public static String MatToBase64(org.opencv.core.Mat mat){
|
||||
if (mat!=null){
|
||||
if (!mat.empty()){
|
||||
if (mat.cols()>0 && mat.rows()>0){
|
||||
MatOfByte mob = new MatOfByte();
|
||||
Imgcodecs.imencode(".jpg", mat, mob);
|
||||
byte[] jpgdata = mob.toArray();
|
||||
String base64 = base64encoder.encodeToString(mob.toArray());
|
||||
mob.release();
|
||||
mat.release();
|
||||
return base64encoder.encodeToString(jpgdata);
|
||||
return base64;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
// Function ini pakai opencv, bukan javacv, jadi perlu Loader.load(opencv_java.class) di awal
|
||||
// lebih optimal untuk konversi frame ke base64
|
||||
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);
|
||||
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);
|
||||
}
|
||||
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 "";
|
||||
}
|
||||
@@ -253,6 +209,7 @@ public class SomeCodes {
|
||||
return config.getProperty(key, null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Mat ResizeMat(Mat source, int width, int height){
|
||||
Size sz = new Size(width, height);
|
||||
Mat dest = new Mat();
|
||||
@@ -260,7 +217,6 @@ public class SomeCodes {
|
||||
UMat src = new UMat();
|
||||
source.copyTo(src);
|
||||
UMat dst = new UMat();
|
||||
|
||||
opencv_imgproc.resize(src, dst, sz);
|
||||
dst.copyTo(dest);
|
||||
} else {
|
||||
@@ -269,11 +225,6 @@ public class SomeCodes {
|
||||
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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,11 +46,11 @@ public class Main {
|
||||
|
||||
private static ExecutorService gpioExecutor = null;
|
||||
|
||||
private static I2C_BUS i2c_bus = null;
|
||||
private static PCF8574 pcf8574 = null;
|
||||
|
||||
// Application start from here
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("jna.debug_load", "false");
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
if (audioPlayer!=null) audioPlayer.Unload();
|
||||
if (webServer!=null) webServer.Stop();
|
||||
@@ -82,6 +82,7 @@ public class Main {
|
||||
|
||||
System.out.println("Current Directory : "+currentDirectory);
|
||||
|
||||
|
||||
//init_gpio();
|
||||
init_pcf8574();
|
||||
init_system_monitoring();
|
||||
@@ -99,7 +100,7 @@ public class Main {
|
||||
|
||||
private static void init_pcf8574(){
|
||||
if (Platform.isLinux()){
|
||||
i2c_bus = new I2C_BUS(7);
|
||||
I2C_BUS i2c_bus = new I2C_BUS(7);
|
||||
if (i2c_bus.Open_Bus()){
|
||||
Logger.info("I2C Bus opened");
|
||||
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");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SuppressWarnings("unused")
|
||||
private static void init_gpio(){
|
||||
if (Platform.isLinux()){
|
||||
if (GPIO.HaveGPIO()){
|
||||
@@ -562,16 +565,15 @@ public class Main {
|
||||
// Live Streaming Related Commands
|
||||
case "GET BASE64":
|
||||
if (rtspGrabber!=null){
|
||||
switch (command.data){
|
||||
case "HQ":
|
||||
return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastHQBase64(), rtspGrabber.HQStreamingStatus());
|
||||
case "LQ":
|
||||
return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastLQBase64(), rtspGrabber.LQStreamingStatus());
|
||||
case "YOLO":
|
||||
return new WebsocketReply("GET BASE64", "data:image/jpeg;base64,"+ rtspGrabber.getLastYoloBase64(), rtspGrabber.HQStreamingStatus());
|
||||
default:
|
||||
return new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
|
||||
}
|
||||
return switch (command.data) {
|
||||
case "YOLO" ->
|
||||
new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastHQBase64(), rtspGrabber.HQStreamingStatus());
|
||||
case "LQ" ->
|
||||
new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastLQBase64(), rtspGrabber.LQStreamingStatus());
|
||||
case "HQ" ->
|
||||
new WebsocketReply("GET BASE64", "data:image/jpeg;base64," + rtspGrabber.getLastYoloBase64(), rtspGrabber.HQStreamingStatus());
|
||||
default -> new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
|
||||
};
|
||||
} else return new WebsocketReply("GET BASE64", "RTSP Grabber not initialized");
|
||||
case "GET RESOLUTION":
|
||||
if (vapixProtocol!=null){
|
||||
|
||||
Reference in New Issue
Block a user