add more py files
This commit is contained in:
parent
1383d84b89
commit
e4959b5bb1
0
fixtracks/__init__.py
Normal file
0
fixtracks/__init__.py
Normal file
43
fixtracks/centralwidget.py
Normal file
43
fixtracks/centralwidget.py
Normal file
@ -0,0 +1,43 @@
|
||||
import logging
|
||||
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QStackedLayout, QPushButton
|
||||
from PyQt6.QtWidgets import QFileDialog
|
||||
from PyQt6.QtCore import Qt, pyqtSignal
|
||||
|
||||
from fixtracks.taskwidgets import MergeDetections, FixTracks, TasksWidget
|
||||
|
||||
|
||||
|
||||
|
||||
class CentralWidget(QWidget):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
layout = QStackedLayout()
|
||||
self._tw = TasksWidget()
|
||||
self._tw.clicked.connect(self._select_task)
|
||||
self._tasksindex = layout.addWidget(self._tw)
|
||||
self._mergewidget = MergeDetections(self)
|
||||
self._trackwidget = FixTracks(self)
|
||||
self._mergeindex = layout.addWidget(self._mergewidget)
|
||||
self._trackindex = layout.addWidget(self._trackwidget)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def _select_task(self, s):
|
||||
logging.debug("Centralwidget: Selected task: %s", s)
|
||||
if "merge" in s.lower():
|
||||
self.layout().setCurrentIndex(self._mergeindex)
|
||||
self._mergewidget.fileList = self._tw.fileList
|
||||
elif "tracks" in s.lower():
|
||||
self.layout().setCurrentIndex(self._trackindex)
|
||||
self._trackwidget.fileList = self._tw.fileList
|
||||
else:
|
||||
logging.warning("Centralwidget: got invalid task request: %s", s)
|
||||
|
||||
# # @Slot(None)
|
||||
# def on_exit(self):
|
||||
# self.exit_signal.emit()
|
||||
|
||||
# # @Slot(None)
|
||||
# def on_new(self):
|
||||
# self._view.setScene(self._gamescene)
|
124
fixtracks/fixtracks.py
Normal file
124
fixtracks/fixtracks.py
Normal file
@ -0,0 +1,124 @@
|
||||
from PyQt6.QtCore import QSize, Qt
|
||||
from PyQt6.QtWidgets import QMainWindow, QWidget, QToolBar, QMenu, QMenuBar, QSizePolicy, QFileDialog
|
||||
from PyQt6.QtGui import QKeySequence, QAction, QIcon
|
||||
|
||||
from fixtracks.centralwidget import CentralWidget
|
||||
|
||||
# Subclass QMainWindow to customize your application's main window
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.create_actions()
|
||||
self._toolbar = None
|
||||
cw = CentralWidget()
|
||||
self.setCentralWidget(cw)
|
||||
# cw.exit_signal.connect(self.exit_request)
|
||||
|
||||
def create_actions(self):
|
||||
self._file_open_action = QAction(QIcon(":/icons/file_open"), "Open", self)
|
||||
self._file_open_action.setStatusTip("Open nix file")
|
||||
self._file_open_action.setShortcut(QKeySequence("Ctrl+o"))
|
||||
self._file_open_action.triggered.connect(self.on_file_open)
|
||||
|
||||
# self._file_close_action = QAction(QIcon(":/icons/file_close"), "Close", self)
|
||||
# self._file_close_action.setStatusTip("Close current nix file")
|
||||
# self._file_close_action.setShortcut(QKeySequence("Ctrl+w"))
|
||||
# self._file_close_action.setEnabled(False)
|
||||
# self._file_close_action.triggered.connect(self.on_file_close)
|
||||
|
||||
self._quit_action = QAction(QIcon(":quit"), "Quit", self)
|
||||
self._quit_action.setStatusTip("Close current file and quit")
|
||||
self._quit_action.setShortcut(QKeySequence("Ctrl+q"))
|
||||
self._quit_action.triggered.connect(self.exit_request)
|
||||
|
||||
# self._plot_action = QAction(QIcon(":/icons/show_plot"), "Plot", self)
|
||||
# self._plot_action.setStatusTip("Plot currently selected entity")
|
||||
# self._plot_action.setShortcut(QKeySequence("Ctrl+p"))
|
||||
# self._plot_action.setEnabled(False)
|
||||
# self._plot_action.triggered.connect(self.on_item_plot)
|
||||
|
||||
# self._table_action = QAction(QIcon(":/icons/show_table"), "Show table", self)
|
||||
# self._table_action.setStatusTip("Show data as table")
|
||||
# self._table_action.setShortcut(QKeySequence("Ctrl+t"))
|
||||
# self._table_action.setEnabled(False)
|
||||
# self._table_action.triggered.connect(self.on_item_show_table)
|
||||
|
||||
self._about_action = QAction("about")
|
||||
self._about_action.setStatusTip("Show about dialog")
|
||||
self._about_action.setEnabled(True)
|
||||
self._about_action.triggered.connect(self.on_about)
|
||||
|
||||
self._help_action = QAction(QIcon(":help"), "help")
|
||||
self._help_action.setStatusTip("Show help dialog")
|
||||
self._help_action.setShortcut(QKeySequence("F1"))
|
||||
|
||||
self._help_action.setEnabled(True)
|
||||
self._help_action.triggered.connect(self.on_help)
|
||||
|
||||
self.create_toolbar()
|
||||
self.create_menu()
|
||||
|
||||
def create_menu(self):
|
||||
menu = self.menuBar()
|
||||
file_menu = menu.addMenu("&File")
|
||||
file_menu.addAction(self._file_open_action)
|
||||
# file_menu.addAction(self._file_close_action)
|
||||
file_menu.addSeparator()
|
||||
file_menu.addAction(self._quit_action)
|
||||
|
||||
plot_menu = menu.addMenu("&Plot")
|
||||
# plot_menu.addAction(self._plot_action)
|
||||
# plot_menu.addAction(self._table_action)
|
||||
|
||||
help_menu = menu.addMenu("&Help")
|
||||
help_menu.addAction(self._about_action)
|
||||
help_menu.addAction(self._help_action)
|
||||
self.setMenuBar(menu)
|
||||
|
||||
def create_toolbar(self):
|
||||
self._toolbar = QToolBar("My main toolbar")
|
||||
#self._toolbar.setStyleSheet("QToolButton:!hover {background-color:none}")
|
||||
self._toolbar.setAllowedAreas(Qt.ToolBarArea.LeftToolBarArea | Qt.ToolBarArea.TopToolBarArea)
|
||||
self._toolbar.setFloatable(False)
|
||||
self._toolbar.setIconSize(QSize(32, 32))
|
||||
|
||||
self._toolbar.addAction(self._file_open_action)
|
||||
# self._toolbar.addAction(self._file_close_action)
|
||||
self._toolbar.addSeparator()
|
||||
# self._toolbar.addAction(self._plot_action)
|
||||
# self._toolbar.addAction(self._table_action)
|
||||
self._toolbar.addAction(self._help_action)
|
||||
|
||||
empty = QWidget()
|
||||
empty.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||
self._toolbar.addWidget(empty)
|
||||
self._toolbar.addSeparator()
|
||||
self._toolbar.addAction(self._quit_action)
|
||||
|
||||
# settings = QSettings(info.ORGANIZATION, info.NAME)
|
||||
# tb_orientation = settings.value("app/toolbar_area", "left")
|
||||
# self.addToolBar(Qt.LeftToolBarArea if tb_orientation == "left" else Qt.TopToolBarArea, self._toolbar)
|
||||
# self._toolbar.topLevelChanged.connect(self.tb_changed)
|
||||
# del settings
|
||||
|
||||
|
||||
def on_file_open(self, s):
|
||||
QFileDialog.getExistingDirectory()
|
||||
# dlg = QFileDialog(self, 'Open dataset folder data file', '', "NIX files (*.h5 *.nix)")
|
||||
# dlg.setFileMode(QFileDialog.ExistingFile)
|
||||
# filenames = None
|
||||
# if dlg.exec_():
|
||||
# filenames = dlg.selectedFiles()
|
||||
# self.open_file(filenames[0])
|
||||
|
||||
def on_about(self, s):
|
||||
pass
|
||||
|
||||
def on_help(self, s):
|
||||
pass
|
||||
|
||||
# @Slot(None)
|
||||
def exit_request(self):
|
||||
self.close()
|
5
fixtracks/info.py
Normal file
5
fixtracks/info.py
Normal file
@ -0,0 +1,5 @@
|
||||
from packaging.version import Version
|
||||
|
||||
organization_name = "de.bendalab"
|
||||
application_name = "FixTracks"
|
||||
application_version = Version("0.0.1")
|
171
fixtracks/taskwidgets.py
Normal file
171
fixtracks/taskwidgets.py
Normal file
@ -0,0 +1,171 @@
|
||||
import logging
|
||||
import pathlib
|
||||
import cv2 as cv
|
||||
|
||||
from PyQt6.QtWidgets import QWidget, QGridLayout, QVBoxLayout, QLabel, QPushButton, QFileDialog, QHBoxLayout, QComboBox, QSizePolicy
|
||||
from PyQt6.QtCore import pyqtSignal, pyqtSlot, QThreadPool
|
||||
from PyQt6.QtGui import QImage, QPixmap
|
||||
|
||||
from fixtracks.util import ImageReader
|
||||
|
||||
class TasksWidget(QWidget):
|
||||
clicked = pyqtSignal((str,))
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
||||
l = QVBoxLayout()
|
||||
l.addWidget(QLabel("Tasks:"))
|
||||
folderBtn = QPushButton("Select data folder")
|
||||
folderBtn.setEnabled(True)
|
||||
folderBtn.clicked.connect(self._open_folder)
|
||||
l.addWidget(folderBtn)
|
||||
self.mergeBtn = QPushButton("Merge detections")
|
||||
self.mergeBtn.setEnabled(False)
|
||||
self.mergeBtn.clicked.connect(self._merge_clicked)
|
||||
self.tracksBtn = QPushButton("Join tracks")
|
||||
self.tracksBtn.setEnabled(False)
|
||||
self.tracksBtn.clicked.connect(self._tracks_clicked)
|
||||
l.addWidget(self.mergeBtn)
|
||||
l.addWidget(self.tracksBtn)
|
||||
self.setLayout(l)
|
||||
self._file_list = []
|
||||
|
||||
def _merge_clicked(self):
|
||||
self.clicked.emit("Merge")
|
||||
|
||||
def _tracks_clicked(self):
|
||||
self.clicked.emit("Tracks")
|
||||
|
||||
def _open_folder(self):
|
||||
logging.debug("TasksWidget:select data folder")
|
||||
folder = QFileDialog.getExistingDirectory()
|
||||
if len(folder.strip()) == 0:
|
||||
logging.debug("TasksWidget: is EMPTY")
|
||||
return
|
||||
p = pathlib.Path(folder)
|
||||
logging.debug("TasksWidget: selected path is %s", p)
|
||||
for d in p.iterdir():
|
||||
if d.is_file():
|
||||
self._file_list.append(d)
|
||||
if len(self._file_list) > 0:
|
||||
self.mergeBtn.setEnabled(True)
|
||||
self.tracksBtn.setEnabled(True)
|
||||
|
||||
@property
|
||||
def fileList(self):
|
||||
return self._file_list
|
||||
|
||||
|
||||
class MergeDetections(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._files = []
|
||||
self.threadpool = QThreadPool()
|
||||
self.right_imagereader = None
|
||||
self.left_imagereader = None
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(QLabel("Merge Detections!"))
|
||||
hbox = QHBoxLayout()
|
||||
|
||||
leftvbox = QVBoxLayout()
|
||||
self.leftdatacombo = QComboBox()
|
||||
self.leftvideocombo = QComboBox()
|
||||
self.leftvideocombo.addItems(self._files)
|
||||
self.left_preview = QLabel()
|
||||
self.left_preview.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||
|
||||
leftvbox.addWidget(self.left_preview)
|
||||
leftvbox.addWidget(QLabel("Left data file:"))
|
||||
leftvbox.addWidget(self.leftdatacombo)
|
||||
leftvbox.addWidget(QLabel("Left video:"))
|
||||
leftvbox.addWidget(self.leftvideocombo)
|
||||
|
||||
rightvbox = QVBoxLayout()
|
||||
self.rightdatacombo = QComboBox()
|
||||
self.rightvideocombo = QComboBox()
|
||||
self.rightvideocombo.addItems(self._files)
|
||||
self.right_preview = QLabel()
|
||||
self.right_preview.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||
rightvbox.addWidget(QLabel("Right data file:"))
|
||||
rightvbox.addWidget(self.rightdatacombo)
|
||||
rightvbox.addWidget(QLabel("Right video:"))
|
||||
rightvbox.addWidget(self.rightvideocombo)
|
||||
rightvbox.addWidget(self.right_preview)
|
||||
|
||||
hbox.addLayout(leftvbox)
|
||||
hbox.addLayout(rightvbox)
|
||||
layout.addLayout(hbox)
|
||||
self.setLayout(layout)
|
||||
|
||||
@property
|
||||
def fileList(self):
|
||||
return self._files
|
||||
|
||||
@fileList.setter
|
||||
def fileList(self, file_list):
|
||||
logging.debug("MergeDetections.fileList: set new file list")
|
||||
|
||||
logging.debug("MergeDetections.fileList: setting video combo boxes")
|
||||
videoformats = [".mp4", ".avi"]
|
||||
self._files = [str(f) for f in file_list if f.suffix in videoformats]
|
||||
self.rightvideocombo.addItem("Please select")
|
||||
self.leftvideocombo.addItem("Please select")
|
||||
self.rightvideocombo.addItems(self.fileList)
|
||||
self.leftvideocombo.addItems(self.fileList)
|
||||
self.leftvideocombo.setCurrentIndex(0)
|
||||
self.rightvideocombo.setCurrentIndex(0)
|
||||
|
||||
logging.debug("MergeDetections.fileList: setting data combo boxes")
|
||||
dataformats = [".csv"]
|
||||
self._files = [str(f) for f in file_list if f.suffix in dataformats]
|
||||
self.rightdatacombo.addItem("Please select")
|
||||
self.leftdatacombo.addItem("Please select")
|
||||
self.rightdatacombo.addItems(self.fileList)
|
||||
self.leftdatacombo.addItems(self.fileList)
|
||||
self.leftdatacombo.setCurrentIndex(0)
|
||||
self.rightdatacombo.setCurrentIndex(0)
|
||||
self.rightvideocombo.currentIndexChanged.connect(self.on_rightvideoSelection)
|
||||
self.leftvideocombo.currentIndexChanged.connect(self.on_leftvideoSelection)
|
||||
# self._files = file_list
|
||||
|
||||
def on_rightvideoSelection(self):
|
||||
logging.debug("Video selection of the %s side", "right")
|
||||
self.right_imagereader = ImageReader(self.rightvideocombo.currentText(), 100)
|
||||
self.right_imagereader.signals.finished.connect(self.right_imgreaderDone)
|
||||
self.threadpool.start(self.right_imagereader)
|
||||
|
||||
def right_imgreaderDone(self, state):
|
||||
logging.debug("Right image reader done with state %s", str(state))
|
||||
frame = self.right_imagereader.frame
|
||||
height, width, _ = frame.shape
|
||||
bytesPerLine = 3 * width
|
||||
img = QImage(frame.data, width, height, bytesPerLine, QImage.Format.Format_BGR888).rgbSwapped()
|
||||
self.right_preview.setPixmap(QPixmap.fromImage(img).scaledToHeight(self.right_preview.height()))
|
||||
|
||||
def on_leftvideoSelection(self):
|
||||
logging.debug("Video selection of the %s side", "left")
|
||||
self.left_imagereader = ImageReader(self.leftvideocombo.currentText(), 100)
|
||||
self.left_imagereader.signals.finished.connect(self.left_imgreaderDone)
|
||||
self.threadpool.start(self.left_imagereader)
|
||||
|
||||
def left_imgreaderDone(self, state):
|
||||
logging.debug("Left image reader done with state %s", str(state))
|
||||
frame = self.left_imagereader.frame
|
||||
height, width, _ = frame.shape
|
||||
bytesPerLine = 3 * width
|
||||
img = QImage(frame.data, width, height, bytesPerLine, QImage.Format.Format_BGR888).rgbSwapped()
|
||||
self.left_preview.setPixmap(QPixmap.fromImage(img).scaledToHeight(self.left_preview.height()))
|
||||
|
||||
|
||||
class FixTracks(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._files = None
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(QLabel("Fix Tracks!"))
|
||||
self.setLayout(layout)
|
||||
|
||||
@property
|
||||
def fileList(self, file_list):
|
||||
self._files = file_list
|
51
fixtracks/util.py
Normal file
51
fixtracks/util.py
Normal file
@ -0,0 +1,51 @@
|
||||
import logging
|
||||
import cv2 as cv
|
||||
|
||||
from PyQt6.QtCore import QRunnable, pyqtSlot, pyqtSignal, QObject
|
||||
|
||||
|
||||
class ProducerSignals(QObject):
|
||||
finished = pyqtSignal(bool)
|
||||
# error = pyqtSignal(str)
|
||||
# start = pyqtSignal(float)
|
||||
# running = pyqtSignal()
|
||||
|
||||
|
||||
class ImageReader(QRunnable):
|
||||
finished = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, filename, frame=1000) -> None:
|
||||
super().__init__()
|
||||
self._filename = filename
|
||||
self._framenumber = frame
|
||||
self._signals = ProducerSignals()
|
||||
self._frame = None
|
||||
|
||||
@pyqtSlot()
|
||||
def run(self):
|
||||
'''
|
||||
Your code goes in this function
|
||||
'''
|
||||
logging.debug("ImageReader: trying to open file %s", self._filename)
|
||||
cap = cv.VideoCapture(self._filename)
|
||||
if not cap.isOpened():
|
||||
logging.debug("ImageReader: failed to open file %s", self._filename)
|
||||
self._signals.finished.emit(False)
|
||||
fn = 0
|
||||
while cap.isOpened() and fn < self._framenumber:
|
||||
ret, frame = cap.read()
|
||||
if not ret:
|
||||
logging.warning("ImageReader: failed to read frame %i", fn)
|
||||
self._signals.finished.emit(False)
|
||||
break
|
||||
fn += 1
|
||||
self._frame = frame # cv.cvtColor(frame, cv.COLOR_BGR2RGB)
|
||||
self._signals.finished.emit(True)
|
||||
|
||||
@property
|
||||
def signals(self):
|
||||
return self._signals
|
||||
|
||||
@property
|
||||
def frame(self):
|
||||
return self._frame
|
Loading…
Reference in New Issue
Block a user