fuck this shit ; i wont fucking maintain this anymore

This commit is contained in:
rattatwinko
2025-05-23 19:29:58 +02:00
parent f2eb9be5d7
commit 9169940214
4 changed files with 772 additions and 197 deletions

View File

@@ -7,6 +7,7 @@ import org.opencv.dnn.Net;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.VideoWriter;
import org.opencv.videoio.Videoio;
import javax.swing.*;
@@ -17,15 +18,15 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@@ -106,29 +107,6 @@ class DownloadProgressBar extends JDialog {
}
}
// Download progress handler class
class DownloadProgressHandler {
private DownloadProgressBar progressDialog;
private AtomicLong currentSize = new AtomicLong(0);
private AtomicLong totalSize = new AtomicLong(0);
private AtomicLong lastUpdate = new AtomicLong(0);
public DownloadProgressHandler(DownloadProgressBar progressDialog) {
this.progressDialog = progressDialog;
}
public void handleProgress(long current, long total) {
this.totalSize.set(total);
this.currentSize.set(current);
long currentTime = System.currentTimeMillis();
if (currentTime - lastUpdate.get() > 100) { // Update every 100ms
progressDialog.updateProgress(current, total);
lastUpdate.set(currentTime);
}
}
}
// Detection thread class
class DetectionThread extends Thread {
private Net net;
@@ -258,6 +236,10 @@ public class CameraApp extends JFrame {
private JButton stopButton;
private JButton snapshotButton;
private JLabel statusLabel;
private JPanel cameraControlPanel;
private JSlider brightnessSlider;
private JSlider contrastSlider;
private JSlider saturationSlider;
// Camera and detection attributes
private int cameraIndex = 0;
@@ -303,7 +285,7 @@ public class CameraApp extends JFrame {
private void initUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1000, 800);
setSize(1200, 900);
setLocationRelativeTo(null);
// Main panel
@@ -314,13 +296,16 @@ public class CameraApp extends JFrame {
videoLabel = new JLabel();
videoLabel.setHorizontalAlignment(JLabel.CENTER);
videoLabel.setVerticalAlignment(JLabel.CENTER);
videoLabel.setPreferredSize(new Dimension(640, 480));
videoLabel.setPreferredSize(new Dimension(800, 600));
videoLabel.setBorder(BorderFactory.createLoweredBevelBorder());
videoLabel.setText("Camera feed will appear here");
mainPanel.add(videoLabel, BorderLayout.CENTER);
// Control panel
JPanel controlPanel = new JPanel(new GridBagLayout());
JPanel controlPanel = new JPanel(new BorderLayout());
// Basic controls
JPanel basicControlPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.fill = GridBagConstraints.HORIZONTAL;
@@ -329,30 +314,36 @@ public class CameraApp extends JFrame {
gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
cameraSelect = new JComboBox<>();
cameraSelect.addActionListener(this::changeCamera);
controlPanel.add(cameraSelect, gbc);
basicControlPanel.add(cameraSelect, gbc);
// Detection checkbox
gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 2;
detectionCheckbox = new JCheckBox("Enable Object Detection", true);
detectionCheckbox.addActionListener(this::toggleDetection);
controlPanel.add(detectionCheckbox, gbc);
basicControlPanel.add(detectionCheckbox, gbc);
// Buttons
gbc.gridwidth = 1;
gbc.gridx = 0; gbc.gridy = 2;
startButton = new JButton("Start Camera");
startButton.addActionListener(e -> startCamera());
controlPanel.add(startButton, gbc);
basicControlPanel.add(startButton, gbc);
gbc.gridx = 1; gbc.gridy = 2;
stopButton = new JButton("Stop Camera");
stopButton.addActionListener(e -> stopCamera());
controlPanel.add(stopButton, gbc);
basicControlPanel.add(stopButton, gbc);
gbc.gridx = 0; gbc.gridy = 3; gbc.gridwidth = 2;
snapshotButton = new JButton("Take Snapshot");
snapshotButton.addActionListener(e -> takeSnapshot());
controlPanel.add(snapshotButton, gbc);
basicControlPanel.add(snapshotButton, gbc);
controlPanel.add(basicControlPanel, BorderLayout.NORTH);
// Camera controls panel for C920
cameraControlPanel = createCameraControlPanel();
controlPanel.add(cameraControlPanel, BorderLayout.CENTER);
mainPanel.add(controlPanel, BorderLayout.EAST);
@@ -385,6 +376,82 @@ public class CameraApp extends JFrame {
});
}
private JPanel createCameraControlPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createTitledBorder("Camera Controls"));
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.fill = GridBagConstraints.HORIZONTAL;
// Brightness control
gbc.gridx = 0; gbc.gridy = 0;
panel.add(new JLabel("Brightness:"), gbc);
gbc.gridx = 1; gbc.gridy = 0;
brightnessSlider = new JSlider(-100, 100, 0);
brightnessSlider.addChangeListener(e -> adjustCameraSettings());
panel.add(brightnessSlider, gbc);
// Contrast control
gbc.gridx = 0; gbc.gridy = 1;
panel.add(new JLabel("Contrast:"), gbc);
gbc.gridx = 1; gbc.gridy = 1;
contrastSlider = new JSlider(0, 200, 100);
contrastSlider.addChangeListener(e -> adjustCameraSettings());
panel.add(contrastSlider, gbc);
// Saturation control
gbc.gridx = 0; gbc.gridy = 2;
panel.add(new JLabel("Saturation:"), gbc);
gbc.gridx = 1; gbc.gridy = 2;
saturationSlider = new JSlider(0, 200, 100);
saturationSlider.addChangeListener(e -> adjustCameraSettings());
panel.add(saturationSlider, gbc);
// Reset button
gbc.gridx = 0; gbc.gridy = 3; gbc.gridwidth = 2;
JButton resetButton = new JButton("Reset to Default");
resetButton.addActionListener(e -> resetCameraSettings());
panel.add(resetButton, gbc);
return panel;
}
private void adjustCameraSettings() {
if (cap == null || !cap.isOpened()) {
return;
}
try {
// Apply brightness (-100 to 100, normalized to 0.0-1.0)
double brightness = (brightnessSlider.getValue() + 100) / 200.0;
cap.set(Videoio.CAP_PROP_BRIGHTNESS, brightness);
// Apply contrast (0 to 200, normalized to 0.0-2.0)
double contrast = contrastSlider.getValue() / 100.0;
cap.set(Videoio.CAP_PROP_CONTRAST, contrast);
// Apply saturation (0 to 200, normalized to 0.0-2.0)
double saturation = saturationSlider.getValue() / 100.0;
cap.set(Videoio.CAP_PROP_SATURATION, saturation);
// Additional C920 specific settings
cap.set(Videoio.CAP_PROP_AUTO_WB, 1); // Enable auto white balance
cap.set(Videoio.CAP_PROP_EXPOSURE, -5); // Set exposure for better indoor lighting
statusLabel.setText("Camera settings adjusted");
} catch (Exception e) {
System.out.println("Warning: Could not adjust all camera settings: " + e.getMessage());
}
}
private void resetCameraSettings() {
brightnessSlider.setValue(0);
contrastSlider.setValue(100);
saturationSlider.setValue(100);
adjustCameraSettings();
}
private void toggleDetection(ActionEvent e) {
detectionEnabled.set(detectionCheckbox.isSelected());
statusLabel.setText("Detection " + (detectionEnabled.get() ? "enabled" : "disabled"));
@@ -461,7 +528,13 @@ public class CameraApp extends JFrame {
selected = availableCameras.get(0);
}
cap = new VideoCapture(selected.index, selected.backend);
// Try to open with default backend first
cap = new VideoCapture(selected.index);
if (!cap.isOpened()) {
// Fall back to selected backend if default fails
cap = new VideoCapture(selected.index, selected.backend);
}
if (!cap.isOpened()) {
JOptionPane.showMessageDialog(this,
String.format("Cannot open camera %d", selected.index),
@@ -470,14 +543,37 @@ public class CameraApp extends JFrame {
return;
}
// Set camera properties
cap.set(Videoio.CAP_PROP_FRAME_WIDTH, 1280);
cap.set(Videoio.CAP_PROP_FRAME_HEIGHT, 720);
cap.set(Videoio.CAP_PROP_FPS, 60);
cap.set(Videoio.CAP_PROP_AUTOFOCUS, 0);
// Enhanced camera settings for C920
try {
// Set resolution - C920 supports up to 1920x1080
cap.set(Videoio.CAP_PROP_FRAME_WIDTH, 1280);
cap.set(Videoio.CAP_PROP_FRAME_HEIGHT, 720);
cap.set(Videoio.CAP_PROP_FPS, 30);
// C920 specific optimizations
cap.set(Videoio.CAP_PROP_FOURCC, VideoWriter.fourcc('M', 'J', 'P', 'G'));
cap.set(Videoio.CAP_PROP_AUTOFOCUS, 1); // Enable autofocus
cap.set(Videoio.CAP_PROP_AUTO_WB, 1); // Auto white balance
cap.set(Videoio.CAP_PROP_AUTO_EXPOSURE, 0.25); // Some auto exposure
cap.set(Videoio.CAP_PROP_EXPOSURE, -5); // Manual exposure for indoor
cap.set(Videoio.CAP_PROP_GAIN, 0); // Minimize gain to reduce noise
// Apply current slider settings
adjustCameraSettings();
} catch (Exception e) {
System.out.println("Warning: Could not set all camera properties: " + e.getMessage());
}
// Get actual settings that were applied
double actualWidth = cap.get(Videoio.CAP_PROP_FRAME_WIDTH);
double actualHeight = cap.get(Videoio.CAP_PROP_FRAME_HEIGHT);
double actualFps = cap.get(Videoio.CAP_PROP_FPS);
statusLabel.setText(String.format("Camera %d started (%dx%d @ %.1f FPS)",
selected.index, (int)actualWidth, (int)actualHeight, actualFps));
timer.start();
statusLabel.setText(String.format("Camera %d started", selected.index));
} catch (Exception ex) {
JOptionPane.showMessageDialog(this,
@@ -503,11 +599,161 @@ public class CameraApp extends JFrame {
}
}
private void loadYolo() {
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 classesUrl = "https://raw.githubusercontent.com/AlexeyAB/darknet/master/data/coco.names";
private void updateFrame(ActionEvent e) {
if (cap == null || !cap.isOpened()) {
return;
}
Mat frame = new Mat();
if (cap.read(frame) && !frame.empty()) {
// Update FPS counter
frameCount++;
long currentTime = System.currentTimeMillis();
if (currentTime - lastFpsUpdate >= 1000) {
fps = frameCount * 1000.0 / (currentTime - lastFpsUpdate);
frameCount = 0;
lastFpsUpdate = currentTime;
}
// Process frame with detection if enabled
if (detectionEnabled.get() && modelLoaded.get()) {
processWithDetection(frame);
} else {
displayFrame(frame);
}
}
}
private void processWithDetection(Mat frame) {
// Stop previous detection if still running
if (detectionThread != null && detectionThread.isAlive()) {
detectionThread.stopDetection();
}
// Start new detection
detectionThread = new DetectionThread(net, classes, outputLayers, frame);
detectionThread.start();
// Get result asynchronously
detectionThread.getDetectionResult().thenAccept(this::displayFrame);
}
private void displayFrame(Mat frame) {
if (frame == null || frame.empty()) {
return;
}
try {
// Add FPS text to frame
String fpsText = String.format("FPS: %.1f", fps);
Point textPos = new Point(10, 30);
Imgproc.putText(frame, fpsText, textPos, Imgproc.FONT_HERSHEY_SIMPLEX, 1, new Scalar(0, 255, 0), 2);
// Convert Mat to BufferedImage
BufferedImage image = matToBufferedImage(frame);
// Scale image to fit label while maintaining aspect ratio
Dimension labelSize = videoLabel.getSize();
if (labelSize.width > 0 && labelSize.height > 0) {
Image scaledImage = image.getScaledInstance(labelSize.width, labelSize.height, Image.SCALE_SMOOTH);
ImageIcon icon = new ImageIcon(scaledImage);
SwingUtilities.invokeLater(() -> videoLabel.setIcon(icon));
}
} catch (Exception ex) {
System.out.println("Error displaying frame: " + ex.getMessage());
}
}
private BufferedImage matToBufferedImage(Mat mat) {
int type = BufferedImage.TYPE_BYTE_GRAY;
if (mat.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = mat.channels() * mat.cols() * mat.rows();
byte[] buffer = new byte[bufferSize];
mat.get(0, 0, buffer); // get all pixels
BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
return image;
}
private void takeSnapshot() {
if (cap == null || !cap.isOpened()) {
JOptionPane.showMessageDialog(this, "Camera is not active", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
Mat frame = new Mat();
if (cap.read(frame) && !frame.empty()) {
try {
// Create snapshots directory if it doesn't exist
File snapshotDir = new File("snapshots");
if (!snapshotDir.exists()) {
snapshotDir.mkdirs();
}
// Generate filename with timestamp
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
String timestamp = sdf.format(new Date());
String filename = String.format("snapshots/snapshot_%s.jpg", timestamp);
// Save image
Imgcodecs.imwrite(filename, frame);
statusLabel.setText("Snapshot saved: " + filename);
JOptionPane.showMessageDialog(this,
"Snapshot saved successfully!\n" + filename,
"Snapshot", JOptionPane.INFORMATION_MESSAGE);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this,
"Error saving snapshot: " + ex.getMessage(),
"Error", JOptionPane.ERROR_MESSAGE);
}
}
}
private boolean loadYoloFromResources() {
try {
// Check if files exist in resources
InputStream weightsStream = getClass().getResourceAsStream("/yolov4-tiny.weights");
InputStream configStream = getClass().getResourceAsStream("/yolov4-tiny.cfg");
InputStream classesStream = getClass().getResourceAsStream("/coco.names");
if (weightsStream != null && configStream != null && classesStream != null) {
statusLabel.setText("Loading YOLO from resources...");
// Copy files from resources to working directory
Files.copy(weightsStream, Paths.get("yolov4-tiny.weights"), StandardCopyOption.REPLACE_EXISTING);
Files.copy(configStream, Paths.get("yolov4-tiny.cfg"), StandardCopyOption.REPLACE_EXISTING);
Files.copy(classesStream, Paths.get("coco.names"), StandardCopyOption.REPLACE_EXISTING);
weightsStream.close();
configStream.close();
classesStream.close();
statusLabel.setText("YOLO files loaded from resources");
return true;
}
} catch (Exception e) {
System.out.println("Could not load YOLO from resources: " + e.getMessage());
}
return false;
}
private void loadYolo() {
// First try to load from resources
if (loadYoloFromResources()) {
initializeYoloModel();
return;
}
// If not in resources, check existing files
String weightsPath = "yolov4-tiny.weights";
String configPath = "yolov4-tiny.cfg";
String classesPath = "coco.names";
@@ -525,28 +771,45 @@ public class CameraApp extends JFrame {
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.YES_OPTION) {
statusLabel.setText("Object detection disabled - model not loaded");
return;
}
downloadYoloFiles(weightsUrl, configUrl, classesUrl);
if (filesValid) {
initializeYoloModel();
return;
}
// If files don't exist, offer to download
int reply = JOptionPane.showConfirmDialog(this,
"YOLO model files need to be downloaded (~25MB). Continue?",
"Download Files",
JOptionPane.YES_NO_OPTION);
if (reply != JOptionPane.YES_OPTION) {
statusLabel.setText("Object detection disabled - model not loaded");
detectionCheckbox.setSelected(false);
detectionEnabled.set(false);
return;
}
// Download files
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 classesUrl = "https://raw.githubusercontent.com/AlexeyAB/darknet/master/data/coco.names";
downloadYoloFiles(weightsUrl, configUrl, classesUrl);
}
private void initializeYoloModel() {
try {
String weightsPath = "yolov4-tiny.weights";
String configPath = "yolov4-tiny.cfg";
String classesPath = "coco.names";
net = Dnn.readNetFromDarknet(configPath, weightsPath);
// Try to use CUDA if available (OpenCV Java bindings may not support this fully)
// Try to use CUDA if available
try {
net.setPreferableBackend(Dnn.DNN_BACKEND_CUDA);
net.setPreferableTarget(Dnn.DNN_TARGET_CUDA);
statusLabel.setText("Attempting CUDA acceleration");
statusLabel.setText("Using CUDA acceleration");
} catch (Exception e) {
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
@@ -572,12 +835,16 @@ public class CameraApp extends JFrame {
}
modelLoaded.set(true);
statusLabel.setText("YOLOv4 model loaded successfully");
statusLabel.setText("YOLOv4-Tiny model loaded successfully (" + classes.size() + " classes)");
} catch (Exception e) {
modelLoaded.set(false);
statusLabel.setText("Error loading model: " + e.getMessage());
JOptionPane.showMessageDialog(this, "Failed to load object detection model", "Error", JOptionPane.WARNING_MESSAGE);
JOptionPane.showMessageDialog(this,
"Failed to load object detection model: " + e.getMessage(),
"Error", JOptionPane.WARNING_MESSAGE);
detectionCheckbox.setSelected(false);
detectionEnabled.set(false);
}
}
@@ -601,17 +868,19 @@ public class CameraApp extends JFrame {
// Download in background thread
CompletableFuture.runAsync(() -> {
boolean allSuccess = true;
try {
for (String[] file : files) {
String fileName = file[0];
String url = file[1];
// Check if file already exists and is valid
if (Files.exists(Paths.get(fileName))) {
try {
long size = getFileSize(fileName);
if ((fileName.equals("yolov4-tiny.weights") && size >= 10000000) ||
(fileName.equals("yolov4-tiny.cfg") && size >= 10000) ||
(fileName.equals("coco.names") && size >= 1000)) {
(fileName.equals("yolov4-tiny.cfg") && size >= 1000) ||
(fileName.equals("coco.names") && size >= 500)) {
continue;
}
} catch (Exception e) {
@@ -620,6 +889,7 @@ public class CameraApp extends JFrame {
}
if (progressDialog.isCancelled()) {
allSuccess = false;
break;
}
@@ -631,14 +901,34 @@ public class CameraApp extends JFrame {
System.out.println("Downloaded " + fileName);
} catch (Exception e) {
System.out.println("Error downloading " + fileName + ": " + e.getMessage());
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(this, "Failed to download " + fileName, "Error", JOptionPane.ERROR_MESSAGE);
});
allSuccess = false;
break;
}
}
} finally {
SwingUtilities.invokeLater(() -> progressDialog.dispose());
boolean finalAllSuccess = allSuccess;
SwingUtilities.invokeLater(() -> {
progressDialog.dispose();
if (finalAllSuccess && !progressDialog.isCancelled()) {
statusLabel.setText("YOLO files downloaded successfully");
initializeYoloModel();
} else {
statusLabel.setText("Download failed or cancelled");
detectionCheckbox.setSelected(false);
detectionEnabled.set(false);
}
});
} catch (Exception e) {
SwingUtilities.invokeLater(() -> {
progressDialog.dispose();
statusLabel.setText("Download error: " + e.getMessage());
JOptionPane.showMessageDialog(this,
"Download failed: " + e.getMessage(),
"Error", JOptionPane.ERROR_MESSAGE);
detectionCheckbox.setSelected(false);
detectionEnabled.set(false);
});
}
}, executorService);
}
@@ -647,17 +937,25 @@ public class CameraApp extends JFrame {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
connection.setConnectTimeout(10000);
connection.setReadTimeout(30000);
int contentLength = connection.getContentLength();
// Set user agent to avoid blocking
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
int responseCode = connection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
throw new IOException("HTTP error code: " + responseCode);
}
long fileSize = connection.getContentLengthLong();
try (InputStream inputStream = connection.getInputStream();
FileOutputStream outputStream = new FileOutputStream(fileName)) {
byte[] buffer = new byte[8192];
int bytesRead;
long totalBytesRead = 0;
long lastUpdate = 0;
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
if (progressDialog.isCancelled()) {
@@ -667,150 +965,53 @@ public class CameraApp extends JFrame {
outputStream.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
long currentTime = System.currentTimeMillis();
if (currentTime - lastUpdate > 100) { // Update every 100ms
progressDialog.updateProgress(totalBytesRead, contentLength);
lastUpdate = currentTime;
if (fileSize > 0) {
progressDialog.updateProgress(totalBytesRead, fileSize);
}
}
}
}
private void updateFrame(ActionEvent e) {
if (cap == null || !cap.isOpened()) {
return;
}
Mat frame = new Mat();
boolean ret = cap.read(frame);
if (!ret || frame.empty()) {
statusLabel.setText("Failed to capture frame");
return;
}
frameCount++;
long currentTime = System.currentTimeMillis();
if (currentTime - lastFpsUpdate >= 1000) {
fps = frameCount * 1000.0 / (currentTime - lastFpsUpdate);
lastFpsUpdate = currentTime;
frameCount = 0;
statusLabel.setText(String.format("Running at %.1f FPS", fps));
}
// Convert BGR to RGB
Mat rgbFrame = new Mat();
Imgproc.cvtColor(frame, rgbFrame, Imgproc.COLOR_BGR2RGB);
if (detectionEnabled.get() && modelLoaded.get()) {
if (detectionThread == null || !detectionThread.isAlive()) {
detectionThread = new DetectionThread(net, classes, outputLayers, rgbFrame);
detectionThread.start();
// Handle detection result asynchronously
detectionThread.getDetectionResult().thenAccept(this::displayFrame);
} else {
displayFrame(rgbFrame);
}
} else {
displayFrame(rgbFrame);
}
}
private void displayFrame(Mat frame) {
SwingUtilities.invokeLater(() -> {
BufferedImage bufferedImage = matToBufferedImage(frame);
if (bufferedImage != null) {
// Scale image to fit label while maintaining aspect ratio
Dimension labelSize = videoLabel.getSize();
ImageIcon scaledIcon = new ImageIcon(bufferedImage.getScaledInstance(
labelSize.width, labelSize.height, Image.SCALE_SMOOTH));
videoLabel.setIcon(scaledIcon);
videoLabel.setText(null);
}
});
}
private BufferedImage matToBufferedImage(Mat mat) {
try {
int type = BufferedImage.TYPE_BYTE_GRAY;
if (mat.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = mat.channels() * mat.cols() * mat.rows();
byte[] buffer = new byte[bufferSize];
mat.get(0, 0, buffer); // get all pixels
BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
return image;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private void takeSnapshot() {
if (cap == null || !cap.isOpened()) {
JOptionPane.showMessageDialog(this, "No active camera to take snapshot from", "Warning", JOptionPane.WARNING_MESSAGE);
return;
}
Mat frame = new Mat();
boolean ret = cap.read(frame);
if (!ret || frame.empty()) {
JOptionPane.showMessageDialog(this, "Failed to capture frame", "Warning", JOptionPane.WARNING_MESSAGE);
return;
}
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Save Snapshot");
fileChooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter("JPEG Images", "jpg", "jpeg"));
int result = fileChooser.showSaveDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
String fileName = fileChooser.getSelectedFile().getAbsolutePath();
if (!fileName.toLowerCase().endsWith(".jpg") && !fileName.toLowerCase().endsWith(".jpeg")) {
fileName += ".jpg";
}
// Convert BGR to RGB for saving
Mat rgbFrame = new Mat();
Imgproc.cvtColor(frame, rgbFrame, Imgproc.COLOR_BGR2RGB);
boolean success = Imgcodecs.imwrite(fileName, rgbFrame);
if (success) {
statusLabel.setText("Snapshot saved to " + fileName);
} else {
JOptionPane.showMessageDialog(this, "Failed to save snapshot", "Error", JOptionPane.WARNING_MESSAGE);
}
}
connection.disconnect();
}
private void closeEvent() {
stopCamera();
if (cap != null) {
cap.release();
}
if (detectionThread != null) {
detectionThread.stopDetection();
}
if (executorService != null) {
executorService.shutdown();
executorService.shutdownNow();
}
System.exit(0);
}
// Main method
public static void main(String[] args) {
try {
// Set system look and feel
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
System.out.println("Could not set system look and feel: " + e.getMessage());
}
SwingUtilities.invokeLater(() -> {
CameraApp app = new CameraApp();
app.setVisible(true);
});
}
}
try {
new CameraApp().setVisible(true);
} catch (Exception e) {
System.err.println("Error starting application: " + e.getMessage());
e.printStackTrace();
JOptionPane.showMessageDialog(null,
"Error starting application:\n" + e.getMessage() +
"\n\nPlease ensure OpenCV is properly installed and configured.",
"Startup Error",
JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
});
}}

View File

@@ -0,0 +1,80 @@
person
bicycle
car
motorbike
aeroplane
bus
train
truck
boat
traffic light
fire hydrant
stop sign
parking meter
bench
bird
cat
dog
horse
sheep
cow
elephant
bear
zebra
giraffe
backpack
umbrella
handbag
tie
suitcase
frisbee
skis
snowboard
sports ball
kite
baseball bat
baseball glove
skateboard
surfboard
tennis racket
bottle
wine glass
cup
fork
knife
spoon
bowl
banana
apple
sandwich
orange
broccoli
carrot
hot dog
pizza
donut
cake
chair
sofa
pottedplant
bed
diningtable
toilet
tvmonitor
laptop
mouse
remote
keyboard
cell phone
microwave
oven
toaster
sink
refrigerator
book
clock
vase
scissors
teddy bear
hair drier
toothbrush

View File

@@ -0,0 +1,294 @@
[net]
# Testing
#batch=1
#subdivisions=1
# Training
batch=64
subdivisions=1
width=416
height=416
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1
learning_rate=0.00261
burn_in=1000
max_batches = 2000200
policy=steps
steps=1600000,1800000
scales=.1,.1
#weights_reject_freq=1001
#ema_alpha=0.9998
#equidistant_point=1000
#num_sigmas_reject_badlabels=3
#badlabels_rejection_percentage=0.2
[convolutional]
batch_normalize=1
filters=32
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=3
stride=2
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[route]
layers=-1
groups=2
group_id=1
[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky
[route]
layers = -1,-2
[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky
[route]
layers = -6,-1
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[route]
layers=-1
groups=2
group_id=1
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[route]
layers = -1,-2
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[route]
layers = -6,-1
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[route]
layers=-1
groups=2
group_id=1
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[route]
layers = -1,-2
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[route]
layers = -6,-1
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
##################################
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=255
activation=linear
[yolo]
mask = 3,4,5
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
classes=80
num=6
jitter=.3
scale_x_y = 1.05
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
ignore_thresh = .7
truth_thresh = 1
random=0
resize=1.5
nms_kind=greedynms
beta_nms=0.6
#new_coords=1
#scale_x_y = 2.0
[route]
layers = -4
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[upsample]
stride=2
[route]
layers = -1, 23
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[convolutional]
size=1
stride=1
pad=1
filters=255
activation=linear
[yolo]
mask = 1,2,3
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
classes=80
num=6
jitter=.3
scale_x_y = 1.05
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
ignore_thresh = .7
truth_thresh = 1
random=0
resize=1.5
nms_kind=greedynms
beta_nms=0.6
#new_coords=1
#scale_x_y = 2.0

Binary file not shown.