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

View File

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

View File

@@ -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];
}
}