fuck this shit ; i wont fucking maintain this anymore
This commit is contained in:
@@ -7,6 +7,7 @@ import org.opencv.dnn.Net;
|
|||||||
import org.opencv.imgcodecs.Imgcodecs;
|
import org.opencv.imgcodecs.Imgcodecs;
|
||||||
import org.opencv.imgproc.Imgproc;
|
import org.opencv.imgproc.Imgproc;
|
||||||
import org.opencv.videoio.VideoCapture;
|
import org.opencv.videoio.VideoCapture;
|
||||||
|
import org.opencv.videoio.VideoWriter;
|
||||||
import org.opencv.videoio.Videoio;
|
import org.opencv.videoio.Videoio;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@@ -17,15 +18,15 @@ import java.awt.event.WindowAdapter;
|
|||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.DataBufferByte;
|
import java.awt.image.DataBufferByte;
|
||||||
import java.io.BufferedReader;
|
import java.io.*;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutorService;
|
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
|
// Detection thread class
|
||||||
class DetectionThread extends Thread {
|
class DetectionThread extends Thread {
|
||||||
private Net net;
|
private Net net;
|
||||||
@@ -258,6 +236,10 @@ public class CameraApp extends JFrame {
|
|||||||
private JButton stopButton;
|
private JButton stopButton;
|
||||||
private JButton snapshotButton;
|
private JButton snapshotButton;
|
||||||
private JLabel statusLabel;
|
private JLabel statusLabel;
|
||||||
|
private JPanel cameraControlPanel;
|
||||||
|
private JSlider brightnessSlider;
|
||||||
|
private JSlider contrastSlider;
|
||||||
|
private JSlider saturationSlider;
|
||||||
|
|
||||||
// Camera and detection attributes
|
// Camera and detection attributes
|
||||||
private int cameraIndex = 0;
|
private int cameraIndex = 0;
|
||||||
@@ -303,7 +285,7 @@ public class CameraApp extends JFrame {
|
|||||||
|
|
||||||
private void initUI() {
|
private void initUI() {
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
setSize(1000, 800);
|
setSize(1200, 900);
|
||||||
setLocationRelativeTo(null);
|
setLocationRelativeTo(null);
|
||||||
|
|
||||||
// Main panel
|
// Main panel
|
||||||
@@ -314,13 +296,16 @@ public class CameraApp extends JFrame {
|
|||||||
videoLabel = new JLabel();
|
videoLabel = new JLabel();
|
||||||
videoLabel.setHorizontalAlignment(JLabel.CENTER);
|
videoLabel.setHorizontalAlignment(JLabel.CENTER);
|
||||||
videoLabel.setVerticalAlignment(JLabel.CENTER);
|
videoLabel.setVerticalAlignment(JLabel.CENTER);
|
||||||
videoLabel.setPreferredSize(new Dimension(640, 480));
|
videoLabel.setPreferredSize(new Dimension(800, 600));
|
||||||
videoLabel.setBorder(BorderFactory.createLoweredBevelBorder());
|
videoLabel.setBorder(BorderFactory.createLoweredBevelBorder());
|
||||||
videoLabel.setText("Camera feed will appear here");
|
videoLabel.setText("Camera feed will appear here");
|
||||||
mainPanel.add(videoLabel, BorderLayout.CENTER);
|
mainPanel.add(videoLabel, BorderLayout.CENTER);
|
||||||
|
|
||||||
// Control panel
|
// 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();
|
GridBagConstraints gbc = new GridBagConstraints();
|
||||||
gbc.insets = new Insets(5, 5, 5, 5);
|
gbc.insets = new Insets(5, 5, 5, 5);
|
||||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
@@ -329,30 +314,36 @@ public class CameraApp extends JFrame {
|
|||||||
gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
|
gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
|
||||||
cameraSelect = new JComboBox<>();
|
cameraSelect = new JComboBox<>();
|
||||||
cameraSelect.addActionListener(this::changeCamera);
|
cameraSelect.addActionListener(this::changeCamera);
|
||||||
controlPanel.add(cameraSelect, gbc);
|
basicControlPanel.add(cameraSelect, gbc);
|
||||||
|
|
||||||
// Detection checkbox
|
// Detection checkbox
|
||||||
gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 2;
|
gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 2;
|
||||||
detectionCheckbox = new JCheckBox("Enable Object Detection", true);
|
detectionCheckbox = new JCheckBox("Enable Object Detection", true);
|
||||||
detectionCheckbox.addActionListener(this::toggleDetection);
|
detectionCheckbox.addActionListener(this::toggleDetection);
|
||||||
controlPanel.add(detectionCheckbox, gbc);
|
basicControlPanel.add(detectionCheckbox, gbc);
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
gbc.gridwidth = 1;
|
gbc.gridwidth = 1;
|
||||||
gbc.gridx = 0; gbc.gridy = 2;
|
gbc.gridx = 0; gbc.gridy = 2;
|
||||||
startButton = new JButton("Start Camera");
|
startButton = new JButton("Start Camera");
|
||||||
startButton.addActionListener(e -> startCamera());
|
startButton.addActionListener(e -> startCamera());
|
||||||
controlPanel.add(startButton, gbc);
|
basicControlPanel.add(startButton, gbc);
|
||||||
|
|
||||||
gbc.gridx = 1; gbc.gridy = 2;
|
gbc.gridx = 1; gbc.gridy = 2;
|
||||||
stopButton = new JButton("Stop Camera");
|
stopButton = new JButton("Stop Camera");
|
||||||
stopButton.addActionListener(e -> stopCamera());
|
stopButton.addActionListener(e -> stopCamera());
|
||||||
controlPanel.add(stopButton, gbc);
|
basicControlPanel.add(stopButton, gbc);
|
||||||
|
|
||||||
gbc.gridx = 0; gbc.gridy = 3; gbc.gridwidth = 2;
|
gbc.gridx = 0; gbc.gridy = 3; gbc.gridwidth = 2;
|
||||||
snapshotButton = new JButton("Take Snapshot");
|
snapshotButton = new JButton("Take Snapshot");
|
||||||
snapshotButton.addActionListener(e -> takeSnapshot());
|
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);
|
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) {
|
private void toggleDetection(ActionEvent e) {
|
||||||
detectionEnabled.set(detectionCheckbox.isSelected());
|
detectionEnabled.set(detectionCheckbox.isSelected());
|
||||||
statusLabel.setText("Detection " + (detectionEnabled.get() ? "enabled" : "disabled"));
|
statusLabel.setText("Detection " + (detectionEnabled.get() ? "enabled" : "disabled"));
|
||||||
@@ -461,7 +528,13 @@ public class CameraApp extends JFrame {
|
|||||||
selected = availableCameras.get(0);
|
selected = availableCameras.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
cap = new VideoCapture(selected.index, selected.backend);
|
||||||
|
}
|
||||||
|
|
||||||
if (!cap.isOpened()) {
|
if (!cap.isOpened()) {
|
||||||
JOptionPane.showMessageDialog(this,
|
JOptionPane.showMessageDialog(this,
|
||||||
String.format("Cannot open camera %d", selected.index),
|
String.format("Cannot open camera %d", selected.index),
|
||||||
@@ -470,14 +543,37 @@ public class CameraApp extends JFrame {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set camera properties
|
// 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_WIDTH, 1280);
|
||||||
cap.set(Videoio.CAP_PROP_FRAME_HEIGHT, 720);
|
cap.set(Videoio.CAP_PROP_FRAME_HEIGHT, 720);
|
||||||
cap.set(Videoio.CAP_PROP_FPS, 60);
|
cap.set(Videoio.CAP_PROP_FPS, 30);
|
||||||
cap.set(Videoio.CAP_PROP_AUTOFOCUS, 0);
|
|
||||||
|
// 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();
|
timer.start();
|
||||||
statusLabel.setText(String.format("Camera %d started", selected.index));
|
|
||||||
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
JOptionPane.showMessageDialog(this,
|
JOptionPane.showMessageDialog(this,
|
||||||
@@ -503,11 +599,161 @@ public class CameraApp extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadYolo() {
|
private void updateFrame(ActionEvent e) {
|
||||||
String weightsUrl = "https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.weights";
|
if (cap == null || !cap.isOpened()) {
|
||||||
String configUrl = "https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4-tiny.cfg";
|
return;
|
||||||
String classesUrl = "https://raw.githubusercontent.com/AlexeyAB/darknet/master/data/coco.names";
|
}
|
||||||
|
|
||||||
|
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 weightsPath = "yolov4-tiny.weights";
|
||||||
String configPath = "yolov4-tiny.cfg";
|
String configPath = "yolov4-tiny.cfg";
|
||||||
String classesPath = "coco.names";
|
String classesPath = "coco.names";
|
||||||
@@ -525,7 +771,12 @@ public class CameraApp extends JFrame {
|
|||||||
filesValid = false;
|
filesValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filesValid) {
|
if (filesValid) {
|
||||||
|
initializeYoloModel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If files don't exist, offer to download
|
||||||
int reply = JOptionPane.showConfirmDialog(this,
|
int reply = JOptionPane.showConfirmDialog(this,
|
||||||
"YOLO model files need to be downloaded (~25MB). Continue?",
|
"YOLO model files need to be downloaded (~25MB). Continue?",
|
||||||
"Download Files",
|
"Download Files",
|
||||||
@@ -533,20 +784,32 @@ public class CameraApp extends JFrame {
|
|||||||
|
|
||||||
if (reply != JOptionPane.YES_OPTION) {
|
if (reply != JOptionPane.YES_OPTION) {
|
||||||
statusLabel.setText("Object detection disabled - model not loaded");
|
statusLabel.setText("Object detection disabled - model not loaded");
|
||||||
|
detectionCheckbox.setSelected(false);
|
||||||
|
detectionEnabled.set(false);
|
||||||
return;
|
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);
|
downloadYoloFiles(weightsUrl, configUrl, classesUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeYoloModel() {
|
||||||
try {
|
try {
|
||||||
|
String weightsPath = "yolov4-tiny.weights";
|
||||||
|
String configPath = "yolov4-tiny.cfg";
|
||||||
|
String classesPath = "coco.names";
|
||||||
|
|
||||||
net = Dnn.readNetFromDarknet(configPath, weightsPath);
|
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 {
|
try {
|
||||||
net.setPreferableBackend(Dnn.DNN_BACKEND_CUDA);
|
net.setPreferableBackend(Dnn.DNN_BACKEND_CUDA);
|
||||||
net.setPreferableTarget(Dnn.DNN_TARGET_CUDA);
|
net.setPreferableTarget(Dnn.DNN_TARGET_CUDA);
|
||||||
statusLabel.setText("Attempting CUDA acceleration");
|
statusLabel.setText("Using CUDA acceleration");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
|
net.setPreferableBackend(Dnn.DNN_BACKEND_OPENCV);
|
||||||
net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
|
net.setPreferableTarget(Dnn.DNN_TARGET_CPU);
|
||||||
@@ -572,12 +835,16 @@ public class CameraApp extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
modelLoaded.set(true);
|
modelLoaded.set(true);
|
||||||
statusLabel.setText("YOLOv4 model loaded successfully");
|
statusLabel.setText("YOLOv4-Tiny model loaded successfully (" + classes.size() + " classes)");
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
modelLoaded.set(false);
|
modelLoaded.set(false);
|
||||||
statusLabel.setText("Error loading model: " + e.getMessage());
|
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
|
// Download in background thread
|
||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
|
boolean allSuccess = true;
|
||||||
try {
|
try {
|
||||||
for (String[] file : files) {
|
for (String[] file : files) {
|
||||||
String fileName = file[0];
|
String fileName = file[0];
|
||||||
String url = file[1];
|
String url = file[1];
|
||||||
|
|
||||||
|
// Check if file already exists and is valid
|
||||||
if (Files.exists(Paths.get(fileName))) {
|
if (Files.exists(Paths.get(fileName))) {
|
||||||
try {
|
try {
|
||||||
long size = getFileSize(fileName);
|
long size = getFileSize(fileName);
|
||||||
if ((fileName.equals("yolov4-tiny.weights") && size >= 10000000) ||
|
if ((fileName.equals("yolov4-tiny.weights") && size >= 10000000) ||
|
||||||
(fileName.equals("yolov4-tiny.cfg") && size >= 10000) ||
|
(fileName.equals("yolov4-tiny.cfg") && size >= 1000) ||
|
||||||
(fileName.equals("coco.names") && size >= 1000)) {
|
(fileName.equals("coco.names") && size >= 500)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -620,6 +889,7 @@ public class CameraApp extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (progressDialog.isCancelled()) {
|
if (progressDialog.isCancelled()) {
|
||||||
|
allSuccess = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,14 +901,34 @@ public class CameraApp extends JFrame {
|
|||||||
System.out.println("Downloaded " + fileName);
|
System.out.println("Downloaded " + fileName);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("Error downloading " + fileName + ": " + e.getMessage());
|
System.out.println("Error downloading " + fileName + ": " + e.getMessage());
|
||||||
SwingUtilities.invokeLater(() -> {
|
allSuccess = false;
|
||||||
JOptionPane.showMessageDialog(this, "Failed to download " + fileName, "Error", JOptionPane.ERROR_MESSAGE);
|
|
||||||
});
|
|
||||||
break;
|
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);
|
}, executorService);
|
||||||
}
|
}
|
||||||
@@ -647,17 +937,25 @@ public class CameraApp extends JFrame {
|
|||||||
URL url = new URL(urlString);
|
URL url = new URL(urlString);
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
connection.setRequestMethod("GET");
|
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();
|
try (InputStream inputStream = connection.getInputStream();
|
||||||
FileOutputStream outputStream = new FileOutputStream(fileName)) {
|
FileOutputStream outputStream = new FileOutputStream(fileName)) {
|
||||||
|
|
||||||
byte[] buffer = new byte[8192];
|
byte[] buffer = new byte[8192];
|
||||||
int bytesRead;
|
|
||||||
long totalBytesRead = 0;
|
long totalBytesRead = 0;
|
||||||
long lastUpdate = 0;
|
int bytesRead;
|
||||||
|
|
||||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
if (progressDialog.isCancelled()) {
|
if (progressDialog.isCancelled()) {
|
||||||
@@ -667,150 +965,53 @@ public class CameraApp extends JFrame {
|
|||||||
outputStream.write(buffer, 0, bytesRead);
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
totalBytesRead += bytesRead;
|
totalBytesRead += bytesRead;
|
||||||
|
|
||||||
long currentTime = System.currentTimeMillis();
|
if (fileSize > 0) {
|
||||||
if (currentTime - lastUpdate > 100) { // Update every 100ms
|
progressDialog.updateProgress(totalBytesRead, fileSize);
|
||||||
progressDialog.updateProgress(totalBytesRead, contentLength);
|
|
||||||
lastUpdate = currentTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFrame(ActionEvent e) {
|
connection.disconnect();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeEvent() {
|
private void closeEvent() {
|
||||||
stopCamera();
|
if (cap != null) {
|
||||||
|
cap.release();
|
||||||
|
}
|
||||||
|
|
||||||
if (detectionThread != null) {
|
if (detectionThread != null) {
|
||||||
detectionThread.stopDetection();
|
detectionThread.stopDetection();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (executorService != null) {
|
if (executorService != null) {
|
||||||
executorService.shutdown();
|
executorService.shutdownNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main method
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try {
|
try {
|
||||||
|
// Set system look and feel
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
System.out.println("Could not set system look and feel: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
CameraApp app = new CameraApp();
|
try {
|
||||||
app.setVisible(true);
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
80
src/main/resources/coco.names
Normal file
80
src/main/resources/coco.names
Normal 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
|
||||||
294
src/main/resources/yolov4-tiny.cfg
Normal file
294
src/main/resources/yolov4-tiny.cfg
Normal 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
|
||||||
BIN
src/main/resources/yolov4-tiny.weights
Normal file
BIN
src/main/resources/yolov4-tiny.weights
Normal file
Binary file not shown.
Reference in New Issue
Block a user