From 6088cb103ccda18d125a044778c82068120565cf Mon Sep 17 00:00:00 2001 From: Bryon Lewis Date: Fri, 7 Jan 2022 16:01:44 -0500 Subject: [PATCH 01/22] figuring stuff out by breaking it --- client/dive-common/components/Viewer.vue | 31 +++-- .../annotators/AnnotatorWrapper.vue | 110 ++++++++++++++++++ client/src/components/index.ts | 2 + client/src/use/useTrackStore.ts | 11 +- 4 files changed, 136 insertions(+), 18 deletions(-) create mode 100644 client/src/components/annotators/AnnotatorWrapper.vue diff --git a/client/dive-common/components/Viewer.vue b/client/dive-common/components/Viewer.vue index 76e44df32..7f6e052db 100644 --- a/client/dive-common/components/Viewer.vue +++ b/client/dive-common/components/Viewer.vue @@ -22,6 +22,7 @@ import { ImageAnnotator, VideoAnnotator, LayerManager, + AnnotatorWrapper, } from 'vue-media-annotator/components'; import { MediaController } from 'vue-media-annotator/components/annotators/mediaControllerType'; @@ -52,6 +53,7 @@ export default defineComponent({ LayerManager, VideoAnnotator, ImageAnnotator, + AnnotatorWrapper, ConfidenceFilter, UserGuideButton, EditorMenu, @@ -77,9 +79,9 @@ export default defineComponent({ const loadError = ref(''); const baseMulticamDatasetId = ref(null as string | null); const datasetId = toRef(props, 'id'); - const multiCamList: Ref = ref([]); - const defaultCamera = ref(''); - const currentCamera = ref(''); + const multiCamList: Ref = ref(['default']); + const defaultCamera = ref('default'); + const currentCamera = ref('default'); const playbackComponent = ref(undefined as Vue | undefined); const readonlyState = computed(() => props.readonlyMode || props.revision !== undefined); const mediaController = computed(() => { @@ -93,11 +95,11 @@ export default defineComponent({ return {} as MediaController; }); const { time, updateTime, initialize: initTime } = useTimeObserver(); - const imageData = ref([] as FrameImage[]); + const imageData = ref({ default: [] } as Record); const datasetType: Ref = ref('image-sequence'); const datasetName = ref(''); const saveInProgress = ref(false); - const videoUrl = ref(undefined as undefined | string); + const videoUrl = ref({ default: null } as Record); const { loadDetections, loadMetadata, saveMetadata } = useApi(); const progress = reactive({ // Loaded flag prevents annotator window from populating @@ -343,8 +345,8 @@ export default defineComponent({ frameRate: meta.fps, originalFps: meta.originalFps || null, }); - imageData.value = cloneDeep(meta.imageData) as FrameImage[]; - videoUrl.value = meta.videoUrl; + imageData.value[currentCamera.value] = cloneDeep(meta.imageData) as FrameImage[]; + videoUrl.value[currentCamera.value] = meta.videoUrl || null; datasetType.value = meta.type as DatasetType; const trackData = await loadDetections(datasetId.value, props.revision); @@ -588,15 +590,11 @@ export default defineComponent({ - @@ -606,8 +604,7 @@ export default defineComponent({ @select-track="handler.trackSelect" /> - - +
+import { + defineComponent, ref, onUnmounted, PropType, toRef, watch, +} from '@vue/composition-api'; +import { DatasetType } from 'dive-common/apispec'; +import { + ImageAnnotator, + VideoAnnotator, + LayerManager, +} from 'vue-media-annotator/components'; +import { SetTimeFunc } from '../use/useTimeObserver'; +import { ImageDataItem } from './annotators/ImageAnnotator.vue'; + +function loadImageFunc(imageDataItem: ImageDataItem, img: HTMLImageElement) { + // eslint-disable-next-line no-param-reassign + img.src = imageDataItem.url; +} + + +export default defineComponent({ + name: 'AnnotationWrapper', + components: { + VideoAnnotator, + ImageAnnotator, + LayerManager, + }, + props: { + datasetType: { + type: String as PropType, + required: true, + }, + cameras: { + type: Array as PropType, + required: true, + }, + currentCamera: { + type: String, + required: true, + }, + imageData: { + type: Object as PropType>, + required: true, + }, + videoUrl: { + type: Object as PropType>, + required: true, + }, + videoPlayerAttributes: { + type: Object as PropType<{ [key: string]: string }>, + default: () => ({}), + }, + frameRate: { + type: Number, + required: true, + }, + updateTime: { + type: Function as PropType, + required: true, + }, + loadImageFunc: { + type: Function as PropType<(imageDataItem: ImageDataItem, img: HTMLImageElement) => void>, + default: loadImageFunc, + }, + // Range is [0, inf.) + brightness: { + type: Number as PropType, + default: undefined, + }, + }, + + setup(props) { + // We + return { + + }; + }, +}); + + + + + diff --git a/client/src/components/index.ts b/client/src/components/index.ts index 562a71884..be892bf5d 100644 --- a/client/src/components/index.ts +++ b/client/src/components/index.ts @@ -6,6 +6,7 @@ import ImageAnnotator from './annotators/ImageAnnotator.vue'; import VideoAnnotator from './annotators/VideoAnnotator.vue'; +import AnnotatorWrapper from './annotators/AnnotatorWrapper.vue'; import Controls from './controls/Controls.vue'; import EventChart from './controls/EventChart.vue'; @@ -27,6 +28,7 @@ export { LineChart, Timeline, LayerManager, + AnnotatorWrapper, TooltipButton, TrackItem, TrackList, diff --git a/client/src/use/useTrackStore.ts b/client/src/use/useTrackStore.ts index a47062e74..2195ba65d 100644 --- a/client/src/use/useTrackStore.ts +++ b/client/src/use/useTrackStore.ts @@ -17,6 +17,7 @@ interface UseTrackStoreParams { interface InsertArgs { imported?: boolean; afterId?: TrackId; + cameraName?: string; } export function getTrack( @@ -57,6 +58,9 @@ export default function useTrackStore({ markChangesPending }: UseTrackStoreParam const trackIds: Ref> = ref([]); const canary = ref(0); + // Multi-Camera Support + const camTrackMap: Record> = { base: new Map() }; + // internval Tree should be the same because all overlapping tracks have the same Id and length function _depend(): number { return canary.value; @@ -84,7 +88,12 @@ export default function useTrackStore({ markChangesPending }: UseTrackStoreParam function insertTrack(track: Track, args?: InsertArgs) { track.setNotifier(onChange); - trackMap.set(track.trackId, track); + if (args?.cameraName !== undefined) { + if (camTrackMap[args.cameraName] === undefined) { + camTrackMap[args.cameraName] = new Map(); + } + camTrackMap[args.cameraName].set(track.trackId, track); + } intervalTree.insert([track.begin, track.end], track.trackId.toString()); if (args && args.afterId) { /* Insert specifically after another trackId */ From edc4e4cde393025ee3c12aa89a3b4f2434c9a8c2 Mon Sep 17 00:00:00 2001 From: Bryon Lewis Date: Wed, 12 Jan 2022 14:39:14 -0500 Subject: [PATCH 02/22] need to redo useMediaController --- client/dive-common/components/Viewer.vue | 8 +- .../annotators/AnnotatorWrapper.vue | 85 ++++++++++++++----- .../annotators/subMediaController.ts | 0 client/src/use/useTrackStore.ts | 2 + 4 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 client/src/components/annotators/subMediaController.ts diff --git a/client/dive-common/components/Viewer.vue b/client/dive-common/components/Viewer.vue index 7f6e052db..fcdef96b8 100644 --- a/client/dive-common/components/Viewer.vue +++ b/client/dive-common/components/Viewer.vue @@ -1,6 +1,6 @@ diff --git a/client/dive-common/components/Viewer.vue b/client/dive-common/components/Viewer.vue index edd362919..1032d498f 100644 --- a/client/dive-common/components/Viewer.vue +++ b/client/dive-common/components/Viewer.vue @@ -18,9 +18,6 @@ import { } from 'vue-media-annotator/use'; import { getTrack } from 'vue-media-annotator/use/useTrackStore'; import { provideAnnotator } from 'vue-media-annotator/provides'; -import { - AnnotatorWrapper, -} from 'vue-media-annotator/components'; import { MediaControlAggregator } from 'vue-media-annotator/components/annotators/mediaControllerType'; /* DIVE COMMON */ @@ -40,6 +37,7 @@ import { usePrompt } from 'dive-common/vue-utilities/prompt-service'; import { cloneDeep } from 'lodash'; import { getResponseError } from 'vue-media-annotator/utils'; import context from 'dive-common/store/context'; +import AnnotatorWrapper from './AnnotatorWrapper.vue'; export default defineComponent({ components: { diff --git a/client/src/components/annotators/annotator.scss b/client/src/components/annotators/annotator.scss index 4a466879b..b10c75a74 100644 --- a/client/src/components/annotators/annotator.scss +++ b/client/src/components/annotators/annotator.scss @@ -1,13 +1,3 @@ -.annotator-wrapper { - position: relative; - left: 0; - right: 0; - top: 0; - bottom: 0; - z-index: 0; - display: flex; - flex-direction: column; -} .controls { position: absolute; From 6ae400dc450800165be1245212dbb1dd4f87af59 Mon Sep 17 00:00:00 2001 From: Brandon Davis Date: Fri, 25 Feb 2022 10:02:13 -0500 Subject: [PATCH 12/22] Variation on MultiCam Media Controller (#1171) * WIP * Doneish * WIP --- .../components/AnnotatorWrapper.vue | 196 ---------- .../components/ConfidenceFilter.vue | 4 +- .../components/ControlsContainer.vue | 25 +- client/dive-common/components/Sidebar.vue | 12 +- client/dive-common/components/Viewer.vue | 146 ++++--- client/dive-common/use/useModeManager.ts | 20 +- client/dive-common/use/useRequest.ts | 3 +- client/src/components/LayerManager.vue | 4 +- .../components/annotators/ImageAnnotator.vue | 42 +- .../components/annotators/VideoAnnotator.vue | 37 +- .../src/components/annotators/annotator.scss | 6 +- .../annotators/mediaControllerType.ts | 79 ++-- .../annotators/useMediaController.ts | 361 ++++++++++-------- client/src/components/controls/Controls.vue | 19 +- .../controls/FileNameTimeDisplay.vue | 27 +- 15 files changed, 423 insertions(+), 558 deletions(-) delete mode 100644 client/dive-common/components/AnnotatorWrapper.vue diff --git a/client/dive-common/components/AnnotatorWrapper.vue b/client/dive-common/components/AnnotatorWrapper.vue deleted file mode 100644 index f527276f2..000000000 --- a/client/dive-common/components/AnnotatorWrapper.vue +++ /dev/null @@ -1,196 +0,0 @@ - - - - - diff --git a/client/dive-common/components/ConfidenceFilter.vue b/client/dive-common/components/ConfidenceFilter.vue index 915d1d899..34596543b 100644 --- a/client/dive-common/components/ConfidenceFilter.vue +++ b/client/dive-common/components/ConfidenceFilter.vue @@ -25,9 +25,7 @@ export default defineComponent({ setup(props, { emit }) { function _updateConfidence(event: InputEvent) { if (event.target) { - // eslint-disable-next-line @typescript-eslint/ban-ts-ignore - // @ts-ignore - emit('update:confidence', Number.parseFloat(event.target.value)); + emit('update:confidence', Number.parseFloat((event.target as HTMLInputElement).value)); } } function _emitEnd() { diff --git a/client/dive-common/components/ControlsContainer.vue b/client/dive-common/components/ControlsContainer.vue index de8921aa0..7470b7664 100644 --- a/client/dive-common/components/ControlsContainer.vue +++ b/client/dive-common/components/ControlsContainer.vue @@ -1,16 +1,16 @@