Change SBC to Jetson Orin

This commit is contained in:
2025-02-25 07:35:38 +07:00
parent 21e8ab1e82
commit ce5c8d5946
16 changed files with 1057 additions and 80 deletions

View File

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

View File

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

View File

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

View 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;
}
}