experimental #1

Merged
rattatwinko merged 4 commits from experimental into master 2025-05-24 17:29:25 +00:00
Showing only changes of commit 201d8013be - Show all commits

View File

@@ -15,6 +15,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.*; import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileNameExtensionFilter;
import org.opencv.core.*; import org.opencv.core.*;
import org.opencv.core.Point; import org.opencv.core.Point;
import org.opencv.dnn.Dnn; import org.opencv.dnn.Dnn;
@@ -47,7 +48,7 @@ public class CameraApp extends JFrame {
private List<String> outputLayers; private List<String> outputLayers;
private boolean detectionEnabled = true; private boolean detectionEnabled = true;
private boolean modelLoaded = false; private boolean modelLoaded = false;
private int frameCount = 0; private final int frameCount = 0;
private long lastFpsUpdate = System.currentTimeMillis(); private long lastFpsUpdate = System.currentTimeMillis();
public CameraApp() { public CameraApp() {
@@ -245,6 +246,12 @@ public class CameraApp extends JFrame {
} }
private void loadYolo() { private void loadYolo() {
// Try to load from resources first
if (loadYoloFromResources()) {
return;
}
// Fall back to downloading if not found in resources
String weightsUrl = "https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.weights"; String weightsUrl = "https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.weights";
String configUrl = "https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4-tiny.cfg"; String configUrl = "https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4-tiny.cfg";
String classesUrl = "https://raw.githubusercontent.com/AlexeyAB/darknet/master/data/coco.names"; String classesUrl = "https://raw.githubusercontent.com/AlexeyAB/darknet/master/data/coco.names";
@@ -253,47 +260,40 @@ public class CameraApp extends JFrame {
String configPath = "./yolov4-tiny.cfg"; String configPath = "./yolov4-tiny.cfg";
String classesPath = "./coco.names"; String classesPath = "./coco.names";
boolean filesValid = true; // Rest of your download logic...
}
private boolean loadYoloFromResources() {
try { try {
Path path = Paths.get(weightsPath); // Load the model files from resources
if (!Files.exists(path) || Files.size(path) < 10000000) { byte[] weights = readResourceToByteArray("/yolov4-tiny.weights");
filesValid = false; byte[] config = readResourceToByteArray("/yolov4-tiny.cfg");
}
final Path path1 = Paths.get(configPath);
if (!Files.exists(path1) || Files.size(path1) < 10000) {
filesValid = false;
}
final Path path2 = Paths.get(classesPath);
if (!Files.exists(path2) || Files.size(path2) < 1000) {
filesValid = false;
}
} catch (IOException e) {
filesValid = false;
}
if (!filesValid) {
int reply = JOptionPane.showConfirmDialog(this,
"YOLO model files need to be downloaded (~25MB). Continue?",
"Download Files", JOptionPane.YES_NO_OPTION);
if (reply == JOptionPane.NO_OPTION) { if (weights == null || config == null) {
statusLabel.setText("Object detection disabled - model not loaded"); statusLabel.setText("Model files not found in resources");
return; return false;
} }
downloadYoloFiles(weightsUrl, configUrl, classesUrl); // Create temp files with proper extensions
File weightsFile = File.createTempFile("yolov4-tiny", ".weights");
File configFile = File.createTempFile("yolov4-tiny", ".cfg");
// Write bytes to temp files
Files.write(weightsFile.toPath(), weights);
Files.write(configFile.toPath(), config);
// Load the network
net = Dnn.readNetFromDarknet(configFile.getAbsolutePath(), weightsFile.getAbsolutePath());
if (net.empty()) {
statusLabel.setText("Failed to load model from resources");
return false;
} }
try {
net = Dnn.readNetFromDarknet(configPath, weightsPath);
// Try to use GPU if available (OpenCV Java doesn't have CUDA detection, so we'll use CPU)
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
statusLabel.setText("Using CPU backend");
// Load class names // Load class names
classes = new ArrayList<>(); classes = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(classesPath))) { try (InputStream classesStream = getClass().getResourceAsStream("/coco.names");
BufferedReader br = new BufferedReader(new InputStreamReader(classesStream))) {
String line; String line;
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
classes.add(line.trim()); classes.add(line.trim());
@@ -302,8 +302,7 @@ public class CameraApp extends JFrame {
// Get output layer names // Get output layer names
List<String> layerNames = net.getLayerNames(); List<String> layerNames = net.getLayerNames();
MatOfInt unconnectedOutLayers = new MatOfInt(); MatOfInt unconnectedOutLayers = net.getUnconnectedOutLayers();
net.getUnconnectedOutLayers();
int[] indices = unconnectedOutLayers.toArray(); int[] indices = unconnectedOutLayers.toArray();
outputLayers = new ArrayList<>(); outputLayers = new ArrayList<>();
@@ -312,15 +311,41 @@ public class CameraApp extends JFrame {
} }
modelLoaded = true; modelLoaded = true;
statusLabel.setText("YOLOv4 model loaded successfully"); statusLabel.setText("YOLOv4 model loaded from resources");
return true;
} catch (Exception e) { } catch (Exception e) {
modelLoaded = false; statusLabel.setText("Error loading model: " + e.getMessage());
statusLabel.setText(String.format("Error loading model: %s", e.getMessage())); e.printStackTrace();
JOptionPane.showMessageDialog(this, "Failed to load object detection model", "Error", JOptionPane.WARNING_MESSAGE); return false;
} }
} }
private byte [] readResourceToByteArray(String resourcePath) throws IOException {
try (InputStream is = getClass().getResourceAsStream(resourcePath)) {
if (is == null) return null;
return is.readAllBytes();
}
}
private boolean validateModel() {
if (net == null || net.empty()) {
statusLabel.setText("Model is empty or not loaded");
return false;
}
try {
// Create a dummy blob to test the network
Mat blob = Dnn.blobFromImage(new Mat(416, 416, CvType.CV_8UC3), 1.0/255.0);
net.setInput(blob);
List<Mat> outs = new ArrayList<>();
net.forward(outs, outputLayers);
return !outs.isEmpty();
} catch (Exception e) {
statusLabel.setText("Model validation failed: " + e.getMessage());
return false;
}
}
private void downloadYoloFiles(String weightsUrl, String configUrl, String classesUrl) { private void downloadYoloFiles(String weightsUrl, String configUrl, String classesUrl) {
String[][] files = { String[][] files = {
{"yolov4-tiny.weights", weightsUrl}, {"yolov4-tiny.weights", weightsUrl},
@@ -437,8 +462,16 @@ public class CameraApp extends JFrame {
} }
public void displayFrame(Mat frame) { public void displayFrame(Mat frame) {
if (frame == null || frame.empty()) {
return;
}
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
BufferedImage bufferedImage = matToBufferedImage(frame); BufferedImage bufferedImage = matToBufferedImage(frame);
if (bufferedImage == null) {
return;
}
ImageIcon imageIcon = new ImageIcon(bufferedImage); ImageIcon imageIcon = new ImageIcon(bufferedImage);
// Scale to fit label // Scale to fit label