diff --git a/fixtracks/centralwidget.py b/fixtracks/centralwidget.py index 801cfe7..8fd6971 100644 --- a/fixtracks/centralwidget.py +++ b/fixtracks/centralwidget.py @@ -32,7 +32,7 @@ class CentralWidget(QWidget): self._mergewidget.fileList = self._tw.fileList elif "tracks" in s.lower(): self.layout().setCurrentIndex(self._trackindex) - self._trackwidget.fileList = self._tw.fileList + # self._trackwidget.fileList = self._tw.fileList else: self.layout().setCurrentIndex(self._tasksindex) logging.warning("Centralwidget: got invalid task request: %s", s) diff --git a/fixtracks/fixtracks.py b/fixtracks/fixtracks.py index de86d9d..af569d4 100644 --- a/fixtracks/fixtracks.py +++ b/fixtracks/fixtracks.py @@ -4,6 +4,7 @@ from PyQt6.QtGui import QKeySequence, QAction, QIcon from fixtracks.centralwidget import CentralWidget +import fixtracks.resources # Subclass QMainWindow to customize your application's main window @@ -17,7 +18,7 @@ class MainWindow(QMainWindow): # 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 = QAction(QIcon(":/icons/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) diff --git a/fixtracks/icons/Unbenannt.afdesign b/fixtracks/icons/Unbenannt.afdesign index 808d490..a511541 100644 Binary files a/fixtracks/icons/Unbenannt.afdesign and b/fixtracks/icons/Unbenannt.afdesign differ diff --git a/fixtracks/icons/convert.png b/fixtracks/icons/convert.png index 7e00cf5..f85c30d 100644 Binary files a/fixtracks/icons/convert.png and b/fixtracks/icons/convert.png differ diff --git a/fixtracks/icons/merge.png b/fixtracks/icons/merge.png index e916b21..f4f3aac 100644 Binary files a/fixtracks/icons/merge.png and b/fixtracks/icons/merge.png differ diff --git a/fixtracks/icons/open.png b/fixtracks/icons/open.png index 890e23c..646054e 100644 Binary files a/fixtracks/icons/open.png and b/fixtracks/icons/open.png differ diff --git a/fixtracks/icons/tracks.png b/fixtracks/icons/tracks.png index 53f3e6e..d88cec7 100644 Binary files a/fixtracks/icons/tracks.png and b/fixtracks/icons/tracks.png differ diff --git a/fixtracks/taskwidget.py b/fixtracks/taskwidget.py index d7fd8aa..67cc3a4 100644 --- a/fixtracks/taskwidget.py +++ b/fixtracks/taskwidget.py @@ -1,8 +1,9 @@ import logging import pathlib -from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QFileDialog, QSizePolicy -from PyQt6.QtCore import pyqtSignal, Qt +from PyQt6.QtWidgets import QWidget, QPushButton, QFileDialog, QSizePolicy, QGridLayout +from PyQt6.QtCore import pyqtSignal, Qt, QSize +from PyQt6.QtGui import QIcon, QAction, QPixmap class TasksWidget(QWidget): @@ -10,37 +11,49 @@ class TasksWidget(QWidget): def __init__(self, parent = None): super().__init__(parent) - folderBtn = QPushButton("Select data folder") + + folderBtn = QPushButton() folderBtn.setEnabled(True) folderBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) - folderBtn.setMaximumSize(200, 100) + folderBtn.setMaximumSize(300, 300) + folderBtn.setIcon(QIcon(":icons/open")) + folderBtn.setIconSize(0.95 * folderBtn.size()) folderBtn.clicked.connect(self._open_folder) - self.convertBtn = QPushButton("Convert tracks") + self.convertBtn = QPushButton() + self.convertBtn.setIcon(QIcon(":/icons/convert")) self.convertBtn.setToolTip("Convert JSON pose files to to Pandas data frames") self.convertBtn.setEnabled(False) - self.convertBtn.setMaximumSize(200, 100) - self.convertBtn.clicked.connect(self.convert_clicked) - self.convertBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + self.convertBtn.setFixedSize(250, 100) + self.convertBtn.setIconSize(0.95 * self.convertBtn.size()) + self.convertBtn.clicked.connect(self._convert_clicked) + # self.convertBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) - self.mergeBtn = QPushButton("Merge detections") + self.mergeBtn = QPushButton(QIcon(":/icons/merge"), "") self.mergeBtn.setEnabled(False) - self.mergeBtn.setMaximumSize(200, 100) + self.mergeBtn.setFixedSize(250, 100) + self.mergeBtn.setIconSize(0.95 * self.mergeBtn.size()) self.mergeBtn.clicked.connect(self._merge_clicked) - self.mergeBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + # self.mergeBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) - self.tracksBtn = QPushButton("Join tracks") + self.tracksBtn = QPushButton(QIcon(":/icons/tracks"), "") self.tracksBtn.setEnabled(False) - self.tracksBtn.setMaximumSize(200, 100) + self.tracksBtn.setFixedSize(250, 100) + self.tracksBtn.setIconSize(0.95 * self.tracksBtn.size()) self.tracksBtn.clicked.connect(self._tracks_clicked) - self.tracksBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + # self.tracksBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + + l = QGridLayout() + l.setAlignment(Qt.AlignmentFlag.AlignCenter) + l.addWidget(folderBtn, 0, 0, 3, 1, Qt.AlignmentFlag.AlignCenter) + l.addWidget(self.convertBtn, 0, 1, 1, 1, Qt.AlignmentFlag.AlignCenter) + l.addWidget(self.mergeBtn, 1, 1, 1, 1, Qt.AlignmentFlag.AlignCenter) + l.addWidget(self.tracksBtn, 2, 1, 1, 1, Qt.AlignmentFlag.AlignCenter) - l = QVBoxLayout() - l.setAlignment(Qt.AlignmentFlag.AlignVCenter) - l.addWidget(folderBtn) - l.addWidget(self.convertBtn) - l.addWidget(self.mergeBtn) - l.addWidget(self.tracksBtn) + # l.addWidget(folderBtn) + # l.addWidget(self.convertBtn) + # l.addWidget(self.mergeBtn) + # l.addWidget(self.tracksBtn) self.setLayout(l) self._file_list = [] @@ -50,7 +63,7 @@ class TasksWidget(QWidget): def _tracks_clicked(self): self.clicked.emit("Tracks") - def _convert_clickes(self) + def _convert_clicked(self): self.clicked.emit("Convert") def _open_folder(self): diff --git a/fixtracks/util.py b/fixtracks/util.py index 84fb579..e841081 100644 --- a/fixtracks/util.py +++ b/fixtracks/util.py @@ -204,32 +204,56 @@ def merge_detections(left_data:pd.DataFrame, right_data: pd.DataFrame, left_cut: else: visibility[i, :] = row["visible"] return keypoints, visibility, boxcoordinates - + + def sort_detections(keypoints, threshold, left=True): + """Categorize the detections into those that are easy (not in the visual overlap zone) and those that are tricky, i.e. right across the threshold. + Detections beyond threshold can be discarded, those across the threshold need to be treated separately. + + Parameters + ---------- + keypoints : np.ndarray + 3d array of keypoint coordinates (num detections, num keypoints, (x,y)) + threshold : int + the threshold line at which the data should be merged + left : bool, optional + whether or not the data is from the left side, controls how the threshold is interpreted, by default True + + Returns + ------- + np.ndarray + The indices of the easy detections + np.ndarray + The tricky detections + """ + if left: + easyindeces = np.where(np.all(keypoints[:,:,0] < threshold, axis=1))[0] + trickyindices = np.where(np.any((keypoints[:,:,0] >= threshold) & + (keypoints[:,:,0] < threshold), axis=1))[0] + else: + easyindeces = np.where(np.all(keypoints[:,:,0] >= threshold, axis=1))[0] + trickyindices = np.where(np.any((keypoints[:,:,0] < threshold) & + (keypoints[:,:,0] >= threshold), axis=1))[0] + return easyindeces, trickyindices + logging.debug("Cutting left detections to limit %i", left_cut) if not check_dataframe(left_data) or not check_dataframe(right_data): logging.error("Left or right dataframe structure does not match my expectations") return None - df = pd.DataFrame(columns=left_data.columns) - dangerzone = {"left": [], "right":[]} lkeypoints, lquality, lbox = to_numpy(left_data) + # rkeypoint, rquality, rbox = to_numpy(right_data) + lframes = left_data.frame.values + # rframes = right_data.frame.values + led, ltd = sort_detections(lkeypoints, left_cut, left=True) + # red, rtd = sort_detections(rkeypoints, right_cut, left=False) + + # here we need to decide what to do with these data points, trust the left, or trust the right perspective? + # we could also discard them. unless it is a lot of data points, not much harm will be done... + # next step after handling the tricky ones is to export the data again to pandas? nixtrack? + # 1. the right coordinates have to adapted! x - right_threshold + left_threshold! + rkeypoints[:, :, 0] += (left_cut - right_cut) + embed() exit() - for i, row in left_data.iterrows(): - if check_frame(row, left_cut): - df = pd.concat([df, row.to_frame().T], ignore_index=True) - else: - dangerzone["left"].append(row) - if i > 10000: - break - print("Left done") - for i, row in right_data.iterrows(): - if check_frame(row[1], right_cut, left=False): - # convert_right(row[1]) need to convert the frame coordinates! - df = pd.concat([df, row[1].to_frame().T], ignore_index=True) - else: - dangerzone["right"].append(row[1]) - if i > 10000: - break def main():