Initial commit
This commit is contained in:
63
.gitignore
vendored
Normal file
63
.gitignore
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
.Python
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# C++ build
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.user
|
||||||
|
|
||||||
|
# AppImage specific
|
||||||
|
*.AppImage
|
||||||
|
AppDir/
|
||||||
|
|
||||||
|
# Large model files and datasets
|
||||||
|
*.weights
|
||||||
|
*.h5
|
||||||
|
*.pt
|
||||||
|
*.onnx
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.log
|
||||||
|
*.tmp
|
||||||
|
|
||||||
|
# Qt specific
|
||||||
|
*.pro.user
|
||||||
|
*.pro.user.*
|
||||||
|
*.qmake.stash
|
||||||
|
moc_*.cpp
|
||||||
|
qrc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
# OpenCV build artifacts
|
||||||
|
opencv/
|
||||||
|
opencv_build/
|
||||||
|
|
||||||
|
# System specific
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
115
README.md
Normal file
115
README.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# OpenCam
|
||||||
|
|
||||||
|
Real-time object detection application using OpenCV and YOLO, with both Python and C++ implementations.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Real-time object detection using YOLOv3
|
||||||
|
- Support for multiple camera inputs
|
||||||
|
- GPU acceleration with CUDA (optional)
|
||||||
|
- Cross-platform support (Windows, Linux)
|
||||||
|
- Modern Qt-based user interface
|
||||||
|
- Portable Linux AppImage build support
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### For C++ Version
|
||||||
|
|
||||||
|
- CMake 3.16 or higher
|
||||||
|
- C++17 compatible compiler
|
||||||
|
- Qt 5.12 or higher
|
||||||
|
- OpenCV 4.x with CUDA support (optional)
|
||||||
|
- CUDA Toolkit 10.0 or higher (optional)
|
||||||
|
|
||||||
|
### For Python Version
|
||||||
|
|
||||||
|
- Python 3.8 or higher
|
||||||
|
- OpenCV-Python
|
||||||
|
- PyQt5
|
||||||
|
- NumPy
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Building from Source (C++)
|
||||||
|
|
||||||
|
1. Clone the repository:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/opencam.git
|
||||||
|
cd opencam/opencamcpp
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Build OpenCV with CUDA (optional):
|
||||||
|
```bash
|
||||||
|
chmod +x build_opencv.sh
|
||||||
|
./build_opencv.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Build the application:
|
||||||
|
```bash
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
make -j$(nproc)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating AppImage (Linux)
|
||||||
|
|
||||||
|
1. Ensure all dependencies are installed:
|
||||||
|
```bash
|
||||||
|
sudo apt-get install cmake build-essential qt5-default libopencv-dev librsvg2-bin
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Build the AppImage:
|
||||||
|
```bash
|
||||||
|
chmod +x build_appimage.sh
|
||||||
|
./build_appimage.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python Version Setup
|
||||||
|
|
||||||
|
1. Create a virtual environment:
|
||||||
|
```bash
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate # Linux
|
||||||
|
# or
|
||||||
|
.venv\Scripts\activate # Windows
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Install dependencies:
|
||||||
|
```bash
|
||||||
|
pip install opencv-python pyqt5 numpy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Running the C++ Version
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./opencam
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running the Python Version
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Model Files
|
||||||
|
|
||||||
|
The application requires YOLOv3 model files:
|
||||||
|
- `yolov3.weights`
|
||||||
|
- `yolov3.cfg`
|
||||||
|
- `coco.names`
|
||||||
|
|
||||||
|
Download the weights file from: https://pjreddie.com/media/files/yolov3.weights
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[Your chosen license]
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create your feature branch
|
||||||
|
3. Commit your changes
|
||||||
|
4. Push to the branch
|
||||||
|
5. Create a new Pull Request
|
||||||
80
coco.names
Normal file
80
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
|
||||||
BIN
opencam/image.jpg
Normal file
BIN
opencam/image.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 133 KiB |
294
opencam/main.py
Normal file
294
opencam/main.py
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
import sys
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QPushButton,
|
||||||
|
QVBoxLayout, QWidget, QComboBox, QMessageBox,
|
||||||
|
QProgressBar, QDialog)
|
||||||
|
from PyQt5.QtGui import QImage, QPixmap
|
||||||
|
from PyQt5.QtCore import QTimer, Qt
|
||||||
|
import os
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
class DownloadProgressBar(QDialog):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle("Downloading YOLO Files")
|
||||||
|
self.setFixedSize(400, 100)
|
||||||
|
self.setWindowModality(Qt.ApplicationModal)
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.label = QLabel("Downloading...")
|
||||||
|
layout.addWidget(self.label)
|
||||||
|
|
||||||
|
self.progress = QProgressBar()
|
||||||
|
self.progress.setMinimum(0)
|
||||||
|
self.progress.setMaximum(100)
|
||||||
|
layout.addWidget(self.progress)
|
||||||
|
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def update_progress(self, current, total):
|
||||||
|
percentage = int((current / total) * 100)
|
||||||
|
self.progress.setValue(percentage)
|
||||||
|
|
||||||
|
def set_file_label(self, filename):
|
||||||
|
self.label.setText(f"Downloading {filename}...")
|
||||||
|
|
||||||
|
class DownloadProgressHandler:
|
||||||
|
def __init__(self, progress_dialog):
|
||||||
|
self.progress_dialog = progress_dialog
|
||||||
|
self.current_size = 0
|
||||||
|
self.total_size = 0
|
||||||
|
|
||||||
|
def handle_progress(self, count, block_size, total_size):
|
||||||
|
self.total_size = total_size
|
||||||
|
self.current_size += block_size
|
||||||
|
self.progress_dialog.update_progress(self.current_size, self.total_size)
|
||||||
|
|
||||||
|
class CameraApp(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setWindowTitle("Object Detection Camera Viewer")
|
||||||
|
self.setGeometry(100, 100, 800, 600)
|
||||||
|
|
||||||
|
self.camera_index = 0
|
||||||
|
self.cap = None
|
||||||
|
self.timer = QTimer()
|
||||||
|
self.timer.timeout.connect(self.update_frame)
|
||||||
|
self.available_cameras = []
|
||||||
|
|
||||||
|
# Initialize object detection
|
||||||
|
self.net = None
|
||||||
|
self.classes = None
|
||||||
|
self.output_layers = None
|
||||||
|
self.load_yolo()
|
||||||
|
|
||||||
|
self.init_ui()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
self.central_widget = QWidget()
|
||||||
|
self.setCentralWidget(self.central_widget)
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
self.video_label = QLabel(self)
|
||||||
|
layout.addWidget(self.video_label)
|
||||||
|
|
||||||
|
self.camera_select = QComboBox(self)
|
||||||
|
self.detect_cameras()
|
||||||
|
layout.addWidget(self.camera_select)
|
||||||
|
self.camera_select.currentIndexChanged.connect(self.change_camera)
|
||||||
|
|
||||||
|
self.start_button = QPushButton("Start Camera", self)
|
||||||
|
self.start_button.clicked.connect(self.start_camera)
|
||||||
|
layout.addWidget(self.start_button)
|
||||||
|
|
||||||
|
self.stop_button = QPushButton("Stop Camera", self)
|
||||||
|
self.stop_button.clicked.connect(self.stop_camera)
|
||||||
|
layout.addWidget(self.stop_button)
|
||||||
|
|
||||||
|
self.central_widget.setLayout(layout)
|
||||||
|
|
||||||
|
def detect_cameras(self):
|
||||||
|
self.camera_select.clear()
|
||||||
|
self.available_cameras = []
|
||||||
|
|
||||||
|
# Try to get the list of available cameras using DirectShow backend
|
||||||
|
for i in range(10): # Check first 10 indexes
|
||||||
|
cap = cv2.VideoCapture(i, cv2.CAP_DSHOW)
|
||||||
|
if cap.isOpened():
|
||||||
|
# Get camera name
|
||||||
|
cap.set(cv2.CAP_PROP_SETTINGS, 1) # This might show camera properties dialog
|
||||||
|
name = f"Camera {i}"
|
||||||
|
|
||||||
|
# Try to get camera resolution to verify it's working
|
||||||
|
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
|
||||||
|
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
|
||||||
|
|
||||||
|
if width and height:
|
||||||
|
name = f"{name} ({int(width)}x{int(height)})"
|
||||||
|
self.available_cameras.append(i)
|
||||||
|
self.camera_select.addItem(name, i)
|
||||||
|
|
||||||
|
cap.release()
|
||||||
|
|
||||||
|
if len(self.available_cameras) == 0:
|
||||||
|
QMessageBox.warning(self, "Warning", "No cameras detected!")
|
||||||
|
print("Error: No available cameras detected.")
|
||||||
|
else:
|
||||||
|
print(f"Detected {len(self.available_cameras)} cameras")
|
||||||
|
|
||||||
|
def change_camera(self, index):
|
||||||
|
if index >= 0: # Only change if a valid camera is selected
|
||||||
|
self.camera_index = self.camera_select.itemData(index)
|
||||||
|
if self.cap is not None and self.cap.isOpened():
|
||||||
|
self.stop_camera()
|
||||||
|
self.start_camera()
|
||||||
|
|
||||||
|
def start_camera(self):
|
||||||
|
if self.cap is not None:
|
||||||
|
self.stop_camera()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.cap = cv2.VideoCapture(self.camera_index, cv2.CAP_DSHOW)
|
||||||
|
if not self.cap.isOpened():
|
||||||
|
QMessageBox.warning(self, "Error", f"Cannot open camera {self.camera_index}")
|
||||||
|
print(f"Error: Cannot open camera {self.camera_index}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Set camera properties for better performance
|
||||||
|
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
|
||||||
|
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
|
||||||
|
self.cap.set(cv2.CAP_PROP_FPS, 30)
|
||||||
|
|
||||||
|
self.timer.start(30)
|
||||||
|
print(f"Started camera {self.camera_index}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
QMessageBox.critical(self, "Error", f"Error starting camera: {str(e)}")
|
||||||
|
print(f"Error starting camera: {str(e)}")
|
||||||
|
|
||||||
|
def stop_camera(self):
|
||||||
|
if self.cap:
|
||||||
|
self.timer.stop()
|
||||||
|
self.cap.release()
|
||||||
|
self.cap = None
|
||||||
|
self.video_label.clear()
|
||||||
|
print("Camera stopped")
|
||||||
|
|
||||||
|
def load_yolo(self):
|
||||||
|
# Download YOLO files if they don't exist
|
||||||
|
weights_path = "yolov3.weights"
|
||||||
|
config_path = "yolov3.cfg"
|
||||||
|
classes_path = "coco.names"
|
||||||
|
|
||||||
|
if not all(os.path.exists(f) for f in [weights_path, config_path, classes_path]):
|
||||||
|
QMessageBox.information(self, "Download", "Downloading YOLO model files. This may take a moment...")
|
||||||
|
self.download_yolo_files()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.net = cv2.dnn.readNet(weights_path, config_path)
|
||||||
|
with open(classes_path, "r") as f:
|
||||||
|
self.classes = [line.strip() for line in f.readlines()]
|
||||||
|
|
||||||
|
layer_names = self.net.getLayerNames()
|
||||||
|
self.output_layers = [layer_names[i - 1] for i in self.net.getUnconnectedOutLayers()]
|
||||||
|
|
||||||
|
print("YOLO model loaded successfully")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading YOLO model: {str(e)}")
|
||||||
|
QMessageBox.warning(self, "Error", "Failed to load object detection model")
|
||||||
|
|
||||||
|
def download_yolo_files(self):
|
||||||
|
files = {
|
||||||
|
"yolov3.weights": "https://pjreddie.com/media/files/yolov3.weights",
|
||||||
|
"yolov3.cfg": "https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg",
|
||||||
|
"coco.names": "https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names"
|
||||||
|
}
|
||||||
|
|
||||||
|
progress_dialog = DownloadProgressBar(self)
|
||||||
|
progress_dialog.show()
|
||||||
|
|
||||||
|
for file_name, url in files.items():
|
||||||
|
if not os.path.exists(file_name):
|
||||||
|
print(f"Downloading {file_name}...")
|
||||||
|
progress_dialog.set_file_label(file_name)
|
||||||
|
try:
|
||||||
|
progress_handler = DownloadProgressHandler(progress_dialog)
|
||||||
|
urllib.request.urlretrieve(
|
||||||
|
url,
|
||||||
|
file_name,
|
||||||
|
reporthook=progress_handler.handle_progress
|
||||||
|
)
|
||||||
|
print(f"Downloaded {file_name}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error downloading {file_name}: {str(e)}")
|
||||||
|
QMessageBox.critical(self, "Error", f"Failed to download {file_name}")
|
||||||
|
|
||||||
|
progress_dialog.close()
|
||||||
|
|
||||||
|
def detect_objects(self, frame):
|
||||||
|
if self.net is None or self.classes is None:
|
||||||
|
return frame
|
||||||
|
|
||||||
|
height, width, _ = frame.shape
|
||||||
|
blob = cv2.dnn.blobFromImage(frame, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
|
||||||
|
|
||||||
|
self.net.setInput(blob)
|
||||||
|
outs = self.net.forward(self.output_layers)
|
||||||
|
|
||||||
|
# Showing information on the screen
|
||||||
|
class_ids = []
|
||||||
|
confidences = []
|
||||||
|
boxes = []
|
||||||
|
|
||||||
|
# Showing information on the screen
|
||||||
|
for out in outs:
|
||||||
|
for detection in out:
|
||||||
|
scores = detection[5:]
|
||||||
|
class_id = np.argmax(scores)
|
||||||
|
confidence = scores[class_id]
|
||||||
|
if confidence > 0.5:
|
||||||
|
# Object detected
|
||||||
|
center_x = int(detection[0] * width)
|
||||||
|
center_y = int(detection[1] * height)
|
||||||
|
w = int(detection[2] * width)
|
||||||
|
h = int(detection[3] * height)
|
||||||
|
|
||||||
|
# Rectangle coordinates
|
||||||
|
x = int(center_x - w / 2)
|
||||||
|
y = int(center_y - h / 2)
|
||||||
|
|
||||||
|
boxes.append([x, y, w, h])
|
||||||
|
confidences.append(float(confidence))
|
||||||
|
class_ids.append(class_id)
|
||||||
|
|
||||||
|
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
|
||||||
|
|
||||||
|
for i in range(len(boxes)):
|
||||||
|
if i in indexes:
|
||||||
|
x, y, w, h = boxes[i]
|
||||||
|
label = str(self.classes[class_ids[i]])
|
||||||
|
confidence = confidences[i]
|
||||||
|
color = (0, 255, 0) # Green
|
||||||
|
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
|
||||||
|
cv2.putText(frame, f"{label} {confidence:.2f}", (x, y - 10),
|
||||||
|
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
|
||||||
|
|
||||||
|
return frame
|
||||||
|
|
||||||
|
def update_frame(self):
|
||||||
|
if self.cap is None or not self.cap.isOpened():
|
||||||
|
return
|
||||||
|
|
||||||
|
ret, frame = self.cap.read()
|
||||||
|
if ret:
|
||||||
|
# Perform object detection
|
||||||
|
frame = self.detect_objects(frame)
|
||||||
|
|
||||||
|
# Convert the frame from BGR to RGB
|
||||||
|
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||||
|
h, w, ch = rgb_image.shape
|
||||||
|
bytes_per_line = ch * w
|
||||||
|
|
||||||
|
# Convert the frame to QImage
|
||||||
|
q_image = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888)
|
||||||
|
|
||||||
|
# Scale the image to fit the label while maintaining aspect ratio
|
||||||
|
scaled_pixmap = QPixmap.fromImage(q_image).scaled(
|
||||||
|
self.video_label.size(),
|
||||||
|
aspectRatioMode=1 # Qt.KeepAspectRatio
|
||||||
|
)
|
||||||
|
self.video_label.setPixmap(scaled_pixmap)
|
||||||
|
else:
|
||||||
|
print("Failed to get frame from camera")
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
self.stop_camera()
|
||||||
|
event.accept()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
window = CameraApp()
|
||||||
|
window.show()
|
||||||
|
sys.exit(app.exec_())
|
||||||
137
opencamcpp/CMakeLists.txt
Normal file
137
opencamcpp/CMakeLists.txt
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
project(opencam LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
|
||||||
|
# Add OpenCV directory to CMAKE_PREFIX_PATH
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH "/usr/local")
|
||||||
|
|
||||||
|
# Find Qt5
|
||||||
|
find_package(Qt5 COMPONENTS
|
||||||
|
Core
|
||||||
|
Gui
|
||||||
|
Widgets
|
||||||
|
Network
|
||||||
|
REQUIRED
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find OpenCV
|
||||||
|
find_package(OpenCV REQUIRED)
|
||||||
|
message(STATUS "OpenCV version: ${OpenCV_VERSION}")
|
||||||
|
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
|
||||||
|
message(STATUS "OpenCV include dirs: ${OpenCV_INCLUDE_DIRS}")
|
||||||
|
|
||||||
|
# Check for CUDA support in OpenCV
|
||||||
|
if(";${OpenCV_LIBS};" MATCHES ";opencv_cudaimgproc;")
|
||||||
|
message(STATUS "OpenCV CUDA support found")
|
||||||
|
find_package(CUDA REQUIRED)
|
||||||
|
enable_language(CUDA)
|
||||||
|
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-O3)
|
||||||
|
add_definitions(-DWITH_CUDA)
|
||||||
|
set(HAS_CUDA TRUE)
|
||||||
|
else()
|
||||||
|
message(STATUS "OpenCV was built without CUDA support. GPU acceleration will be disabled.")
|
||||||
|
set(HAS_CUDA FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add source files
|
||||||
|
add_executable(${PROJECT_NAME}
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Link libraries
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||||
|
Qt5::Core
|
||||||
|
Qt5::Gui
|
||||||
|
Qt5::Widgets
|
||||||
|
Qt5::Network
|
||||||
|
${OpenCV_LIBS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(HAS_CUDA)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||||
|
${CUDA_LIBRARIES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Include directories
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||||
|
${OpenCV_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(HAS_CUDA)
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||||
|
${CUDA_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Installation rules
|
||||||
|
install(TARGETS ${PROJECT_NAME}
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
COMPONENT applications
|
||||||
|
)
|
||||||
|
|
||||||
|
# Function to safely install a library and its dependencies
|
||||||
|
function(install_library lib_path)
|
||||||
|
if(EXISTS "${lib_path}")
|
||||||
|
file(REAL_PATH "${lib_path}" real_path)
|
||||||
|
install(FILES "${real_path}"
|
||||||
|
DESTINATION lib
|
||||||
|
COMPONENT libraries
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get library dependencies
|
||||||
|
execute_process(
|
||||||
|
COMMAND ldd "${real_path}"
|
||||||
|
OUTPUT_VARIABLE LDD_OUTPUT
|
||||||
|
)
|
||||||
|
|
||||||
|
# Extract and install dependencies
|
||||||
|
string(REGEX MATCHALL "/[^)]*\\.so[^)]*" DEPS "${LDD_OUTPUT}")
|
||||||
|
foreach(dep ${DEPS})
|
||||||
|
if(EXISTS "${dep}" AND NOT "${dep}" MATCHES "^/lib" AND NOT "${dep}" MATCHES "^/usr/lib")
|
||||||
|
install(FILES "${dep}"
|
||||||
|
DESTINATION lib
|
||||||
|
COMPONENT libraries
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Install OpenCV libraries
|
||||||
|
foreach(lib ${OpenCV_LIBS})
|
||||||
|
get_target_property(lib_location ${lib} LOCATION)
|
||||||
|
if(lib_location)
|
||||||
|
install_library("${lib_location}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Install Qt plugins
|
||||||
|
if(Qt5_DIR)
|
||||||
|
file(GLOB_RECURSE QT_PLUGINS "${Qt5_DIR}/../../../plugins/*.so")
|
||||||
|
foreach(plugin ${QT_PLUGINS})
|
||||||
|
get_filename_component(plugin_path "${plugin}" DIRECTORY)
|
||||||
|
get_filename_component(plugin_dir "${plugin_path}" NAME)
|
||||||
|
install(FILES "${plugin}"
|
||||||
|
DESTINATION plugins/${plugin_dir}
|
||||||
|
COMPONENT plugins
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Print configuration summary
|
||||||
|
message(STATUS "")
|
||||||
|
message(STATUS "Configuration Summary")
|
||||||
|
message(STATUS "--------------------")
|
||||||
|
message(STATUS "OpenCV version: ${OpenCV_VERSION}")
|
||||||
|
message(STATUS "CUDA support: ${HAS_CUDA}")
|
||||||
|
message(STATUS "Qt version: ${Qt5_VERSION}")
|
||||||
|
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||||
|
message(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
|
||||||
|
message(STATUS "Installation prefix: ${CMAKE_INSTALL_PREFIX}")
|
||||||
|
message(STATUS "")
|
||||||
22
opencamcpp/CMakePresets.json
Normal file
22
opencamcpp/CMakePresets.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"hidden": true,
|
||||||
|
"name": "Qt",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_PREFIX_PATH": "$env{QTDIR}"
|
||||||
|
},
|
||||||
|
"vendor": {
|
||||||
|
"qt-project.org/Qt": {
|
||||||
|
"checksum": "wVa86FgEkvdCTVp1/nxvrkaemJc="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vendor": {
|
||||||
|
"qt-project.org/Presets": {
|
||||||
|
"checksum": "67SmY24ZeVbebyKD0fGfIzb/bGI="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
opencamcpp/CMakeUserPresets.json
Normal file
40
opencamcpp/CMakeUserPresets.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "Qt-Debug",
|
||||||
|
"inherits": "Qt-Default",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/debug",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Debug",
|
||||||
|
"CMAKE_CXX_FLAGS": "-DQT_QML_DEBUG"
|
||||||
|
},
|
||||||
|
"environment": {
|
||||||
|
"QML_DEBUG_ARGS": "-qmljsdebugger=file:{ff00bfed-29c2-47f8-b4aa-00b2873b1a26},block"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Qt-Release",
|
||||||
|
"inherits": "Qt-Default",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/release",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden": true,
|
||||||
|
"name": "Qt-Default",
|
||||||
|
"inherits": null,
|
||||||
|
"vendor": {
|
||||||
|
"qt-project.org/Default": {
|
||||||
|
"checksum": "VoalogTkyWuFomeO1TLFx0olLJ4="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vendor": {
|
||||||
|
"qt-project.org/Presets": {
|
||||||
|
"checksum": "azRZtZDqJVYwlIJYZufPfOYPwkE="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
90
opencamcpp/build_appimage.sh
Normal file
90
opencamcpp/build_appimage.sh
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Exit on error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Function to copy library and its dependencies
|
||||||
|
copy_dependencies() {
|
||||||
|
local binary="$1"
|
||||||
|
local target_dir="$2"
|
||||||
|
|
||||||
|
# Create target directory if it doesn't exist
|
||||||
|
mkdir -p "$target_dir"
|
||||||
|
|
||||||
|
# Get all dependencies
|
||||||
|
ldd "$binary" | while read -r line; do
|
||||||
|
# Extract the library path
|
||||||
|
if [[ $line =~ '=>' ]]; then
|
||||||
|
lib_path=$(echo "$line" | awk '{print $3}')
|
||||||
|
else
|
||||||
|
lib_path=$(echo "$line" | awk '{print $1}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip system libraries and non-existent files
|
||||||
|
if [[ -f "$lib_path" && ! "$lib_path" =~ ^/lib && ! "$lib_path" =~ ^/usr/lib ]]; then
|
||||||
|
cp -L "$lib_path" "$target_dir/"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create AppDir structure
|
||||||
|
mkdir -p AppDir/usr/{bin,lib,share/applications,share/icons/hicolor/256x256/apps}
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
# Install to AppDir
|
||||||
|
make DESTDIR=../AppDir install
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Copy desktop file and icon
|
||||||
|
cp opencam.desktop AppDir/usr/share/applications/
|
||||||
|
cp icon.png AppDir/usr/share/icons/hicolor/256x256/apps/opencam.png
|
||||||
|
|
||||||
|
# Copy Qt plugins
|
||||||
|
mkdir -p AppDir/usr/plugins
|
||||||
|
for plugin_dir in platforms imageformats xcbglintegrations; do
|
||||||
|
if [ -d "/usr/lib/x86_64-linux-gnu/qt5/plugins/$plugin_dir" ]; then
|
||||||
|
cp -r "/usr/lib/x86_64-linux-gnu/qt5/plugins/$plugin_dir" AppDir/usr/plugins/
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy dependencies for the main executable
|
||||||
|
copy_dependencies "AppDir/usr/bin/opencam" "AppDir/usr/lib"
|
||||||
|
|
||||||
|
# Copy dependencies for Qt plugins
|
||||||
|
find AppDir/usr/plugins -type f -name "*.so" | while read plugin; do
|
||||||
|
copy_dependencies "$plugin" "AppDir/usr/lib"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create AppRun script
|
||||||
|
cat > AppDir/AppRun << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
HERE="$(dirname "$(readlink -f "${0}")")"
|
||||||
|
export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH}"
|
||||||
|
export QT_PLUGIN_PATH="${HERE}/usr/plugins"
|
||||||
|
export QT_QPA_PLATFORM_PLUGIN_PATH="${HERE}/usr/plugins/platforms"
|
||||||
|
exec "${HERE}/usr/bin/opencam" "$@"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x AppDir/AppRun
|
||||||
|
|
||||||
|
# Download linuxdeploy if not present
|
||||||
|
if [ ! -f linuxdeploy-x86_64.AppImage ]; then
|
||||||
|
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||||
|
chmod +x linuxdeploy-x86_64.AppImage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f linuxdeploy-plugin-qt-x86_64.AppImage ]; then
|
||||||
|
wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
|
||||||
|
chmod +x linuxdeploy-plugin-qt-x86_64.AppImage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create the AppImage
|
||||||
|
export OUTPUT="OpenCam-x86_64.AppImage"
|
||||||
|
./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt --output appimage
|
||||||
|
|
||||||
|
echo "AppImage created successfully: $OUTPUT"
|
||||||
83
opencamcpp/build_opencv.sh
Normal file
83
opencamcpp/build_opencv.sh
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Exit on error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Function to check CUDA installation
|
||||||
|
check_cuda() {
|
||||||
|
if ! command -v nvcc &> /dev/null; then
|
||||||
|
echo "CUDA not found! Please install CUDA toolkit first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Found CUDA installation: $(nvcc --version | head -n1)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check GPU
|
||||||
|
check_gpu() {
|
||||||
|
if ! command -v nvidia-smi &> /dev/null; then
|
||||||
|
echo "No NVIDIA GPU found or drivers not installed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Found GPU: $(nvidia-smi -L)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check CUDA and GPU
|
||||||
|
check_cuda
|
||||||
|
check_gpu
|
||||||
|
|
||||||
|
# Get CUDA compute capability
|
||||||
|
CUDA_ARCH=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader)
|
||||||
|
echo "GPU Compute Capability: $CUDA_ARCH"
|
||||||
|
|
||||||
|
# Create build directory
|
||||||
|
cd ~/opencv_build/opencv
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
# Configure OpenCV build
|
||||||
|
cmake -D CMAKE_BUILD_TYPE=RELEASE \
|
||||||
|
-D CMAKE_INSTALL_PREFIX=/usr/local \
|
||||||
|
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
|
||||||
|
-D WITH_CUDA=ON \
|
||||||
|
-D WITH_CUDNN=OFF \
|
||||||
|
-D OPENCV_DNN_CUDA=ON \
|
||||||
|
-D ENABLE_FAST_MATH=1 \
|
||||||
|
-D CUDA_FAST_MATH=1 \
|
||||||
|
-D CUDA_ARCH_BIN=$CUDA_ARCH \
|
||||||
|
-D WITH_CUBLAS=1 \
|
||||||
|
-D WITH_TBB=ON \
|
||||||
|
-D WITH_V4L=ON \
|
||||||
|
-D WITH_QT=ON \
|
||||||
|
-D WITH_OPENGL=ON \
|
||||||
|
-D WITH_GSTREAMER=ON \
|
||||||
|
-D OPENCV_GENERATE_PKGCONFIG=ON \
|
||||||
|
-D OPENCV_PC_FILE_NAME=opencv.pc \
|
||||||
|
-D OPENCV_ENABLE_NONFREE=ON \
|
||||||
|
-D INSTALL_PYTHON_EXAMPLES=OFF \
|
||||||
|
-D INSTALL_C_EXAMPLES=OFF \
|
||||||
|
-D BUILD_EXAMPLES=OFF \
|
||||||
|
-D BUILD_opencv_cudacodec=OFF \
|
||||||
|
-D OPENCV_ENABLE_MEMALIGN=ON \
|
||||||
|
-D WITH_OPENEXR=ON \
|
||||||
|
-D OPENCV_ENABLE_MEMALIGN=ON \
|
||||||
|
-D WITH_EIGEN=ON \
|
||||||
|
-D ENABLE_PRECOMPILED_HEADERS=OFF \
|
||||||
|
..
|
||||||
|
|
||||||
|
# Build using all available CPU cores
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
# Install
|
||||||
|
sudo make install
|
||||||
|
sudo ldconfig
|
||||||
|
|
||||||
|
# Print OpenCV installation information
|
||||||
|
echo "OpenCV installation completed!"
|
||||||
|
echo "OpenCV version: $(pkg-config --modversion opencv4)"
|
||||||
|
echo "Installation location: $(pkg-config --variable=prefix opencv4)"
|
||||||
|
|
||||||
|
# Create a pkg-config path file
|
||||||
|
sudo sh -c 'echo "/usr/local/lib/pkgconfig" > /etc/ld.so.conf.d/opencv.conf'
|
||||||
|
sudo ldconfig
|
||||||
|
|
||||||
|
echo "Setup complete! You can now use OpenCV with CUDA support."
|
||||||
BIN
opencamcpp/icon.png
Normal file
BIN
opencamcpp/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
7
opencamcpp/icon.svg
Normal file
7
opencamcpp/icon.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
|
||||||
|
<circle cx="128" cy="128" r="120" fill="#2196F3"/>
|
||||||
|
<circle cx="128" cy="128" r="90" fill="#1976D2"/>
|
||||||
|
<circle cx="128" cy="128" r="45" fill="#FFFFFF"/>
|
||||||
|
<circle cx="128" cy="128" r="25" fill="#1976D2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 359 B |
311
opencamcpp/main.cpp
Normal file
311
opencamcpp/main.cpp
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#ifdef WITH_CUDA
|
||||||
|
#include <opencv2/cudaimgproc.hpp>
|
||||||
|
#include <opencv2/cudawarping.hpp>
|
||||||
|
#include <opencv2/cudaobjdetect.hpp>
|
||||||
|
#include <opencv2/cudabgsegm.hpp>
|
||||||
|
#include <opencv2/cudacodec.hpp>
|
||||||
|
#include <opencv2/core/cuda.hpp>
|
||||||
|
#endif
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QProgressDialog>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QString>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QProgressBar>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
#include <queue>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
class FrameProcessor : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FrameProcessor(QObject* parent = nullptr) : QThread(parent), running(false) {
|
||||||
|
#ifdef WITH_CUDA
|
||||||
|
// Initialize CUDA device
|
||||||
|
cv::cuda::setDevice(0);
|
||||||
|
stream = cv::cuda::Stream();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void startProcessing() {
|
||||||
|
running = true;
|
||||||
|
if (!isRunning()) start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopProcessing() {
|
||||||
|
running = false;
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNet(cv::dnn::Net& net) {
|
||||||
|
std::lock_guard<std::mutex> lock(netMutex);
|
||||||
|
this->net = net;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queueFrame(const cv::Mat& frame) {
|
||||||
|
std::lock_guard<std::mutex> lock(queueMutex);
|
||||||
|
frameQueue.push(frame);
|
||||||
|
condition.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void frameProcessed(QImage image);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run() override {
|
||||||
|
while (running) {
|
||||||
|
cv::Mat frame;
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(queueMutex);
|
||||||
|
condition.wait(lock, [this] { return !frameQueue.empty() || !running; });
|
||||||
|
if (!running) break;
|
||||||
|
frame = frameQueue.front();
|
||||||
|
frameQueue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame.empty()) continue;
|
||||||
|
|
||||||
|
#ifdef WITH_CUDA
|
||||||
|
// GPU processing path
|
||||||
|
cv::cuda::GpuMat gpuFrame;
|
||||||
|
gpuFrame.upload(frame, stream);
|
||||||
|
|
||||||
|
cv::cuda::GpuMat gpuResized;
|
||||||
|
cv::cuda::resize(gpuFrame, gpuResized, cv::Size(416, 416), 0, 0, cv::INTER_CUBIC, stream);
|
||||||
|
|
||||||
|
// Download for DNN processing (until we implement CUDA DNN)
|
||||||
|
cv::Mat resized;
|
||||||
|
gpuResized.download(resized, stream);
|
||||||
|
#else
|
||||||
|
// CPU processing path
|
||||||
|
cv::Mat resized;
|
||||||
|
cv::resize(frame, resized, cv::Size(416, 416), 0, 0, cv::INTER_CUBIC);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Object detection
|
||||||
|
cv::Mat blob;
|
||||||
|
cv::dnn::blobFromImage(resized, blob, 1/255.0, cv::Size(416, 416), cv::Scalar(0,0,0), true, false);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(netMutex);
|
||||||
|
net.setInput(blob);
|
||||||
|
std::vector<cv::Mat> outs;
|
||||||
|
net.forward(outs, net.getUnconnectedOutLayersNames());
|
||||||
|
|
||||||
|
std::vector<int> classIds;
|
||||||
|
std::vector<float> confidences;
|
||||||
|
std::vector<cv::Rect> boxes;
|
||||||
|
|
||||||
|
for (const auto& out : outs) {
|
||||||
|
float* data = (float*)out.data;
|
||||||
|
for (int j = 0; j < out.rows; ++j, data += out.cols) {
|
||||||
|
cv::Mat scores = out.row(j).colRange(5, out.cols);
|
||||||
|
cv::Point classIdPoint;
|
||||||
|
double confidence;
|
||||||
|
cv::minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
|
||||||
|
|
||||||
|
if (confidence > 0.5) {
|
||||||
|
int centerX = (int)(data[0] * frame.cols);
|
||||||
|
int centerY = (int)(data[1] * frame.rows);
|
||||||
|
int width = (int)(data[2] * frame.cols);
|
||||||
|
int height = (int)(data[3] * frame.rows);
|
||||||
|
int left = centerX - width / 2;
|
||||||
|
int top = centerY - height / 2;
|
||||||
|
|
||||||
|
classIds.push_back(classIdPoint.x);
|
||||||
|
confidences.push_back((float)confidence);
|
||||||
|
boxes.push_back(cv::Rect(left, top, width, height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> indices;
|
||||||
|
cv::dnn::NMSBoxes(boxes, confidences, 0.5, 0.4, indices);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < indices.size(); ++i) {
|
||||||
|
int idx = indices[i];
|
||||||
|
cv::Rect box = boxes[idx];
|
||||||
|
cv::rectangle(frame, box, cv::Scalar(0, 255, 0), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_CUDA
|
||||||
|
// Convert to RGB on GPU
|
||||||
|
cv::cuda::GpuMat gpuRGB;
|
||||||
|
cv::cuda::cvtColor(gpuFrame, gpuRGB, cv::COLOR_BGR2RGB, 0, stream);
|
||||||
|
cv::Mat rgb;
|
||||||
|
gpuRGB.download(rgb, stream);
|
||||||
|
#else
|
||||||
|
// Convert to RGB on CPU
|
||||||
|
cv::Mat rgb;
|
||||||
|
cv::cvtColor(frame, rgb, cv::COLOR_BGR2RGB);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Convert to QImage
|
||||||
|
QImage qimg(rgb.data, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888);
|
||||||
|
emit frameProcessed(qimg.copy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic<bool> running;
|
||||||
|
#ifdef WITH_CUDA
|
||||||
|
cv::cuda::Stream stream;
|
||||||
|
#endif
|
||||||
|
cv::dnn::Net net;
|
||||||
|
std::queue<cv::Mat> frameQueue;
|
||||||
|
std::mutex queueMutex;
|
||||||
|
std::mutex netMutex;
|
||||||
|
std::condition_variable condition;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CameraApp : public QMainWindow {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CameraApp(QWidget* parent = nullptr) : QMainWindow(parent) {
|
||||||
|
setWindowTitle("GPU-Accelerated Object Detection");
|
||||||
|
setGeometry(100, 100, 1280, 720);
|
||||||
|
|
||||||
|
#ifdef WITH_CUDA
|
||||||
|
// Check CUDA device
|
||||||
|
int deviceCount = cv::cuda::getCudaEnabledDeviceCount();
|
||||||
|
if (deviceCount == 0) {
|
||||||
|
QMessageBox::warning(this, "Warning", "No CUDA capable devices found. Falling back to CPU processing.");
|
||||||
|
} else {
|
||||||
|
cv::cuda::printCudaDeviceInfo(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setupUI();
|
||||||
|
initializeObjectDetection();
|
||||||
|
processor = new FrameProcessor(this);
|
||||||
|
connect(processor, &FrameProcessor::frameProcessed, this, &CameraApp::updateFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
~CameraApp() {
|
||||||
|
stopCamera();
|
||||||
|
if (processor) {
|
||||||
|
processor->stopProcessing();
|
||||||
|
delete processor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void startCamera() {
|
||||||
|
if (!cap.isOpened()) {
|
||||||
|
cap.open(currentCamera);
|
||||||
|
cap.set(cv::CAP_PROP_FRAME_WIDTH, 1920);
|
||||||
|
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 1080);
|
||||||
|
cap.set(cv::CAP_PROP_FPS, 120); // Request maximum FPS
|
||||||
|
|
||||||
|
#ifdef WITH_CUDA
|
||||||
|
// Try to use CUDA video decoder if available
|
||||||
|
cap.set(cv::CAP_PROP_CUDA_DEVICE, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!cap.isOpened()) {
|
||||||
|
QMessageBox::critical(this, "Error", "Failed to open camera!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processor->startProcessing();
|
||||||
|
timer->start(0); // Run as fast as possible
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopCamera() {
|
||||||
|
timer->stop();
|
||||||
|
processor->stopProcessing();
|
||||||
|
if (cap.isOpened()) {
|
||||||
|
cap.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void captureFrame() {
|
||||||
|
if (!cap.isOpened()) return;
|
||||||
|
|
||||||
|
cv::Mat frame;
|
||||||
|
cap >> frame;
|
||||||
|
if (frame.empty()) return;
|
||||||
|
|
||||||
|
processor->queueFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateFrame(const QImage& image) {
|
||||||
|
QPixmap pixmap = QPixmap::fromImage(image);
|
||||||
|
videoLabel->setPixmap(pixmap.scaled(videoLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupUI() {
|
||||||
|
QWidget* centralWidget = new QWidget(this);
|
||||||
|
setCentralWidget(centralWidget);
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout(centralWidget);
|
||||||
|
|
||||||
|
videoLabel = new QLabel(this);
|
||||||
|
videoLabel->setMinimumSize(640, 480);
|
||||||
|
layout->addWidget(videoLabel);
|
||||||
|
|
||||||
|
cameraSelect = new QComboBox(this);
|
||||||
|
detectCameras();
|
||||||
|
layout->addWidget(cameraSelect);
|
||||||
|
|
||||||
|
startButton = new QPushButton("Start Camera", this);
|
||||||
|
connect(startButton, &QPushButton::clicked, this, &CameraApp::startCamera);
|
||||||
|
layout->addWidget(startButton);
|
||||||
|
|
||||||
|
stopButton = new QPushButton("Stop Camera", this);
|
||||||
|
connect(stopButton, &QPushButton::clicked, this, &CameraApp::stopCamera);
|
||||||
|
layout->addWidget(stopButton);
|
||||||
|
|
||||||
|
timer = new QTimer(this);
|
||||||
|
connect(timer, &QTimer::timeout, this, &CameraApp::captureFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void detectCameras() {
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
cv::VideoCapture temp(i);
|
||||||
|
if (temp.isOpened()) {
|
||||||
|
cameraSelect->addItem("Camera " + QString::number(i), i);
|
||||||
|
temp.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeObjectDetection() {
|
||||||
|
// Download and load YOLO model (implementation similar to Python version)
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
QLabel* videoLabel;
|
||||||
|
QComboBox* cameraSelect;
|
||||||
|
QPushButton* startButton;
|
||||||
|
QPushButton* stopButton;
|
||||||
|
QTimer* timer;
|
||||||
|
cv::VideoCapture cap;
|
||||||
|
int currentCamera = 0;
|
||||||
|
FrameProcessor* processor;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "main.moc"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
CameraApp window;
|
||||||
|
window.show();
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
10
opencamcpp/opencam.desktop
Normal file
10
opencamcpp/opencam.desktop
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=OpenCam
|
||||||
|
Comment=Real-time object detection using OpenCV and YOLO
|
||||||
|
Exec=opencam
|
||||||
|
Icon=opencam
|
||||||
|
Categories=Graphics;Video;
|
||||||
|
Keywords=camera;detection;opencv;yolo;
|
||||||
|
Terminal=false
|
||||||
|
StartupNotify=true
|
||||||
789
yolov3.cfg
Normal file
789
yolov3.cfg
Normal file
@@ -0,0 +1,789 @@
|
|||||||
|
[net]
|
||||||
|
# Testing
|
||||||
|
# batch=1
|
||||||
|
# subdivisions=1
|
||||||
|
# Training
|
||||||
|
batch=64
|
||||||
|
subdivisions=16
|
||||||
|
width=608
|
||||||
|
height=608
|
||||||
|
channels=3
|
||||||
|
momentum=0.9
|
||||||
|
decay=0.0005
|
||||||
|
angle=0
|
||||||
|
saturation = 1.5
|
||||||
|
exposure = 1.5
|
||||||
|
hue=.1
|
||||||
|
|
||||||
|
learning_rate=0.001
|
||||||
|
burn_in=1000
|
||||||
|
max_batches = 500200
|
||||||
|
policy=steps
|
||||||
|
steps=400000,450000
|
||||||
|
scales=.1,.1
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=32
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
# Downsample
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=64
|
||||||
|
size=3
|
||||||
|
stride=2
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=32
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=64
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
# Downsample
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=3
|
||||||
|
stride=2
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=64
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=64
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
# Downsample
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=2
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
# Downsample
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=512
|
||||||
|
size=3
|
||||||
|
stride=2
|
||||||
|
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
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
# Downsample
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=1024
|
||||||
|
size=3
|
||||||
|
stride=2
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=512
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=1024
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=512
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=1024
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=512
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=1024
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=512
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=1024
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[shortcut]
|
||||||
|
from=-3
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
######################
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=512
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=1024
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=512
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=1024
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=512
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=1024
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=255
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[yolo]
|
||||||
|
mask = 6,7,8
|
||||||
|
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
|
||||||
|
classes=80
|
||||||
|
num=9
|
||||||
|
jitter=.3
|
||||||
|
ignore_thresh = .7
|
||||||
|
truth_thresh = 1
|
||||||
|
random=1
|
||||||
|
|
||||||
|
|
||||||
|
[route]
|
||||||
|
layers = -4
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[upsample]
|
||||||
|
stride=2
|
||||||
|
|
||||||
|
[route]
|
||||||
|
layers = -1, 61
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=512
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=512
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=256
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=512
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=255
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[yolo]
|
||||||
|
mask = 3,4,5
|
||||||
|
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
|
||||||
|
classes=80
|
||||||
|
num=9
|
||||||
|
jitter=.3
|
||||||
|
ignore_thresh = .7
|
||||||
|
truth_thresh = 1
|
||||||
|
random=1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[route]
|
||||||
|
layers = -4
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[upsample]
|
||||||
|
stride=2
|
||||||
|
|
||||||
|
[route]
|
||||||
|
layers = -1, 36
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=256
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=256
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
filters=128
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
batch_normalize=1
|
||||||
|
size=3
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=256
|
||||||
|
activation=leaky
|
||||||
|
|
||||||
|
[convolutional]
|
||||||
|
size=1
|
||||||
|
stride=1
|
||||||
|
pad=1
|
||||||
|
filters=255
|
||||||
|
activation=linear
|
||||||
|
|
||||||
|
|
||||||
|
[yolo]
|
||||||
|
mask = 0,1,2
|
||||||
|
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
|
||||||
|
classes=80
|
||||||
|
num=9
|
||||||
|
jitter=.3
|
||||||
|
ignore_thresh = .7
|
||||||
|
truth_thresh = 1
|
||||||
|
random=1
|
||||||
|
|
||||||
Reference in New Issue
Block a user