Compare commits
No commits in common. "a8fd5375f2a65bd0c87e6e64a3e026a3b170537c" and "6d288aace1d0f012a4a1e2e69db6181ab20df5d7" have entirely different histories.
a8fd5375f2
...
6d288aace1
@ -20,6 +20,9 @@ class ImageReader(QRunnable):
|
|||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def run(self):
|
def run(self):
|
||||||
|
'''
|
||||||
|
Your code goes in this function
|
||||||
|
'''
|
||||||
logging.debug("ImageReader: trying to open file %s", self._filename)
|
logging.debug("ImageReader: trying to open file %s", self._filename)
|
||||||
cap = cv.VideoCapture(self._filename)
|
cap = cv.VideoCapture(self._filename)
|
||||||
framecount = int(cap.get(cv.CAP_PROP_FRAME_COUNT))
|
framecount = int(cap.get(cv.CAP_PROP_FRAME_COUNT))
|
||||||
|
@ -171,30 +171,16 @@ class TrackingData(QObject):
|
|||||||
return orientations
|
return orientations
|
||||||
|
|
||||||
def bendedness(self, bodyaxis=None):
|
def bendedness(self, bodyaxis=None):
|
||||||
"""
|
|
||||||
Calculate the bendedness of the body axis.
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
bodyaxis : list of int, optional
|
|
||||||
Indices of the body axis coordinates to consider. If None, defaults to [0, 1, 2, 5].
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
numpy.ndarray
|
|
||||||
Array of mean absolute deviations of the body axis points from the head-tail vector.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if bodyaxis is None:
|
if bodyaxis is None:
|
||||||
bodyaxis = [0, 1, 2, 5]
|
bodyaxis = [0, 1, 2, 5]
|
||||||
bodycoords = self.coordinates()[:, bodyaxis, :]
|
bodycoords = self.coordinates()[:, bodyaxis, :]
|
||||||
bodycoords = np.concat((bodycoords, np.zeros((bodycoords.shape[0], len(bodyaxis), 1))), axis=2)
|
|
||||||
head_tail_vector = bodycoords[:, -1, :] - bodycoords[:, 0, :]
|
head_tail_vector = bodycoords[:, -1, :] - bodycoords[:, 0, :]
|
||||||
point_axis_vector = bodycoords[:,:,:] - bodycoords[:, 0, :][:,np.newaxis,:]
|
head_tail_vector = head_tail_vector[:, np.newaxis ,:] # cross-product only defined in space, not in 2D
|
||||||
htv = head_tail_vector[:,np.newaxis, :]
|
head_tail_length = np.linalg.norm(head_tail_vector, axis=1, keepdims=True) # pythagoras, length of head- tail connection
|
||||||
# Pythagoras, length of head- tail connection
|
point_axis_vectors = bodycoords - head_tail_vector
|
||||||
head_tail_length = np.linalg.norm(head_tail_vector, axis=1, keepdims=True)
|
deviations = np.cross(head_tail_vector, point_axis_vectors)/head_tail_length
|
||||||
deviations = np.cross(htv, point_axis_vector)[:,:,-1] / head_tail_length
|
deviation = np.mean(deviations, axis=1)
|
||||||
deviations = np.mean(np.abs(deviations), axis=1)
|
return deviation
|
||||||
return deviations
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self._data[key]
|
return self._data[key]
|
||||||
@ -250,8 +236,8 @@ def main():
|
|||||||
lengths = data.animalLength()
|
lengths = data.animalLength()
|
||||||
frames = data["frame"]
|
frames = data["frame"]
|
||||||
tracks = data["track"]
|
tracks = data["track"]
|
||||||
bendedness = data.bendedness()
|
|
||||||
|
# bendedness = data.bendedness()
|
||||||
|
|
||||||
embed()
|
embed()
|
||||||
tracks = data["track"]
|
tracks = data["track"]
|
||||||
|
@ -1,101 +1,13 @@
|
|||||||
import logging
|
import logging
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QTabWidget, QPushButton, QGraphicsView, QSpinBox, QProgressBar, QGridLayout, QLabel
|
from PySide6.QtWidgets import QWidget, QVBoxLayout, QTabWidget,QPushButton, QGraphicsView
|
||||||
from PySide6.QtCore import Signal, Slot, QRunnable, QObject, QThreadPool
|
from PySide6.QtCore import Signal
|
||||||
from PySide6.QtGui import QBrush, QColor
|
from PySide6.QtGui import QBrush, QColor
|
||||||
import pyqtgraph as pg # needs to be imported after pyside to not import pyqt
|
import pyqtgraph as pg # needs to be imported after pyside to not import pyqt
|
||||||
|
|
||||||
from fixtracks.utils.trackingdata import TrackingData
|
from fixtracks.utils.trackingdata import TrackingData
|
||||||
|
|
||||||
from IPython import embed
|
|
||||||
class WorkerSignals(QObject):
|
|
||||||
error = Signal(str)
|
|
||||||
running = Signal(bool)
|
|
||||||
progress = Signal(int, int, int)
|
|
||||||
finished = Signal(bool)
|
|
||||||
|
|
||||||
class ConsistencyWorker(QRunnable):
|
|
||||||
signals = WorkerSignals()
|
|
||||||
|
|
||||||
def __init__(self, positions, orientations, lengths, bendedness, frames, tracks, startframe=0) -> None:
|
|
||||||
super().__init__()
|
|
||||||
self.positions = positions
|
|
||||||
self.orientations = orientations
|
|
||||||
self.lengths = lengths
|
|
||||||
self._bendedness = bendedness
|
|
||||||
self.frames = frames
|
|
||||||
self.tracks = tracks
|
|
||||||
self._startframe = startframe
|
|
||||||
self._stoprequest = False
|
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def cancel(self):
|
|
||||||
self._stoprequest = True
|
|
||||||
|
|
||||||
@Slot()
|
|
||||||
def run(self):
|
|
||||||
last_pos = [self.positions[self.tracks == 1][0], self.positions[self.tracks == 2][0]]
|
|
||||||
last_frame = [self.frames[self.tracks == 1][0], self.frames[self.tracks == 2][0]]
|
|
||||||
last_angle = [self.orientations[self.tracks == 1][0], self.orientations[self.tracks == 2][0]]
|
|
||||||
errors = 0
|
|
||||||
processed = 0
|
|
||||||
self._stoprequest = False
|
|
||||||
maxframes = np.max(self.frames)
|
|
||||||
steps = int((maxframes - self._startframe) // 100)
|
|
||||||
progress = 0
|
|
||||||
assignment_error = False
|
|
||||||
for f in range(self._startframe, np.max(self.frames), 1):
|
|
||||||
processed += 1
|
|
||||||
if self._stoprequest:
|
|
||||||
break
|
|
||||||
indices = np.where(self.frames == f)[0]
|
|
||||||
pp = self.positions[indices]
|
|
||||||
originaltracks = self.tracks[indices]
|
|
||||||
assignments = np.zeros_like(originaltracks)
|
|
||||||
distances = np.zeros((len(originaltracks), 2))
|
|
||||||
for i, (idx, p) in enumerate(zip(indices, pp)):
|
|
||||||
if f < last_frame[0]:
|
|
||||||
self.tracks[idx] = 2
|
|
||||||
last_frame[1] = f
|
|
||||||
last_pos[1] = p
|
|
||||||
last_angle[1] = self.orientations[idx]
|
|
||||||
continue
|
|
||||||
if f < last_frame[1]:
|
|
||||||
last_frame[0] = f
|
|
||||||
last_pos[0] = p
|
|
||||||
last_angle[0] = self.orientations[idx]
|
|
||||||
self.tracks[idx] = 1
|
|
||||||
continue
|
|
||||||
# else, we have already seen track one and track two entries
|
|
||||||
distance_to_trackone = np.linalg.norm(p - last_pos[0])/(f - last_frame[0])
|
|
||||||
distance_to_tracktwo = np.linalg.norm(p - last_pos[1])/(f - last_frame[1])
|
|
||||||
most_likely_track = np.argmin([distance_to_trackone, distance_to_tracktwo]) + 1
|
|
||||||
distances[i, 0] = distance_to_trackone
|
|
||||||
distances[i, 1] = distance_to_tracktwo
|
|
||||||
assignments[i] = most_likely_track
|
|
||||||
# check (re) assignment update and proceed
|
|
||||||
if len(assignments) > 1 and (np.all(assignments == 1) or np.all(assignments == 2)):
|
|
||||||
logging.warning("frame %i: Issues assigning based on distances %s", f, str(distances))
|
|
||||||
assignment_error = True
|
|
||||||
errors += 1
|
|
||||||
else:
|
|
||||||
processed += 1
|
|
||||||
for i, idx in enumerate(indices):
|
|
||||||
if assignment_error:
|
|
||||||
self.tracks[idx] = -1
|
|
||||||
else:
|
|
||||||
self.tracks[idx] = assignments[i]
|
|
||||||
last_pos[assignments[i]-1] = pp[i]
|
|
||||||
last_frame[assignments[i]-1] = f
|
|
||||||
assignment_error = False
|
|
||||||
if f % steps == 0:
|
|
||||||
progress += 1
|
|
||||||
self.signals.progress.emit(progress, processed, errors)
|
|
||||||
|
|
||||||
self.signals.finished.emit(True)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SizeClassifier(QWidget):
|
class SizeClassifier(QWidget):
|
||||||
apply = Signal()
|
apply = Signal()
|
||||||
@ -290,144 +202,63 @@ class ConsistencyClassifier(QWidget):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._data = None
|
|
||||||
self._all_cogs = None
|
|
||||||
self._all_orientations = None
|
|
||||||
self._all_lengths = None
|
|
||||||
self._all_bendedness = None
|
|
||||||
self._all_scores = None
|
|
||||||
self._frames = None
|
|
||||||
self._tracks = None
|
|
||||||
self._worker = None
|
|
||||||
|
|
||||||
self._errorlabel = QLabel()
|
|
||||||
self._errorlabel.setStyleSheet("QLabel { color : red; }")
|
|
||||||
self._assignedlabel = QLabel()
|
|
||||||
self._startframe_spinner = QSpinBox()
|
|
||||||
|
|
||||||
self._startbtn = QPushButton("run")
|
|
||||||
self._startbtn.clicked.connect(self.run)
|
|
||||||
self._startbtn.setEnabled(False)
|
|
||||||
|
|
||||||
self._cancelbtn = QPushButton("cancel")
|
def setData(self, keypoints, tracks, frames):
|
||||||
self._cancelbtn.clicked.connect(self.cancel)
|
|
||||||
self._cancelbtn.setEnabled(False)
|
|
||||||
self._apply_btn = QPushButton("apply")
|
|
||||||
|
|
||||||
self._progressbar = QProgressBar()
|
|
||||||
self._progressbar.setMinimum(0)
|
|
||||||
self._progressbar.setMaximum(100)
|
|
||||||
|
|
||||||
self._apply_btn.clicked.connect(lambda: self.apply.emit())
|
|
||||||
self._apply_btn.setEnabled(False)
|
|
||||||
self.threadpool = QThreadPool()
|
|
||||||
|
|
||||||
lyt = QGridLayout()
|
|
||||||
lyt.addWidget(QLabel("Start frame:"), 0, 0 )
|
|
||||||
lyt.addWidget(self._startframe_spinner, 0, 1 )
|
|
||||||
lyt.addWidget(QLabel("assigned"), 1, 0)
|
|
||||||
lyt.addWidget(self._assignedlabel, 1, 1)
|
|
||||||
lyt.addWidget(QLabel("errors/issues"), 2, 0)
|
|
||||||
lyt.addWidget(self._errorlabel, 2, 1)
|
|
||||||
|
|
||||||
lyt.addWidget(self._startbtn, 3, 0)
|
|
||||||
lyt.addWidget(self._cancelbtn, 3, 1)
|
|
||||||
lyt.addWidget(self._progressbar, 4, 0, 1, 2)
|
|
||||||
lyt.addWidget(self._apply_btn, 5, 0, 1, 2)
|
|
||||||
self.setLayout(lyt)
|
|
||||||
|
|
||||||
def setData(self, data:TrackingData):
|
|
||||||
"""Set the data, the classifier/should be working on.
|
"""Set the data, the classifier/should be working on.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
data : Trackingdata
|
positions : np.ndarray
|
||||||
The tracking data.
|
The position estimates, e.g. the center of gravity for each detection
|
||||||
|
tracks : np.ndarray
|
||||||
|
The current track assignment.
|
||||||
|
frames : np.ndarray
|
||||||
|
respective frame.
|
||||||
"""
|
"""
|
||||||
|
def mouseClicked(event):
|
||||||
|
pos = event.pos()
|
||||||
|
if self._plot.sceneBoundingRect().contains(pos):
|
||||||
|
mousePoint = vb.mapSceneToView(pos)
|
||||||
|
print("mouse clicked at", mousePoint)
|
||||||
|
vLine.setPos(mousePoint.x())
|
||||||
|
track2_brush = QBrush(QColor.fromString("green"))
|
||||||
|
track1_brush = QBrush(QColor.fromString("orange"))
|
||||||
|
self._positions = positions
|
||||||
|
self._tracks = tracks
|
||||||
|
self._frames = frames
|
||||||
|
t1_positions = self._positions[self._tracks == 1]
|
||||||
|
t1_frames = self._frames[self._tracks == 1]
|
||||||
|
t1_distances = self.neighborDistances(t1_positions, t1_frames, 1, False)
|
||||||
|
t2_positions = self._positions[self._tracks == 2]
|
||||||
|
t2_frames = self._frames[self._tracks == 2]
|
||||||
|
t2_distances = self.neighborDistances(t2_positions, t2_frames, 1, False)
|
||||||
|
|
||||||
self._all_cogs = data.centerOfGravity()
|
|
||||||
self._all_orientations = data.orientation()
|
|
||||||
self._all_lengths = data.animalLength()
|
|
||||||
self._all_bendedness = data.bendedness()
|
|
||||||
self._all_scores = data["confidence"] # ignore for now, let's see how far this carries.
|
|
||||||
self._frames = data["frame"]
|
|
||||||
self._tracks = data["track"]
|
|
||||||
min_frame = max([self._frames[self._tracks == 1][0], self._frames[self._tracks == 2][0]]) + 1
|
|
||||||
self._startframe_spinner.setMinimum(min_frame)
|
|
||||||
self._startframe_spinner.setMaximum(self._frames[-1])
|
|
||||||
self._startframe_spinner.setValue(self._frames[0] + 1)
|
|
||||||
self._startbtn.setEnabled(True)
|
|
||||||
self._worker = None
|
|
||||||
|
|
||||||
@Slot(float)
|
|
||||||
def on_progress(self, value):
|
|
||||||
if self._progressbar is not None:
|
|
||||||
self._progressDialog.setValue(int(value * 100))
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
if self._worker is not None:
|
|
||||||
self._worker.cancel()
|
|
||||||
self._startbtn.setEnabled(True)
|
|
||||||
self._cancelbtn.setEnabled(False)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self._startbtn.setEnabled(False)
|
|
||||||
self._cancelbtn.setEnabled(True)
|
|
||||||
self._worker = ConsistencyWorker(self._all_cogs, self._all_orientations, self._all_lengths,
|
|
||||||
self._all_bendedness, self._frames, self._tracks, self._startframe_spinner.value())
|
|
||||||
self._worker.signals.finished.connect(self.worker_done)
|
|
||||||
self._worker.signals.progress.connect(self.worker_progress)
|
|
||||||
self.threadpool.start(self._worker)
|
|
||||||
|
|
||||||
def worker_progress(self, progress, processed, errors):
|
|
||||||
self._progressbar.setValue(progress)
|
|
||||||
self._errorlabel.setText(str(errors))
|
|
||||||
self._assignedlabel.setText(str(processed))
|
|
||||||
|
|
||||||
def worker_done(self):
|
|
||||||
self._apply_btn.setEnabled(True)
|
|
||||||
self._startbtn.setEnabled(True)
|
|
||||||
self._cancelbtn.setEnabled(False)
|
|
||||||
|
|
||||||
def assignedTracks(self):
|
|
||||||
return self._tracks
|
|
||||||
|
|
||||||
class ClassifierWidget(QTabWidget):
|
class ClassifierWidget(QTabWidget):
|
||||||
apply_classifier = Signal(np.ndarray)
|
apply_sizeclassifier = Signal(np.ndarray)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._data = None
|
|
||||||
self._size_classifier = SizeClassifier()
|
self._size_classifier = SizeClassifier()
|
||||||
# self._neigborhood_validator = NeighborhoodValidator()
|
self._neigborhood_validator = NeighborhoodValidator()
|
||||||
self._consistency_tracker = ConsistencyClassifier()
|
|
||||||
self.addTab(self._size_classifier, SizeClassifier.name)
|
self.addTab(self._size_classifier, SizeClassifier.name)
|
||||||
self.addTab(self._consistency_tracker, ConsistencyClassifier.name)
|
self.addTab(self._neigborhood_validator, NeighborhoodValidator.name)
|
||||||
self.tabBarClicked.connect(self.update)
|
|
||||||
self._size_classifier.apply.connect(self._on_applySizeClassifier)
|
self._size_classifier.apply.connect(self._on_applySizeClassifier)
|
||||||
self._consistency_tracker.apply.connect(self._on_applyConsistencyTracker)
|
|
||||||
|
|
||||||
def _on_applySizeClassifier(self):
|
def _on_applySizeClassifier(self):
|
||||||
tracks = self.size_classifier.assignedTracks()
|
tracks = self.size_classifier.assignedTracks()
|
||||||
self.apply_classifier.emit(tracks)
|
self.apply_sizeclassifier.emit(tracks)
|
||||||
|
|
||||||
def _on_applyConsistencyTracker(self):
|
|
||||||
tracks = self._consistency_tracker.assignedTracks()
|
|
||||||
self.apply_classifier.emit(tracks)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size_classifier(self):
|
def size_classifier(self):
|
||||||
return self._size_classifier
|
return self._size_classifier
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def consistency_tracker(self):
|
def neighborhood_validator(self):
|
||||||
return self._consistency_tracker
|
return self._neigborhood_validator
|
||||||
|
|
||||||
def update(self):
|
|
||||||
self.consistency_tracker.setData(self._data)
|
|
||||||
|
|
||||||
def setData(self, data:TrackingData):
|
|
||||||
self._data = data
|
|
||||||
|
|
||||||
def as_dict(df):
|
def as_dict(df):
|
||||||
d = {c: df[c].values for c in df.columns}
|
d = {c: df[c].values for c in df.columns}
|
||||||
@ -438,9 +269,8 @@ def as_dict(df):
|
|||||||
def main():
|
def main():
|
||||||
test_size = False
|
test_size = False
|
||||||
import pickle
|
import pickle
|
||||||
from IPython import embed
|
|
||||||
from fixtracks.info import PACKAGE_ROOT
|
from fixtracks.info import PACKAGE_ROOT
|
||||||
|
|
||||||
datafile = PACKAGE_ROOT / "data/merged_small_tracked.pkl"
|
datafile = PACKAGE_ROOT / "data/merged_small_tracked.pkl"
|
||||||
|
|
||||||
with open(datafile, "rb") as f:
|
with open(datafile, "rb") as f:
|
||||||
@ -448,6 +278,11 @@ def main():
|
|||||||
data = TrackingData()
|
data = TrackingData()
|
||||||
data.setData(as_dict(df))
|
data.setData(as_dict(df))
|
||||||
|
|
||||||
|
positions = data.centerOfGravity()
|
||||||
|
tracks = data["track"]
|
||||||
|
frames = data["frame"]
|
||||||
|
coords = data.coordinates()
|
||||||
|
|
||||||
app = QApplication([])
|
app = QApplication([])
|
||||||
window = QWidget()
|
window = QWidget()
|
||||||
window.setMinimumSize(200, 200)
|
window.setMinimumSize(200, 200)
|
||||||
@ -456,7 +291,7 @@ def main():
|
|||||||
# win.setCoordinates(coords)
|
# win.setCoordinates(coords)
|
||||||
# else:
|
# else:
|
||||||
w = ClassifierWidget()
|
w = ClassifierWidget()
|
||||||
w.setData(data)
|
w.neighborhood_validator.setData(positions, tracks, frames)
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
layout.addWidget(w)
|
layout.addWidget(w)
|
||||||
|
@ -254,7 +254,7 @@ class FixTracks(QWidget):
|
|||||||
btnBox.addWidget(self._saveBtn)
|
btnBox.addWidget(self._saveBtn)
|
||||||
|
|
||||||
self._classifier = ClassifierWidget()
|
self._classifier = ClassifierWidget()
|
||||||
self._classifier.apply_classifier.connect(self.on_autoClassify)
|
self._classifier.apply_sizeclassifier.connect(self.on_classifyBySize)
|
||||||
self._classifier.setMaximumWidth(500)
|
self._classifier.setMaximumWidth(500)
|
||||||
cntrlBox = QHBoxLayout()
|
cntrlBox = QHBoxLayout()
|
||||||
cntrlBox.addWidget(self._classifier)
|
cntrlBox.addWidget(self._classifier)
|
||||||
@ -278,7 +278,7 @@ class FixTracks(QWidget):
|
|||||||
layout.addWidget(splitter)
|
layout.addWidget(splitter)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
def on_autoClassify(self, tracks):
|
def on_classifyBySize(self, tracks):
|
||||||
self._data.setSelectionRange("index", 0, self._data.numDetections)
|
self._data.setSelectionRange("index", 0, self._data.numDetections)
|
||||||
self._data.assignTracks(tracks)
|
self._data.assignTracks(tracks)
|
||||||
self._timeline.setDetectionData(self._data.data)
|
self._timeline.setDetectionData(self._data.data)
|
||||||
@ -333,7 +333,6 @@ class FixTracks(QWidget):
|
|||||||
update_detectionView(unassigned, "unassigned")
|
update_detectionView(unassigned, "unassigned")
|
||||||
update_detectionView(assigned_left, "assigned_left")
|
update_detectionView(assigned_left, "assigned_left")
|
||||||
update_detectionView(assigned_right, "assigned_right")
|
update_detectionView(assigned_right, "assigned_right")
|
||||||
self._classifier.setData(self._data)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fileList(self):
|
def fileList(self):
|
||||||
@ -370,7 +369,6 @@ class FixTracks(QWidget):
|
|||||||
self._progress_bar.setValue(0)
|
self._progress_bar.setValue(0)
|
||||||
if state and self._reader is not None:
|
if state and self._reader is not None:
|
||||||
self._data.setData(self._reader.asdict)
|
self._data.setData(self._reader.asdict)
|
||||||
self._saveBtn.setEnabled(True)
|
|
||||||
self._currentWindowPos = 0
|
self._currentWindowPos = 0
|
||||||
self._currentWindowWidth = self._windowspinner.value()
|
self._currentWindowWidth = self._windowspinner.value()
|
||||||
self._maxframes = self._data.max("frame")
|
self._maxframes = self._data.max("frame")
|
||||||
@ -383,8 +381,9 @@ class FixTracks(QWidget):
|
|||||||
tracks = self._data["track"]
|
tracks = self._data["track"]
|
||||||
frames = self._data["frame"]
|
frames = self._data["frame"]
|
||||||
self._classifier.size_classifier.setCoordinates(coordinates)
|
self._classifier.size_classifier.setCoordinates(coordinates)
|
||||||
self._classifier.consistency_tracker.setData(self._data)
|
self._classifier.neighborhood_validator.setData(positions, tracks, frames)
|
||||||
self.update()
|
self.update()
|
||||||
|
self._saveBtn.setEnabled(True)
|
||||||
logging.info("Finished loading data: %i frames, %i detections", self._maxframes, len(positions))
|
logging.info("Finished loading data: %i frames, %i detections", self._maxframes, len(positions))
|
||||||
|
|
||||||
def on_keypointSelected(self):
|
def on_keypointSelected(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user