initial
This commit is contained in:
0
mucapy/__init__.py
Normal file
0
mucapy/__init__.py
Normal file
498
mucapy/main.py
Normal file
498
mucapy/main.py
Normal file
@@ -0,0 +1,498 @@
|
||||
import os
|
||||
import sys
|
||||
import cv2
|
||||
import numpy as np
|
||||
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout,
|
||||
QWidget, QLabel, QPushButton, QComboBox, QSpinBox,
|
||||
QFileDialog, QMessageBox, QMenu, QAction, QMenuBar,
|
||||
QActionGroup, QSizePolicy, QGridLayout, QGroupBox)
|
||||
from PyQt5.QtCore import Qt, QTimer, QDir
|
||||
from PyQt5.QtGui import QImage, QPixmap
|
||||
|
||||
class MultiCamYOLODetector:
|
||||
def __init__(self):
|
||||
self.cameras = []
|
||||
self.net = None
|
||||
self.classes = []
|
||||
self.colors = []
|
||||
self.target_fps = 10
|
||||
self.last_frame_time = 0
|
||||
self.frame_interval = 1.0 / self.target_fps
|
||||
self.available_cameras = []
|
||||
self.model_dir = ""
|
||||
self.cuda_available = self.check_cuda()
|
||||
|
||||
def check_cuda(self):
|
||||
"""Check if CUDA is available"""
|
||||
try:
|
||||
count = cv2.cuda.getCudaEnabledDeviceCount()
|
||||
return count > 0
|
||||
except:
|
||||
return False
|
||||
|
||||
def scan_for_cameras(self, max_to_check=10):
|
||||
"""Check for available cameras on Linux with better error handling"""
|
||||
self.available_cameras = []
|
||||
|
||||
# Check standard video devices
|
||||
for i in range(max_to_check):
|
||||
try:
|
||||
cap = cv2.VideoCapture(i, cv2.CAP_V4L2)
|
||||
if cap.isOpened():
|
||||
self.available_cameras.append(str(i))
|
||||
cap.release()
|
||||
except:
|
||||
continue
|
||||
|
||||
# Also check direct device paths
|
||||
v4l_paths = [f"/dev/video{i}" for i in range(max_to_check)]
|
||||
v4l_paths += [f"/dev/v4l/video{i}" for i in range(max_to_check)]
|
||||
|
||||
for path in v4l_paths:
|
||||
if os.path.exists(path):
|
||||
try:
|
||||
cap = cv2.VideoCapture(path, cv2.CAP_V4L2)
|
||||
if cap.isOpened():
|
||||
if path not in self.available_cameras:
|
||||
self.available_cameras.append(path)
|
||||
cap.release()
|
||||
except:
|
||||
continue
|
||||
|
||||
return self.available_cameras
|
||||
|
||||
def load_yolo_model(self, model_dir):
|
||||
"""Load YOLO model from selected directory with better error handling"""
|
||||
self.model_dir = model_dir
|
||||
try:
|
||||
# Find model files in the directory
|
||||
weights = [f for f in os.listdir(model_dir) if f.endswith(('.weights', '.onnx'))]
|
||||
configs = [f for f in os.listdir(model_dir) if f.endswith('.cfg')]
|
||||
classes = [f for f in os.listdir(model_dir) if f.endswith('.names')]
|
||||
|
||||
if not weights or not configs or not classes:
|
||||
return False
|
||||
|
||||
# Use the first found files
|
||||
weights_path = os.path.join(model_dir, weights[0])
|
||||
config_path = os.path.join(model_dir, configs[0])
|
||||
classes_path = os.path.join(model_dir, classes[0])
|
||||
|
||||
self.net = cv2.dnn.readNet(weights_path, config_path)
|
||||
|
||||
# Set backend based on availability
|
||||
if self.cuda_available:
|
||||
try:
|
||||
self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
|
||||
self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
|
||||
except:
|
||||
# Fall back to CPU if CUDA fails
|
||||
self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
|
||||
self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
|
||||
else:
|
||||
self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
|
||||
self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
|
||||
|
||||
with open(classes_path, 'r') as f:
|
||||
self.classes = f.read().strip().split('\n')
|
||||
|
||||
np.random.seed(42)
|
||||
self.colors = np.random.randint(0, 255, size=(len(self.classes), 3), dtype='uint8')
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error loading YOLO model: {e}")
|
||||
return False
|
||||
|
||||
def connect_cameras(self, camera_paths):
|
||||
"""Connect to multiple cameras with better error handling"""
|
||||
self.disconnect_cameras()
|
||||
|
||||
for cam_path in camera_paths:
|
||||
try:
|
||||
if isinstance(cam_path, str) and cam_path.startswith('/dev/'):
|
||||
cap = cv2.VideoCapture(cam_path, cv2.CAP_V4L2)
|
||||
else:
|
||||
cap = cv2.VideoCapture(int(cam_path), cv2.CAP_V4L2)
|
||||
|
||||
if not cap.isOpened():
|
||||
print(f"Warning: Could not open camera {cam_path}")
|
||||
continue
|
||||
|
||||
# Try to set properties but continue if they fail
|
||||
try:
|
||||
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
|
||||
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
|
||||
cap.set(cv2.CAP_PROP_FPS, self.target_fps)
|
||||
cap.set(cv2.CAP_PROP_AUTOFOCUS, 0)
|
||||
cap.set(cv2.CAP_PROP_BUFFERSIZE, 2)
|
||||
except:
|
||||
pass
|
||||
|
||||
self.cameras.append((cam_path, cap))
|
||||
except Exception as e:
|
||||
print(f"Error opening camera {cam_path}: {e}")
|
||||
|
||||
return len(self.cameras) > 0
|
||||
|
||||
def disconnect_cameras(self):
|
||||
"""Disconnect all cameras"""
|
||||
for _, cam in self.cameras:
|
||||
try:
|
||||
cam.release()
|
||||
except:
|
||||
pass
|
||||
self.cameras = []
|
||||
|
||||
def get_detections(self, frame):
|
||||
"""Perform YOLO object detection on a frame with error handling"""
|
||||
if self.net is None:
|
||||
return frame
|
||||
|
||||
try:
|
||||
blob = cv2.dnn.blobFromImage(frame, 1/255.0, (416, 416), swapRB=True, crop=False)
|
||||
self.net.setInput(blob)
|
||||
|
||||
# Get output layer names compatible with different OpenCV versions
|
||||
try:
|
||||
layer_names = self.net.getLayerNames()
|
||||
output_layers = [layer_names[i - 1] for i in self.net.getUnconnectedOutLayers()]
|
||||
except:
|
||||
output_layers = self.net.getUnconnectedOutLayersNames()
|
||||
|
||||
outputs = self.net.forward(output_layers)
|
||||
|
||||
boxes = []
|
||||
confidences = []
|
||||
class_ids = []
|
||||
|
||||
for output in outputs:
|
||||
for detection in output:
|
||||
scores = detection[5:]
|
||||
class_id = np.argmax(scores)
|
||||
confidence = scores[class_id]
|
||||
|
||||
if confidence > 0.5:
|
||||
box = detection[0:4] * np.array([frame.shape[1], frame.shape[0],
|
||||
frame.shape[1], frame.shape[0]])
|
||||
(centerX, centerY, width, height) = box.astype('int')
|
||||
x = int(centerX - (width / 2))
|
||||
y = int(centerY - (height / 2))
|
||||
|
||||
boxes.append([x, y, int(width), int(height)])
|
||||
confidences.append(float(confidence))
|
||||
class_ids.append(class_id)
|
||||
|
||||
indices = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
|
||||
|
||||
if len(indices) > 0:
|
||||
for i in indices.flatten():
|
||||
(x, y, w, h) = boxes[i]
|
||||
color = [int(c) for c in self.colors[class_ids[i]]]
|
||||
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
|
||||
text = f"{self.classes[class_ids[i]]}: {confidences[i]:.2f}"
|
||||
cv2.putText(frame, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
|
||||
except Exception as e:
|
||||
print(f"Detection error: {e}")
|
||||
|
||||
return frame
|
||||
|
||||
def get_frames(self):
|
||||
"""Get frames from all cameras with error handling"""
|
||||
frames = []
|
||||
for i, (cam_path, cam) in enumerate(self.cameras):
|
||||
try:
|
||||
ret, frame = cam.read()
|
||||
if not ret:
|
||||
print(f"Warning: Could not read frame from camera {cam_path}")
|
||||
frame = np.zeros((720, 1280, 3), dtype=np.uint8)
|
||||
else:
|
||||
frame = self.get_detections(frame)
|
||||
frames.append(frame)
|
||||
except:
|
||||
frame = np.zeros((720, 1280, 3), dtype=np.uint8)
|
||||
frames.append(frame)
|
||||
|
||||
return frames
|
||||
|
||||
def get_frames(self):
|
||||
"""Get frames from all cameras with detections"""
|
||||
frames = []
|
||||
for i, (cam_path, cam) in enumerate(self.cameras):
|
||||
ret, frame = cam.read()
|
||||
if not ret:
|
||||
print(f"Warning: Could not read frame from camera {cam_path}")
|
||||
frame = np.zeros((720, 1280, 3), dtype=np.uint8)
|
||||
else:
|
||||
frame = self.get_detections(frame)
|
||||
frames.append(frame)
|
||||
return frames
|
||||
|
||||
class CameraDisplay(QLabel):
|
||||
"""Custom QLabel for displaying camera feed"""
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setAlignment(Qt.AlignCenter)
|
||||
self.setText("No camera feed")
|
||||
self.setStyleSheet("background-color: black; color: white;")
|
||||
self.setMinimumSize(320, 240)
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("Multi-Camera YOLO Detection")
|
||||
self.setGeometry(100, 100, 1200, 800)
|
||||
|
||||
self.detector = MultiCamYOLODetector()
|
||||
self.camera_settings = {} # Store camera-specific settings
|
||||
self.create_menus()
|
||||
|
||||
self.init_ui()
|
||||
self.init_timer()
|
||||
|
||||
def create_menus(self):
|
||||
"""Create the menu bar with model and camera menus"""
|
||||
menubar = self.menuBar()
|
||||
|
||||
# Model menu
|
||||
model_menu = menubar.addMenu('Model')
|
||||
|
||||
load_model_action = QAction('Load Model Directory...', self)
|
||||
load_model_action.triggered.connect(self.load_model_directory)
|
||||
model_menu.addAction(load_model_action)
|
||||
|
||||
# Camera menu
|
||||
self.camera_menu = menubar.addMenu('Cameras')
|
||||
self.refresh_cameras_action = QAction('Refresh Camera List', self)
|
||||
self.refresh_cameras_action.triggered.connect(self.populate_camera_menu)
|
||||
self.camera_menu.addAction(self.refresh_cameras_action)
|
||||
self.camera_menu.addSeparator()
|
||||
|
||||
self.camera_action_group = QActionGroup(self)
|
||||
self.camera_action_group.setExclusive(False)
|
||||
self.populate_camera_menu()
|
||||
|
||||
def populate_camera_menu(self):
|
||||
"""Populate the camera menu with available cameras"""
|
||||
# Clear existing camera actions (except refresh)
|
||||
for action in self.camera_menu.actions()[2:]:
|
||||
self.camera_menu.removeAction(action)
|
||||
|
||||
available_cams = self.detector.scan_for_cameras()
|
||||
for cam_path in available_cams:
|
||||
# Display friendly name
|
||||
if cam_path.startswith('/dev/'):
|
||||
cam_name = os.path.basename(cam_path)
|
||||
else:
|
||||
cam_name = f"Camera {cam_path}"
|
||||
|
||||
action = QAction(cam_name, self, checkable=True)
|
||||
action.setData(cam_path)
|
||||
self.camera_action_group.addAction(action)
|
||||
self.camera_menu.addAction(action)
|
||||
|
||||
if not available_cams:
|
||||
no_cam_action = QAction('No cameras found', self)
|
||||
no_cam_action.setEnabled(False)
|
||||
self.camera_menu.addAction(no_cam_action)
|
||||
|
||||
def load_model_directory(self):
|
||||
"""Open file dialog to select model directory"""
|
||||
model_dir = QFileDialog.getExistingDirectory(
|
||||
self,
|
||||
"Select Model Directory",
|
||||
QDir.homePath(),
|
||||
QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks
|
||||
)
|
||||
|
||||
if model_dir:
|
||||
if self.detector.load_yolo_model(model_dir):
|
||||
self.model_label.setText(f"Model: {os.path.basename(model_dir)}")
|
||||
QMessageBox.information(self, "Success", "Model loaded successfully!")
|
||||
else:
|
||||
QMessageBox.critical(self, "Error", "Failed to load model from selected directory")
|
||||
|
||||
def init_ui(self):
|
||||
"""Initialize the user interface"""
|
||||
main_widget = QWidget()
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
# Control panel
|
||||
control_panel = QGroupBox("Controls")
|
||||
control_layout = QHBoxLayout()
|
||||
|
||||
# Model info
|
||||
self.model_label = QLabel("Model: Not loaded")
|
||||
control_layout.addWidget(self.model_label)
|
||||
|
||||
# Selected cameras label
|
||||
self.cameras_label = QLabel("Selected Cameras: None")
|
||||
control_layout.addWidget(self.cameras_label)
|
||||
|
||||
# FPS control
|
||||
self.fps_spin = QSpinBox()
|
||||
self.fps_spin.setRange(1, 60)
|
||||
self.fps_spin.setValue(10)
|
||||
control_layout.addWidget(QLabel("FPS:"))
|
||||
control_layout.addWidget(self.fps_spin)
|
||||
|
||||
# Camera layout selection
|
||||
self.layout_combo = QComboBox()
|
||||
self.layout_combo.addItems(["1 Camera", "2 Cameras", "3 Cameras", "4 Cameras", "Grid Layout"])
|
||||
self.layout_combo.currentIndexChanged.connect(self.change_camera_layout)
|
||||
control_layout.addWidget(QLabel("Layout:"))
|
||||
control_layout.addWidget(self.layout_combo)
|
||||
|
||||
# Buttons
|
||||
self.start_btn = QPushButton("Start Detection")
|
||||
self.start_btn.clicked.connect(self.start_detection)
|
||||
control_layout.addWidget(self.start_btn)
|
||||
|
||||
self.stop_btn = QPushButton("Stop Detection")
|
||||
self.stop_btn.clicked.connect(self.stop_detection)
|
||||
self.stop_btn.setEnabled(False)
|
||||
control_layout.addWidget(self.stop_btn)
|
||||
|
||||
control_panel.setLayout(control_layout)
|
||||
main_layout.addWidget(control_panel)
|
||||
|
||||
# Camera display area
|
||||
self.display_area = QWidget()
|
||||
self.display_layout = QGridLayout()
|
||||
self.camera_displays = []
|
||||
|
||||
# Initially create 4 camera displays
|
||||
for i in range(4):
|
||||
display = CameraDisplay()
|
||||
self.camera_displays.append(display)
|
||||
self.display_layout.addWidget(display, i//2, i%2)
|
||||
|
||||
self.display_area.setLayout(self.display_layout)
|
||||
main_layout.addWidget(self.display_area)
|
||||
|
||||
main_widget.setLayout(main_layout)
|
||||
self.setCentralWidget(main_widget)
|
||||
|
||||
def change_camera_layout(self, index):
|
||||
"""Change the camera display layout"""
|
||||
# Clear the layout
|
||||
for i in reversed(range(self.display_layout.count())):
|
||||
self.display_layout.itemAt(i).widget().setParent(None)
|
||||
|
||||
num_cameras = index + 1 if index < 4 else 4
|
||||
|
||||
if index == 4: # Grid layout
|
||||
rows = 2
|
||||
cols = 2
|
||||
for i in range(4):
|
||||
self.display_layout.addWidget(self.camera_displays[i], i//cols, i%cols)
|
||||
else:
|
||||
if num_cameras == 1:
|
||||
self.display_layout.addWidget(self.camera_displays[0], 0, 0, 1, 2)
|
||||
elif num_cameras == 2:
|
||||
self.display_layout.addWidget(self.camera_displays[0], 0, 0)
|
||||
self.display_layout.addWidget(self.camera_displays[1], 0, 1)
|
||||
elif num_cameras == 3:
|
||||
self.display_layout.addWidget(self.camera_displays[0], 0, 0)
|
||||
self.display_layout.addWidget(self.camera_displays[1], 0, 1)
|
||||
self.display_layout.addWidget(self.camera_displays[2], 1, 0, 1, 2)
|
||||
elif num_cameras == 4:
|
||||
for i in range(4):
|
||||
self.display_layout.addWidget(self.camera_displays[i], i//2, i%2)
|
||||
|
||||
# Hide unused displays
|
||||
for i, display in enumerate(self.camera_displays):
|
||||
display.setVisible(i < num_cameras)
|
||||
|
||||
def init_timer(self):
|
||||
"""Initialize the timer for updating camera feeds"""
|
||||
self.timer = QTimer()
|
||||
self.timer.timeout.connect(self.update_feeds)
|
||||
|
||||
def start_detection(self):
|
||||
"""Start the detection process"""
|
||||
if not self.detector.model_dir:
|
||||
QMessageBox.critical(self, "Error", "No model directory selected!")
|
||||
return
|
||||
|
||||
# Get selected cameras
|
||||
selected_cameras = []
|
||||
for action in self.camera_action_group.actions():
|
||||
if action.isChecked():
|
||||
selected_cameras.append(action.data())
|
||||
|
||||
if not selected_cameras:
|
||||
QMessageBox.critical(self, "Error", "No cameras selected!")
|
||||
return
|
||||
|
||||
# Set FPS
|
||||
self.detector.target_fps = self.fps_spin.value()
|
||||
self.detector.frame_interval = 1.0 / self.detector.target_fps
|
||||
|
||||
# Connect to cameras
|
||||
if not self.detector.connect_cameras(selected_cameras):
|
||||
QMessageBox.critical(self, "Error", "Failed to connect to cameras!")
|
||||
return
|
||||
|
||||
# Update UI
|
||||
self.update_selection_labels()
|
||||
self.start_btn.setEnabled(False)
|
||||
self.stop_btn.setEnabled(True)
|
||||
self.fps_spin.setEnabled(False)
|
||||
|
||||
# Start timer
|
||||
self.timer.start(int(1000 / self.detector.target_fps))
|
||||
|
||||
def stop_detection(self):
|
||||
"""Stop the detection process"""
|
||||
self.timer.stop()
|
||||
self.detector.disconnect_cameras()
|
||||
|
||||
# Update UI
|
||||
self.start_btn.setEnabled(True)
|
||||
self.stop_btn.setEnabled(False)
|
||||
self.fps_spin.setEnabled(True)
|
||||
|
||||
# Clear displays
|
||||
for display in self.camera_displays:
|
||||
display.setText("No camera feed")
|
||||
display.setStyleSheet("background-color: black; color: white;")
|
||||
|
||||
def update_selection_labels(self):
|
||||
"""Update the model and camera selection labels"""
|
||||
# Update cameras label
|
||||
selected_cams = []
|
||||
for action in self.camera_action_group.actions():
|
||||
if action.isChecked():
|
||||
selected_cams.append(action.text())
|
||||
self.cameras_label.setText(f"Selected Cameras: {', '.join(selected_cams) or 'None'}")
|
||||
|
||||
def update_feeds(self):
|
||||
"""Update the camera feeds in the display"""
|
||||
frames = self.detector.get_frames()
|
||||
|
||||
for i, frame in enumerate(frames):
|
||||
if i >= len(self.camera_displays):
|
||||
break
|
||||
|
||||
# Convert frame to QImage
|
||||
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
h, w, ch = rgb_image.shape
|
||||
bytes_per_line = ch * w
|
||||
qt_image = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888)
|
||||
|
||||
# Scale while maintaining aspect ratio
|
||||
pixmap = QPixmap.fromImage(qt_image)
|
||||
display = self.camera_displays[i]
|
||||
display.setPixmap(pixmap.scaled(display.width(), display.height(),
|
||||
Qt.KeepAspectRatio, Qt.SmoothTransformation))
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Handle window close event"""
|
||||
self.stop_detection()
|
||||
super().closeEvent(event)
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
||||
80
mucapy/models/coco.names
Normal file
80
mucapy/models/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
mucapy/models/yolov4-tiny.cfg
Normal file
294
mucapy/models/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
mucapy/models/yolov4-tiny.weights
Normal file
BIN
mucapy/models/yolov4-tiny.weights
Normal file
Binary file not shown.
Reference in New Issue
Block a user