Skip to content

Commit

Permalink
improve track 3d viewer
Browse files Browse the repository at this point in the history
- align camera, camera mode, reset camera
- show 3d/2d views at the same time
- better track viewer settings menu (in sidebar)
- use one single lut per track type
- make detection glyph size configurable
- make cube axes actor bounds configurable
- draw detection glyph label with track id

- fix: feature coordinates yz inversion
  • Loading branch information
bourdaisj committed Apr 17, 2024
1 parent 6c8a20f commit 92592d0
Show file tree
Hide file tree
Showing 14 changed files with 908 additions and 289 deletions.
39 changes: 14 additions & 25 deletions client/dive-common/components/Viewer.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<!-- eslint-disable max-len -->
<script lang="ts">
import {
defineComponent, ref, toRef, computed, Ref,
Expand Down Expand Up @@ -50,6 +51,7 @@ import { MarkChangesPendingFilter, TrackWithContext } from 'vue-media-annotator/
import { EditAnnotationTypes, VisibleAnnotationTypes } from 'vue-media-annotator/layers';
import TrackViewer from 'vue-media-annotator/components/track_3d_viewer/TrackViewer.vue';
import TrackViewerSettings from 'vue-media-annotator/components/track_3d_viewer/TrackViewerSettings.vue';
import TrackViewerSettingsStore from 'vue-media-annotator/components/track_3d_viewer/TrackViewerSettingsStore';
import GroupSidebarVue from './GroupSidebar.vue';
import MultiCamToolsVue from './MultiCamTools.vue';
import PrimaryAttributeTrackFilter from './PrimaryAttributeTrackFilter.vue';
Expand Down Expand Up @@ -105,9 +107,6 @@ export default defineComponent({
const loadError = ref('');

const tracks3d = ref(false);
const trackViewerSettings = reactive({
onlyShowSelectedTrack: false,
});

const baseMulticamDatasetId = ref(null as string | null);
const datasetId = toRef(props, 'id');
Expand Down Expand Up @@ -192,6 +191,7 @@ export default defineComponent({
const groupStyleManager = new StyleManager({ markChangesPending, vuetify });

const cameraStore = new CameraStore({ markChangesPending });
const trackViewerSettingsStore = new TrackViewerSettingsStore();
// This context for removal
const removeGroups = (id: AnnotationId) => {
cameraStore.removeGroups(id);
Expand Down Expand Up @@ -758,15 +758,6 @@ export default defineComponent({
watch(datasetId, reloadAnnotations);
watch(readonlyState, () => handler.trackSelect(null, false));

// Handles the case where the user is leaving the 3d viewer, if so, just reloads the view
// in order to avoid broken features
watch(tracks3d, (newTracks3d: boolean, oldTracks3d: boolean) => {
if (oldTracks3d && !newTracks3d) {
reloadAnnotations();
}
});
function handleResize() {
if (controlsRef.value) {
controlsHeight.value = controlsRef.value.$el.clientHeight;
Expand Down Expand Up @@ -881,6 +872,7 @@ export default defineComponent({
annotatorPreferences: toRef(clientSettings, 'annotatorPreferences'),
attributes,
cameraStore,
trackViewerSettingsStore,
datasetId,
editingMode,
groupFilters,
Expand Down Expand Up @@ -973,7 +965,6 @@ export default defineComponent({
onGeometryAdded,
datasetId,
tracks3d,
trackViewerSettings,
};
},
});
Expand Down Expand Up @@ -1096,10 +1087,6 @@ export default defineComponent({
Toggle 3d
</v-btn>

<track-viewer-settings
v-if="tracks3d"
:only-show-selected-track.sync="trackViewerSettings.onlyShowSelectedTrack"
/>
<v-divider
vertical
class="mx-2"
Expand Down Expand Up @@ -1200,20 +1187,22 @@ export default defineComponent({
]"
class="d-flex flex-column grow"
>
<track-viewer
v-if="tracks3d"
:controls-height="controlsHeight"
:only-show-selected-track="trackViewerSettings.onlyShowSelectedTrack"
/>
<div
v-else
class="d-flex grow"
class="d-flex grow flex-wrap"
:style="{ 'max-height': `calc(100% - ${controlsHeight}px)` }"
>
<div
v-if="tracks3d"
:style="{ height: '50%', width: '100%', 'flex-basis': '100%' }"
>
<track-viewer :controls-height="controlsHeight" />
</div>

<div
v-for="camera in multiCamList"
:key="camera"
class="d-flex flex-column grow"
:style="{ height: `calc(100% - ${controlsHeight}px)`}"
:style="tracks3d ? { height: '50%' } : { height: '100%' }"
@mousedown.left="changeCamera(camera, $event)"
@mouseup.right="changeCamera(camera, $event)"
>
Expand Down
4 changes: 4 additions & 0 deletions client/dive-common/store/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import GroupSidebar from 'dive-common/components/GroupSidebar.vue';
import AttributesSideBar from 'dive-common/components/Attributes/AttributesSideBar.vue';
import MultiCamTools from 'dive-common/components/MultiCamTools.vue';
import AttributeTrackFilters from 'vue-media-annotator/components/AttributeTrackFilters.vue';
import TrackViewerSettings from 'vue-media-annotator/components/track_3d_viewer/TrackViewerSettings.vue';

Vue.use(Install);

Expand Down Expand Up @@ -51,6 +52,9 @@ const componentMap: Record<string, ComponentMapItem> = {
[AttributeTrackFilters.name]: {
description: 'Attribute Track Filters',
component: AttributeTrackFilters,
[TrackViewerSettings.name]: {
description: 'Track Viewer Settings',
component: TrackViewerSettings,
},
};

Expand Down
50 changes: 44 additions & 6 deletions client/src/components/track_3d_viewer/TrackManager.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
import { AnnotationId } from 'vue-media-annotator/BaseAnnotation';
import { RGBColor } from './lookupTable';

export type FrameNumber = number;

export type TrackTracker = {
trackActor: vtkActor;
hidden: boolean; // true if the track should remain hidden whatever happens
detectionsMap: Map<FrameNumber, vtkActor>;
trackColor: RGBColor;
trackType: string;
};

export type TracksMap = Map<AnnotationId, TrackTracker>;

export type FramesMap = Map<FrameNumber, {
trackIds: AnnotationId[];
detectionActors: vtkActor[];
}>;

export default class TrackManager {
tracksMap: TracksMap;

framesMap: Map<FrameNumber, vtkActor[]>;
framesMap: FramesMap;

constructor() {
this.tracksMap = new Map();
Expand All @@ -25,29 +33,39 @@ export default class TrackManager {
trackId: AnnotationId,
trackActor: vtkActor,
frameDetections: Array<[FrameNumber, vtkActor]>,
trackColor: RGBColor,
trackType: string,
) {
const detectionsMap = new Map<FrameNumber, vtkActor>();

frameDetections.forEach(([frameNumber, actor]) => {
actor.getProperty().setDiffuse(0.6);
actor.getProperty().setAmbient(0.6);
detectionsMap.set(frameNumber, actor);

const actorList = this.framesMap.get(frameNumber);
const frameTracker = this.framesMap.get(frameNumber);

if (actorList) {
actorList.push(actor);
if (frameTracker) {
frameTracker.trackIds.push(trackId);
frameTracker.detectionActors.push(actor);
} else {
this.framesMap.set(frameNumber, [actor]);
this.framesMap.set(frameNumber, {
trackIds: [trackId],
detectionActors: [actor],
});
}
});

this.tracksMap.set(trackId, {
trackActor,
detectionsMap,
hidden: false, // track should not be hidden by default
trackColor,
trackType,
});
}

getFrameActors(frameNumber: FrameNumber) {
getFrameTracker(frameNumber: FrameNumber) {
return this.framesMap.get(frameNumber);
}

Expand All @@ -70,4 +88,24 @@ export default class TrackManager {
hasTrack(trackId: AnnotationId) {
return this.tracksMap.has(trackId);
}

getTrackActorsInFrameRange(frameStart: number, frameCount: number) {
const trackActors: Set<vtkActor> = new Set();

// eslint-disable-next-line no-plusplus
for (let frame = frameStart; frame < frameStart + frameCount; frame++) {
const frameTracker = this.framesMap.get(frame);

if (frameTracker && frameTracker.trackIds.length > 0) {
frameTracker.trackIds.forEach((trackId) => {
trackActors.add(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.tracksMap.get(trackId)!.trackActor,
);
});
}
}

return trackActors;
}
}
Loading

0 comments on commit 92592d0

Please sign in to comment.