diff --git a/YOLO/yolov8n.onnx b/YOLO/yolov8n.onnx deleted file mode 100644 index 9ede1eb..0000000 Binary files a/YOLO/yolov8n.onnx and /dev/null differ diff --git a/YOLO/yolov8n.pt b/YOLO/yolov8n.pt deleted file mode 100644 index 0db4ca4..0000000 Binary files a/YOLO/yolov8n.pt and /dev/null differ diff --git a/src/main/java/id/co/gtc/cctvwithcuda/MainController.java b/src/main/java/id/co/gtc/cctvwithcuda/MainController.java index 9ead3a7..58ec71b 100644 --- a/src/main/java/id/co/gtc/cctvwithcuda/MainController.java +++ b/src/main/java/id/co/gtc/cctvwithcuda/MainController.java @@ -7,6 +7,9 @@ import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.StackPane; +import org.opencv.core.Rect; +import org.opencv.core.Scalar; +import org.opencv.imgproc.Imgproc; import org.opencv.osgi.OpenCVNativeLoader; import java.time.LocalDateTime; @@ -106,17 +109,50 @@ public class MainController { }, (frame) -> { yoloDetector.Detect(frame, (detection)->{ - String dimension = "Dimension : "+detection.dims(); - String imagesize = "Image Size : "+detection.size(0); - String imagechannels = "Image Channels : "+detection.size(1); - String imageheight = "Image Height : "+detection.size(2); - String imagewidth = "Image Width : "+detection.size(3); - System.out.println("Detection : "); - System.out.println(dimension); - System.out.println(imagesize); - System.out.println(imagechannels); - System.out.println(imageheight); - System.out.println(imagewidth); + + if (detection!=null && !detection.empty()){ + for (int i=0; i maxScore) { + maxScore = score; + classId = j - 5; + } + } + + System.out.println("MaxScore: " + maxScore + ", ClassId: " + classId); + if (classId < 0) continue; + if (classId >= 80) continue; + String className = yoloDetector.getClassName(classId); + if (className == null) continue; + System.out.println("ClassName: " + className + ", Confidence: " + confidence); + + float cx = row[0] * frame.cols(); + float cy = row[1] * frame.rows(); + float w = row[2] * frame.cols(); + float h = row[3] * frame.rows(); + + int x = (int)(cx - w / 2); + int y = (int)(cy - h / 2); + + System.out.println("x: " + x + ", y: " + y + ", w: " + w + ", h: " + h); + + + Rect rect = new Rect(x, y, (int)w, (int)h); + Scalar color = new Scalar(0, 255, 0); + Imgproc.rectangle(frame, rect, color, 2); + } + } + + + }); Image img = SomeCodes.MatToImage(frame); if (img!=null) { diff --git a/src/main/java/id/co/gtc/cctvwithcuda/SomeCodes.java b/src/main/java/id/co/gtc/cctvwithcuda/SomeCodes.java index 9cb0b00..1c31550 100644 --- a/src/main/java/id/co/gtc/cctvwithcuda/SomeCodes.java +++ b/src/main/java/id/co/gtc/cctvwithcuda/SomeCodes.java @@ -6,16 +6,20 @@ import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import org.opencv.core.Mat; -import org.opencv.core.MatOfByte; +import org.opencv.core.*; import org.opencv.imgcodecs.Imgcodecs; +import org.opencv.imgproc.Imgproc; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; public class SomeCodes { public final static String currentDirectory = System.getProperty("user.dir"); @@ -98,4 +102,50 @@ public class SomeCodes { return null; } + public static Mat Convert_BGRA_To_BGR(Mat src){ + if (src.channels() == 4){ + Mat dst = new Mat(); + Imgproc.cvtColor(src, dst, Imgproc.COLOR_BGRA2BGR); + return dst; + } else return src; + + } + + public static boolean IsSquared(Mat src){ + if (src != null && !src.empty()){ + int width = src.cols(); + int height = src.rows(); + return width == height; + } + return false; + } + + public static Mat FormatToSquare(Mat src){ + if (src != null && !src.empty()){ + int width = src.cols(); + int height = src.rows(); + int size = Math.max(width, height); + + int right = size - width; + int bottom = size - height; + + Scalar paddingColor = new Scalar(0, 0, 0); // Black background + + Mat dst = new Mat(); + Core.copyMakeBorder(src, dst, 0, bottom, 0, right, Core.BORDER_CONSTANT, paddingColor); + return dst; + } + return null; + } + + public static List ReadLines(String filename){ + try { + return Files.readAllLines(Paths.get(currentDirectory,filename)); + } catch (IOException e) { + System.out.println("Error reading file: " + filename + ", Message: " + e.getMessage()); + } + return new ArrayList<>(); + } + + } diff --git a/src/main/java/id/co/gtc/cctvwithcuda/YoloDetector.java b/src/main/java/id/co/gtc/cctvwithcuda/YoloDetector.java index 4d600be..825fb8e 100644 --- a/src/main/java/id/co/gtc/cctvwithcuda/YoloDetector.java +++ b/src/main/java/id/co/gtc/cctvwithcuda/YoloDetector.java @@ -1,18 +1,21 @@ package id.co.gtc.cctvwithcuda; +import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.dnn.Dnn; import org.opencv.dnn.Net; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; import java.util.function.Consumer; @SuppressWarnings("FieldCanBeLocal") public class YoloDetector { - - + private List classNames = null; private Net net = null; private boolean loaded = false; @@ -20,6 +23,14 @@ public class YoloDetector { * Create a YoloDetector object */ public YoloDetector(String yolofile){ + SomeCodes.ExtractResource("/coco.names"); + classNames = SomeCodes.ReadLines("coco.names"); + if (!classNames.isEmpty()){ + System.out.println("YoloDetector class names loaded from coco.names, length: " + classNames.size()); + } else { + System.out.println("YoloDetector class names not loaded from coco.names"); + } + if (yolofile!=null && !yolofile.isEmpty()){ if (!yolofile.startsWith("/")) yolofile = "/" + yolofile; String yolofilepath = SomeCodes.ExtractResource(yolofile); @@ -34,15 +45,26 @@ public class YoloDetector { } } } - SomeCodes.ExtractResource("/coco.names"); + System.out.println("YoloDetector failed to load from " + yolofile); } + public String getClassName(int index){ + if (classNames!=null && index>=0 && index onDetect){ if (loaded){ + //System.out.println("frame width: " + frame.width() + ", height: " + frame.height()+" channels: " + frame.channels()); + if (frame.channels()==4) frame = SomeCodes.Convert_BGRA_To_BGR(frame); + if (!SomeCodes.IsSquared(frame)) frame = SomeCodes.FormatToSquare(frame); + //System.out.println("new frame width: " + frame.width() + ", height: " + frame.height()+" channels: " + frame.channels()); Mat blob = Dnn.blobFromImage(frame, scale, blobSize, blobScalar, swapRGB, crop); net.setInput(blob); Mat detections = net.forward(); - if (detections!=null && !detections.empty()){ + if (transposed){ + // Fix shape from [1, 84, 8400] → [8400, 84] + Mat reshaped = detections.reshape(1, 84); // [84 x 8400] + Mat transposed = new Mat(); + Core.transpose(reshaped, transposed); // [8400 x 84] + if (!transposed.empty()){ + if (onDetect!=null) onDetect.accept(transposed); + } + reshaped.release(); + } else { if (onDetect!=null) onDetect.accept(detections); } + } } + + + + }