some work on the merging
@ -32,7 +32,7 @@ class CentralWidget(QWidget):
|
|||||||
self._mergewidget.fileList = self._tw.fileList
|
self._mergewidget.fileList = self._tw.fileList
|
||||||
elif "tracks" in s.lower():
|
elif "tracks" in s.lower():
|
||||||
self.layout().setCurrentIndex(self._trackindex)
|
self.layout().setCurrentIndex(self._trackindex)
|
||||||
self._trackwidget.fileList = self._tw.fileList
|
# self._trackwidget.fileList = self._tw.fileList
|
||||||
else:
|
else:
|
||||||
self.layout().setCurrentIndex(self._tasksindex)
|
self.layout().setCurrentIndex(self._tasksindex)
|
||||||
logging.warning("Centralwidget: got invalid task request: %s", s)
|
logging.warning("Centralwidget: got invalid task request: %s", s)
|
||||||
|
@ -4,6 +4,7 @@ from PyQt6.QtGui import QKeySequence, QAction, QIcon
|
|||||||
|
|
||||||
from fixtracks.centralwidget import CentralWidget
|
from fixtracks.centralwidget import CentralWidget
|
||||||
|
|
||||||
|
import fixtracks.resources
|
||||||
# Subclass QMainWindow to customize your application's main window
|
# Subclass QMainWindow to customize your application's main window
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ class MainWindow(QMainWindow):
|
|||||||
# cw.exit_signal.connect(self.exit_request)
|
# cw.exit_signal.connect(self.exit_request)
|
||||||
|
|
||||||
def create_actions(self):
|
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.setStatusTip("Open nix file")
|
||||||
self._file_open_action.setShortcut(QKeySequence("Ctrl+o"))
|
self._file_open_action.setShortcut(QKeySequence("Ctrl+o"))
|
||||||
self._file_open_action.triggered.connect(self.on_file_open)
|
self._file_open_action.triggered.connect(self.on_file_open)
|
||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 40 KiB |
@ -1,8 +1,9 @@
|
|||||||
import logging
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QFileDialog, QSizePolicy
|
from PyQt6.QtWidgets import QWidget, QPushButton, QFileDialog, QSizePolicy, QGridLayout
|
||||||
from PyQt6.QtCore import pyqtSignal, Qt
|
from PyQt6.QtCore import pyqtSignal, Qt, QSize
|
||||||
|
from PyQt6.QtGui import QIcon, QAction, QPixmap
|
||||||
|
|
||||||
|
|
||||||
class TasksWidget(QWidget):
|
class TasksWidget(QWidget):
|
||||||
@ -10,37 +11,49 @@ class TasksWidget(QWidget):
|
|||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
folderBtn = QPushButton("Select data folder")
|
|
||||||
|
folderBtn = QPushButton()
|
||||||
folderBtn.setEnabled(True)
|
folderBtn.setEnabled(True)
|
||||||
folderBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
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)
|
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.setToolTip("Convert JSON pose files to to Pandas data frames")
|
||||||
self.convertBtn.setEnabled(False)
|
self.convertBtn.setEnabled(False)
|
||||||
self.convertBtn.setMaximumSize(200, 100)
|
self.convertBtn.setFixedSize(250, 100)
|
||||||
self.convertBtn.clicked.connect(self.convert_clicked)
|
self.convertBtn.setIconSize(0.95 * self.convertBtn.size())
|
||||||
self.convertBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
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.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.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.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.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.addWidget(folderBtn)
|
||||||
l.setAlignment(Qt.AlignmentFlag.AlignVCenter)
|
# l.addWidget(self.convertBtn)
|
||||||
l.addWidget(folderBtn)
|
# l.addWidget(self.mergeBtn)
|
||||||
l.addWidget(self.convertBtn)
|
# l.addWidget(self.tracksBtn)
|
||||||
l.addWidget(self.mergeBtn)
|
|
||||||
l.addWidget(self.tracksBtn)
|
|
||||||
self.setLayout(l)
|
self.setLayout(l)
|
||||||
self._file_list = []
|
self._file_list = []
|
||||||
|
|
||||||
@ -50,7 +63,7 @@ class TasksWidget(QWidget):
|
|||||||
def _tracks_clicked(self):
|
def _tracks_clicked(self):
|
||||||
self.clicked.emit("Tracks")
|
self.clicked.emit("Tracks")
|
||||||
|
|
||||||
def _convert_clickes(self)
|
def _convert_clicked(self):
|
||||||
self.clicked.emit("Convert")
|
self.clicked.emit("Convert")
|
||||||
|
|
||||||
def _open_folder(self):
|
def _open_folder(self):
|
||||||
|
@ -205,31 +205,55 @@ def merge_detections(left_data:pd.DataFrame, right_data: pd.DataFrame, left_cut:
|
|||||||
visibility[i, :] = row["visible"]
|
visibility[i, :] = row["visible"]
|
||||||
return keypoints, visibility, boxcoordinates
|
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)
|
logging.debug("Cutting left detections to limit %i", left_cut)
|
||||||
if not check_dataframe(left_data) or not check_dataframe(right_data):
|
if not check_dataframe(left_data) or not check_dataframe(right_data):
|
||||||
logging.error("Left or right dataframe structure does not match my expectations")
|
logging.error("Left or right dataframe structure does not match my expectations")
|
||||||
return None
|
return None
|
||||||
df = pd.DataFrame(columns=left_data.columns)
|
|
||||||
dangerzone = {"left": [], "right":[]}
|
|
||||||
lkeypoints, lquality, lbox = to_numpy(left_data)
|
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()
|
embed()
|
||||||
exit()
|
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():
|
def main():
|
||||||
|