Change SBC to Jetson Orin
This commit is contained in:
@@ -9,6 +9,7 @@ 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.tinylog.Logger;
|
||||
|
||||
public class GrabbingTask implements Runnable {
|
||||
@@ -23,6 +24,8 @@ public class GrabbingTask implements Runnable {
|
||||
@Setter private Consumer<Frame> onLQFrameUpdate;
|
||||
@Setter private Consumer<String> onHQBase64Update;
|
||||
@Setter private Consumer<String> onLQBase64Update;
|
||||
@Setter private Consumer<Frame> onYoloUpdate;
|
||||
@Setter private Consumer<String> onYoloBase64Update;
|
||||
|
||||
// status of capture fps
|
||||
@Getter private int CaptureFPS = 0;
|
||||
@@ -33,6 +36,8 @@ public class GrabbingTask implements Runnable {
|
||||
// for FPS calculation
|
||||
private int intendedFps = 10;
|
||||
|
||||
private final YoloDetector yolo;
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private void updateMessage(String message) {
|
||||
if (onMessageUpdate != null) {
|
||||
@@ -40,9 +45,17 @@ public class GrabbingTask implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateYoloBase64(String base64) {
|
||||
if (onYoloBase64Update != null) {
|
||||
onYoloBase64Update.accept(base64);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void updateYoloFrame(Frame frame) {
|
||||
if (onYoloUpdate != null) {
|
||||
onYoloUpdate.accept(frame);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateHQBase64(String base64) {
|
||||
if (onHQBase64Update != null) {
|
||||
@@ -77,6 +90,7 @@ public class GrabbingTask implements Runnable {
|
||||
this.isGrabbing = isGrabbing;
|
||||
this.grabber = grabber;
|
||||
if (fps>0) intendedFps = fps;
|
||||
yolo = new YoloDetector();
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +108,23 @@ public class GrabbingTask implements Runnable {
|
||||
} else updateMessage("processFrame have null frame");
|
||||
}
|
||||
|
||||
//TODO masih trouble di sini
|
||||
private void DetectYolo(Frame frame){
|
||||
if (frame!=null){
|
||||
try{
|
||||
Mat processed = yolo.Detect(frame);
|
||||
Frame yoloFrame = SomeCodes.CoreMatConverter.convert(processed);
|
||||
updateYoloFrame(yoloFrame);
|
||||
updateYoloBase64(SomeCodes.FrameToBase64(yoloFrame));
|
||||
} catch (Exception e){
|
||||
System.out.println("error processing YOLO, Message : "+e.getMessage());
|
||||
updateYoloFrame(null);
|
||||
updateYoloBase64("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void flush_grabber(){
|
||||
try {
|
||||
if (grabber!=null) grabber.flush();
|
||||
@@ -117,9 +148,13 @@ public class GrabbingTask implements Runnable {
|
||||
Thread.yield();
|
||||
Frame frame = grabber.grab();
|
||||
if (framecount<Integer.MAX_VALUE) framecount++; else framecount = 0;
|
||||
if (framecount % skippedframes == 0) processFrame(frame);
|
||||
if (framecount % skippedframes == 0) {
|
||||
processFrame(frame);
|
||||
DetectYolo(frame);
|
||||
}
|
||||
} catch (Exception e){
|
||||
Logger.error("Error grabbing frame: "+e.getMessage());
|
||||
|
||||
}
|
||||
|
||||
long elapsed = System.currentTimeMillis() - starttick;
|
||||
|
||||
@@ -70,10 +70,11 @@ public class PanTiltController {
|
||||
command[0] = (byte) 0xFF; // add synchronization byte
|
||||
if (isOpen()) {
|
||||
Main.Max485Direction(true);
|
||||
serialPort.writeBytes(command, command.length);
|
||||
int written = serialPort.writeBytes(command, command.length);
|
||||
Main.Max485Direction(false);
|
||||
Main.Blink_LedPanTilt();
|
||||
}
|
||||
System.out.println("Stop Movement written : "+written);
|
||||
} else System.out.println("Stop Movement failed, serial port not open");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,10 +90,11 @@ public class PanTiltController {
|
||||
command[0] = (byte) 0xFF; // add synchronization byte
|
||||
if (isOpen()) {
|
||||
Main.Max485Direction(true);
|
||||
serialPort.writeBytes(command, command.length);
|
||||
int written = serialPort.writeBytes(command, command.length);
|
||||
Main.Max485Direction(false);
|
||||
Main.Blink_LedPanTilt();
|
||||
}
|
||||
System.out.println("Pan Left written : "+written);
|
||||
} else System.out.println("Pan Left failed, serial port not open");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,10 +110,11 @@ public class PanTiltController {
|
||||
command[0] = (byte) 0xFF; // add synchronization byte
|
||||
if (isOpen()) {
|
||||
Main.Max485Direction(true);
|
||||
serialPort.writeBytes(command, command.length);
|
||||
int written = serialPort.writeBytes(command, command.length);
|
||||
Main.Max485Direction(false);
|
||||
Main.Blink_LedPanTilt();
|
||||
}
|
||||
System.out.println("Pan Right written : "+written);
|
||||
} else System.out.println("Pan Right failed, serial port not open");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,10 +130,11 @@ public class PanTiltController {
|
||||
command[0] = (byte) 0xFF; // add synchronization byte
|
||||
if (isOpen()) {
|
||||
Main.Max485Direction(true);
|
||||
serialPort.writeBytes(command, command.length);
|
||||
int written = serialPort.writeBytes(command, command.length);
|
||||
Main.Max485Direction(false);
|
||||
Main.Blink_LedPanTilt();
|
||||
}
|
||||
System.out.println("Tilt Up written : "+written);
|
||||
} else System.out.println("Tilt Up failed, serial port not open");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,6 +148,23 @@ public class PanTiltController {
|
||||
byte[] command = new byte[]{0, cameraid, 0, 16, speed, 0, 0};
|
||||
command[6] = Checksum(command); // add checksum
|
||||
command[0] = (byte) 0xFF; // add synchronization byte
|
||||
if (isOpen()) {
|
||||
Main.Max485Direction(true);
|
||||
int written = serialPort.writeBytes(command, command.length);
|
||||
Main.Max485Direction(false);
|
||||
Main.Blink_LedPanTilt();
|
||||
System.out.println("Tilt Down written : "+written);
|
||||
} else System.out.println("Tilt Down failed, serial port not open");
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to Preset
|
||||
* @param preset preset number
|
||||
*/
|
||||
public void GoToPreset(byte preset){
|
||||
byte[] command = new byte[]{0, cameraid, 0, 15, preset, 0, 0};
|
||||
command[6] = Checksum(command); // add checksum
|
||||
command[0] = (byte) 0xFF; // add synchronization byte
|
||||
if (isOpen()) {
|
||||
Main.Max485Direction(true);
|
||||
serialPort.writeBytes(command, command.length);
|
||||
|
||||
@@ -3,6 +3,7 @@ import lombok.Getter;
|
||||
import org.bytedeco.ffmpeg.global.avutil;
|
||||
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.bytedeco.opencv.global.opencv_core;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
@@ -17,8 +18,10 @@ public class RtspGrabber {
|
||||
private final AtomicBoolean isGrabbing = new AtomicBoolean(false);
|
||||
private Frame lastHQFrame = null;
|
||||
private Frame lastLQFrame = null;
|
||||
private Frame lastYoloFrame = null;
|
||||
private String lastHQBase64 = null;
|
||||
private String lastLQBase64 = null;
|
||||
private String lastYoloBase64 = null;
|
||||
private @Getter int HQWidth = 0;
|
||||
private @Getter int HQHeight = 0;
|
||||
private @Getter int LQWidth = 0;
|
||||
@@ -26,6 +29,13 @@ public class RtspGrabber {
|
||||
private GrabbingTask grabbingTask;
|
||||
|
||||
public RtspGrabber(String ip, String path) {
|
||||
int cudacount = opencv_core.getCudaEnabledDeviceCount();
|
||||
if (cudacount>0){
|
||||
Logger.info("CUDA enabled devices found: " + cudacount);
|
||||
opencv_core.printCudaDeviceInfo(0);
|
||||
} else {
|
||||
Logger.info("No CUDA enabled devices found");
|
||||
}
|
||||
this.rtspUrl = "rtsp://" + ip + path;
|
||||
Logger.info("RtspGrabber created with url: " + rtspUrl);
|
||||
}
|
||||
@@ -62,6 +72,22 @@ public class RtspGrabber {
|
||||
return lastLQBase64;
|
||||
}
|
||||
|
||||
private synchronized void setLastYoloBase64(String base64){
|
||||
lastYoloBase64 = base64;
|
||||
}
|
||||
|
||||
public synchronized String getLastYoloBase64(){
|
||||
return lastYoloBase64;
|
||||
}
|
||||
|
||||
private synchronized void setLastYoloFrame(Frame frame){
|
||||
lastYoloFrame = frame;
|
||||
}
|
||||
|
||||
public synchronized Frame getLastYoloFrame(){
|
||||
return lastYoloFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start grabbing frames from rtsp
|
||||
* @param useTcp Use tcp instead of udp
|
||||
@@ -143,6 +169,8 @@ public class RtspGrabber {
|
||||
});
|
||||
tt.setOnHQBase64Update(this::setLastHQBase64);
|
||||
tt.setOnLQBase64Update(this::setLastLQBase64);
|
||||
tt.setOnYoloUpdate(this::setLastYoloFrame);
|
||||
tt.setOnYoloBase64Update(this::setLastYoloBase64);
|
||||
return tt;
|
||||
}
|
||||
}
|
||||
|
||||
167
src/main/java/Camera/YoloDetector.java
Normal file
167
src/main/java/Camera/YoloDetector.java
Normal file
@@ -0,0 +1,167 @@
|
||||
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.dnn.Dnn;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.bytedeco.opencv.global.opencv_core.CV_32F;
|
||||
|
||||
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;
|
||||
// Non-maximum suppression threshold
|
||||
private final float nms_threshold = 0.4f;
|
||||
|
||||
public YoloDetector() {
|
||||
NetLoaded = false;
|
||||
net = null;
|
||||
classes = null;
|
||||
String onnxfile = SomeCodes.ExtractResource("/yolov8n.onnx", SomeCodes.currentDirectory);
|
||||
String namesfile = SomeCodes.ExtractResource("/coco.names", SomeCodes.currentDirectory);
|
||||
if (SomeCodes.ValidFile(onnxfile)){
|
||||
if (SomeCodes.ValidFile(namesfile)){
|
||||
net = opencv_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);
|
||||
}
|
||||
} catch (Exception e){
|
||||
System.out.println("Error: reading names file");
|
||||
}
|
||||
|
||||
if (!net.empty()){
|
||||
if (!classes.isEmpty()){
|
||||
NetLoaded = true;
|
||||
} else System.out.println("Error: names file is empty");
|
||||
} else System.out.println("Error: net is empty");
|
||||
} else System.out.println("Error: names file not found");
|
||||
} 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){
|
||||
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);
|
||||
net.setInput(blob);
|
||||
|
||||
Mat detections = net.forward();
|
||||
return detections;
|
||||
} else {
|
||||
System.out.println("Error: Net not loaded");
|
||||
return new Mat();
|
||||
}
|
||||
}
|
||||
|
||||
private 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++){
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
MatOfFloat conf = new MatOfFloat(ListToArray(confidences));
|
||||
|
||||
MatOfInt indices = new MatOfInt();
|
||||
|
||||
if (!boxes.isEmpty()){
|
||||
Dnn.NMSBoxes(rects, conf, confidence_threshold, nms_threshold, indices);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user