Compare commits
4 Commits
9d38421e02
...
d1b5776e69
Author | SHA1 | Date | |
---|---|---|---|
d1b5776e69 | |||
4a76655766 | |||
ae24463be2 | |||
15264dbe48 |
@ -8,6 +8,7 @@ class DetectionData(Enum):
|
||||
COORDINATES = 2
|
||||
TRACK_ID = 3
|
||||
USERLABELED = 4
|
||||
SCORE = 5
|
||||
|
||||
class Tracks(Enum):
|
||||
TRACKONE = 1
|
||||
|
@ -135,6 +135,16 @@ class ConsistencyWorker(QRunnable):
|
||||
del detections[lowest_dist]
|
||||
return detections
|
||||
|
||||
def find_last_userlabeled(startframe):
|
||||
t1index = np.where((self.frames < startframe) & (self.userlabeled) & (self.tracks == 1))[0][-1]
|
||||
t2index = np.where((self.frames < startframe) & (self.userlabeled) & (self.tracks == 2))[0][-1]
|
||||
d1 = Detection(t1index, self.frames[t1index], self.tracks[t1index], self.positions[t1index],
|
||||
self.orientations[t1index], self.lengths[t1index], self.userlabeled[t1index])
|
||||
d2 = Detection(t1index, self.frames[t2index], self.tracks[t2index], self.positions[t2index],
|
||||
self.orientations[t2index], self.lengths[t2index], self.userlabeled[t2index])
|
||||
last_detections[1] = d1
|
||||
last_detections[2] = d2
|
||||
|
||||
unique_frames = np.unique(self.frames)
|
||||
steps = int((len(unique_frames) - self._startframe) // 100)
|
||||
errors = 0
|
||||
@ -142,6 +152,7 @@ class ConsistencyWorker(QRunnable):
|
||||
progress = 0
|
||||
self._stoprequest = False
|
||||
last_detections = {1: None, 2: None, -1: None}
|
||||
find_last_userlabeled(self._startframe)
|
||||
|
||||
for f in unique_frames[unique_frames >= self._startframe]:
|
||||
if self._stoprequest:
|
||||
@ -188,7 +199,7 @@ class ConsistencyWorker(QRunnable):
|
||||
continue
|
||||
|
||||
if error and self._stoponerror:
|
||||
self.signals.message.emit("Tracking stopped at frame %i.", f)
|
||||
self.signals.message.emit(f"Tracking stopped at frame {f}.")
|
||||
break
|
||||
elif error:
|
||||
continue
|
||||
@ -559,8 +570,11 @@ class ConsistencyClassifier(QWidget):
|
||||
self._messagebox.append("Error preparing data! Make sure that the first user-labeled frames contain both tracks!")
|
||||
self.setEnabled(False)
|
||||
return
|
||||
max_startframe = np.min([t1_userlabeled[-1], t2_userlabeled[-1]])
|
||||
min_startframe = np.max([t1_userlabeled[0], t2_userlabeled[0]])
|
||||
max_startframe = np.min([t1_userlabeled[-1], t2_userlabeled[-1]]) -1
|
||||
first_guess = np.max([t1_userlabeled[0], t2_userlabeled[0]])
|
||||
while first_guess not in t1_userlabeled or first_guess not in t2_userlabeled:
|
||||
first_guess += 1
|
||||
min_startframe = first_guess + 1
|
||||
self._maxframes = np.max(self._frames)
|
||||
self._maxframeslabel.setText(str(self._maxframes))
|
||||
self._startframe_spinner.setMinimum(min_startframe)
|
||||
|
@ -10,6 +10,7 @@ from fixtracks.utils.signals import DetectionSignals, DetectionViewSignals, Dete
|
||||
from fixtracks.utils.enums import DetectionData, Tracks
|
||||
from fixtracks.utils.trackingdata import TrackingData
|
||||
|
||||
|
||||
class Detection(QGraphicsEllipseItem):
|
||||
signals = DetectionSignals()
|
||||
|
||||
@ -138,10 +139,11 @@ class DetectionView(QWidget):
|
||||
coordinates = self._data.coordinates(selection=True)
|
||||
centercoordinates = self._data.centerOfGravity(selection=True)
|
||||
userlabeled = self._data.selectedData("userlabeled")
|
||||
scores = self._data.selectedData("confidence")
|
||||
|
||||
image_rect = self._pixmapitem.boundingRect() if self._pixmapitem is not None else QRectF(0,0,0,0)
|
||||
|
||||
for i, (id, f, t, l) in enumerate(zip(ids, frames, tracks, userlabeled)):
|
||||
for i, (id, f, t, l, s) in enumerate(zip(ids, frames, tracks, userlabeled, scores)):
|
||||
c = Tracks.fromValue(t).toColor()
|
||||
if keypoint >= 0:
|
||||
x = coordinates[i, keypoint, 0]
|
||||
@ -155,7 +157,10 @@ class DetectionView(QWidget):
|
||||
item.setData(DetectionData.ID.value, id)
|
||||
item.setData(DetectionData.COORDINATES.value, coordinates[i, :, :])
|
||||
item.setData(DetectionData.FRAME.value, f)
|
||||
item.setData(DetectionData.USERLABELED.value, l)
|
||||
# item.setData(DetectionData.USERLABELED.value, l)
|
||||
item.setData(DetectionData.SCORE.value, s)
|
||||
print(s)
|
||||
print(item.data(DetectionData.SCORE.value))
|
||||
item = self._scene.addItem(item)
|
||||
|
||||
def fit_image_to_view(self):
|
||||
@ -214,7 +219,7 @@ def main():
|
||||
view.setImage(img)
|
||||
view.addDetections(bg_coords, bg_tracks, bg_ids, background_brush)
|
||||
view.addDetections(focus_coords, focus_tracks, focus_ids, focus_brush)
|
||||
view.addDetections(scnd_coords, scnd_tracks, scnd_ids, second_brush)
|
||||
view.addDetections(scnd_coords, scnd_tracks, scnd_ids, second_brush)
|
||||
window.setLayout(layout)
|
||||
window.show()
|
||||
app.exec()
|
||||
|
@ -52,7 +52,6 @@ class SelectionControls(QWidget):
|
||||
quarterstepBackBtn.setStyleSheet(pushBtnStyle("darkgray"))
|
||||
quarterstepBackBtn.clicked.connect(lambda: self.on_Back(quarterstep))
|
||||
|
||||
|
||||
fwdBtn = QPushButton(">>|")
|
||||
fwdBtn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||
fwdBtn.setShortcut(Qt.Key.Key_Right)
|
||||
@ -173,7 +172,7 @@ class SelectionControls(QWidget):
|
||||
grid.setColumnStretch(0, 1)
|
||||
grid.setColumnStretch(7, 1)
|
||||
self.setLayout(grid)
|
||||
self.setMaximumSize(QSize(500, 500))
|
||||
# self.setMaximumSize(QSize(500, 500))
|
||||
|
||||
def setWindow(self, start:int=0, end:int=0):
|
||||
self.startframe.setText(f"{start:.0f}")
|
||||
|
@ -94,7 +94,8 @@ class SkeletonWidget(QWidget):
|
||||
i = s.data(DetectionData.ID.value)
|
||||
t = s.data(DetectionData.TRACK_ID.value)
|
||||
f = s.data(DetectionData.FRAME.value)
|
||||
self._info_label.setText(f"Id {i}, track {t} on frame {f}, length {l:.1f} px")
|
||||
sc = s.data(DetectionData.SCORE.value)
|
||||
self._info_label.setText(f"Id {i}, track {t} on frame {f}, length {l:.1f} px, confidence {sc:.2f}")
|
||||
else:
|
||||
self._info_label.setText("")
|
||||
|
||||
@ -129,7 +130,7 @@ class SkeletonWidget(QWidget):
|
||||
self._scene.setSceneRect(self._minx, self._miny, self._maxx - self._minx, self._maxy - self._miny)
|
||||
self._view.fitInView(self._scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
|
||||
|
||||
def addSkeleton(self, coords, detection_id, frame, track, brush, update=True):
|
||||
def addSkeleton(self, coords, detection_id, frame, track, score, brush, update=True):
|
||||
def check_extent(x, y, w, h):
|
||||
if x == 0 and y == 0:
|
||||
return
|
||||
@ -157,12 +158,14 @@ class SkeletonWidget(QWidget):
|
||||
item.setData(DetectionData.ID.value, detection_id)
|
||||
item.setData(DetectionData.TRACK_ID.value, track)
|
||||
item.setData(DetectionData.FRAME.value, frame)
|
||||
item.setData(DetectionData.SCORE.value, score)
|
||||
self._skeletons.append(item)
|
||||
if update:
|
||||
self.update()
|
||||
|
||||
def addSkeletons(self, coordinates:np.ndarray, detection_ids:np.ndarray,
|
||||
frames:np.ndarray, tracks:np.ndarray, brush:QBrush):
|
||||
frames:np.ndarray, tracks:np.ndarray, scores:np.ndarray,
|
||||
brush:QBrush):
|
||||
num_detections = 0 if coordinates is None else coordinates.shape[0]
|
||||
logging.debug("SkeletonWidget: add %i Skeletons", num_detections)
|
||||
if num_detections < 1:
|
||||
@ -172,9 +175,10 @@ class SkeletonWidget(QWidget):
|
||||
detection_ids = detection_ids[sorting]
|
||||
frames = frames[sorting]
|
||||
tracks = tracks[sorting]
|
||||
scores = scores[sorting]
|
||||
for i in range(num_detections):
|
||||
self.addSkeleton(coordinates[i,:,:], detection_ids[i], frames[i],
|
||||
tracks[i], brush=brush, update=False)
|
||||
tracks[i], scores[i], brush=brush, update=False)
|
||||
self.update()
|
||||
|
||||
# def addSkeleton(self, coords, detection_id, brush):
|
||||
|
@ -55,12 +55,23 @@ class FixTracks(QWidget):
|
||||
self._keypointcombo = QComboBox()
|
||||
self._keypointcombo.currentIndexChanged.connect(self.on_keypointSelected)
|
||||
|
||||
self._gotoframe = QSpinBox()
|
||||
self._gotoframe.setSingleStep(1)
|
||||
self._gotobtn = QPushButton("go!")
|
||||
self._gotobtn.setToolTip("Jump to a given frame")
|
||||
self._gotobtn.clicked.connect(self.on_goto)
|
||||
|
||||
combo_layout = QHBoxLayout()
|
||||
combo_layout.addWidget(QLabel("Window width:"))
|
||||
combo_layout.addWidget(self._windowspinner)
|
||||
combo_layout.addWidget(QLabel("frames"))
|
||||
combo_layout.addItem(QSpacerItem(10, 10, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed))
|
||||
combo_layout.addWidget(QLabel("Keypoint:"))
|
||||
combo_layout.addWidget(self._keypointcombo)
|
||||
combo_layout.addItem(QSpacerItem(10, 10, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed))
|
||||
combo_layout.addWidget(QLabel("Jump to frame:"))
|
||||
combo_layout.addWidget(self._gotoframe)
|
||||
combo_layout.addWidget(self._gotobtn)
|
||||
combo_layout.addItem(QSpacerItem(100, 10, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed))
|
||||
|
||||
timelinebox = QVBoxLayout()
|
||||
@ -159,15 +170,19 @@ class FixTracks(QWidget):
|
||||
self._detectionView.setImage(img)
|
||||
|
||||
def update(self):
|
||||
kp = self._keypointcombo.currentText().lower()
|
||||
if len(kp) == 0:
|
||||
return
|
||||
kpi = -1 if "center" in kp else int(kp)
|
||||
|
||||
start_frame = self._currentWindowPos
|
||||
stop_frame = start_frame + self._currentWindowWidth
|
||||
|
||||
self._timeline.setWindow(start_frame / self._maxframes,
|
||||
self._currentWindowWidth/self._maxframes)
|
||||
logging.debug("Tracks:update: Updating View for detection range %i, %i frames", start_frame, stop_frame)
|
||||
self._data.setSelectionRange("frame", start_frame, stop_frame)
|
||||
self._controls_widget.setWindow(start_frame, stop_frame)
|
||||
kp = self._keypointcombo.currentText().lower()
|
||||
kpi = -1 if "center" in kp else int(kp)
|
||||
self._detectionView.updateDetections(kpi)
|
||||
|
||||
@property
|
||||
@ -210,6 +225,7 @@ class FixTracks(QWidget):
|
||||
self._currentWindowPos = 0
|
||||
self._currentWindowWidth = self._windowspinner.value()
|
||||
self._maxframes = np.max(self._data["frame"])
|
||||
self._gotoframe.setMaximum(self._maxframes)
|
||||
self.populateKeypointCombo(self._data.numKeypoints())
|
||||
self._timeline.setData(self._data)
|
||||
# self._timeline.setWindow(self._currentWindowPos / self._maxframes,
|
||||
@ -333,11 +349,22 @@ class FixTracks(QWidget):
|
||||
self._timeline.setWindowWidth(self._currentWindowWidth / self._maxframes)
|
||||
self._controls_widget.setSelectedTracks(None)
|
||||
|
||||
def on_goto(self):
|
||||
target = self._gotoframe.value()
|
||||
if target > self._maxframes - self._currentWindowWidth:
|
||||
target = self._maxframes - self._currentWindowWidth
|
||||
logging.info("Jump to frame %i", target)
|
||||
self._currentWindowPos = target
|
||||
self._timeline.setWindow(self._currentWindowPos / self._maxframes,
|
||||
self._currentWindowWidth / self._maxframes)
|
||||
self.update()
|
||||
|
||||
def on_detectionsSelected(self, detections):
|
||||
logging.debug("Tracks: %i Detections selected", len(detections))
|
||||
tracks = np.zeros(len(detections), dtype=int)
|
||||
ids = np.zeros_like(tracks)
|
||||
frames = np.zeros_like(tracks)
|
||||
scores = np.zeros_like(tracks)
|
||||
coordinates = None
|
||||
if len(detections) > 0:
|
||||
c = detections[0].data(DetectionData.COORDINATES.value)
|
||||
@ -348,15 +375,21 @@ class FixTracks(QWidget):
|
||||
ids[i] = d.data(DetectionData.ID.value)
|
||||
frames[i] = d.data(DetectionData.FRAME.value)
|
||||
coordinates[i, :, :] = d.data(DetectionData.COORDINATES.value)
|
||||
scores[i] = d.data(DetectionData.SCORE.value)
|
||||
print(scores[i])
|
||||
self._data.setSelection(ids)
|
||||
self._controls_widget.setSelectedTracks(tracks)
|
||||
self._skeleton.clear()
|
||||
self._skeleton.addSkeletons(coordinates, ids, frames, tracks, QBrush(QColor(10, 255, 65, 255)))
|
||||
self._skeleton.addSkeletons(coordinates, ids, frames, tracks, scores, QBrush(QColor(10, 255, 65, 255)))
|
||||
|
||||
def moveWindow(self, stepsize):
|
||||
logging.info("Tracks.moveWindow: move window with stepsize %.2f", stepsize)
|
||||
self._manualmove = True
|
||||
new_start_frame = self._currentWindowPos + np.round(stepsize * self._currentWindowWidth)
|
||||
if new_start_frame < 0:
|
||||
new_start_frame = 0
|
||||
elif new_start_frame + self._currentWindowWidth > self._maxframes:
|
||||
new_start_frame = self._maxframes - self._currentWindowWidth
|
||||
self._currentWindowPos = new_start_frame
|
||||
self._controls_widget.setSelectedTracks(None)
|
||||
self.update()
|
||||
|
Loading…
Reference in New Issue
Block a user