YOLODetector is working (25/02/2025)
This commit is contained in:
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user