diff --git a/client/dive-common/apispec.ts b/client/dive-common/apispec.ts index 1b5dc03a4..2bfc07c5a 100644 --- a/client/dive-common/apispec.ts +++ b/client/dive-common/apispec.ts @@ -768,6 +768,96 @@ export interface RefineDetectionsResponse { detections?: TextQueryDetection[]; } +/** + * Video Search / IQR (rapid model generation) Types + */ + +export type VideoSearchIndexMethod = 'detections' | 'tracking' | 'existing' | 'frames'; + +/** + * One indexed media stream (video/sequence identifier) in the shared search + * database. All database rows key on this identifier, so a dataset can be + * added, updated, or removed from the index independently. + */ +export interface VideoSearchStreamEntry { + datasetId: string; + method: VideoSearchIndexMethod; + // frame rate the media was indexed at (video only; must match dataset fps) + fps?: number; + createdAt: string; +} + +/** How a search index stores descriptors: per-stream files or an embedded PostgreSQL database. */ +export type SearchIndexBackend = 'files' | 'postgres'; + +/** Sidecar metadata describing the shared search index. */ +export interface VideoSearchIndexMeta { + version: number; + /** Storage backend the index was built with; absent on indexes from before it was recorded (postgres). */ + backend?: SearchIndexBackend; + // stream identifier (as reported in query results) -> source dataset + streams: Record; +} + +export interface VideoSearchIndexStatus { + /** The shared index exists and is queryable (ITQ files present). */ + built: boolean; + /** This dataset has been ingested into the index. */ + indexed: boolean; + /** The stream entry for this dataset, when indexed. */ + stream?: VideoSearchStreamEntry & { streamName: string }; + /** Total datasets in the shared index. */ + datasetCount: number; + meta?: VideoSearchIndexMeta; +} + +export interface VideoSearchTrackState { + frame: number; + bbox?: [number, number, number, number]; +} + +export interface VideoSearchResultTrack { + id: number; + states: VideoSearchTrackState[]; +} + +/** One ranked similarity result returned by the query service. */ +export interface VideoSearchResult { + /** Unique reference for adjudication: ":" */ + ref: string; + /** Federated session index this result came from */ + session: number; + /** Index directory this result came from */ + index_dir: string; + instance_id: number; + query_id: string; + stream_id: string; + relevancy_score: number; + start_frame: number | null; + end_frame: number | null; + tracks: VideoSearchResultTrack[]; +} + +/** One dataset present in the shared search index. */ +export interface VideoSearchIndexInfo { + /** Stream identifier query results report for this dataset */ + streamName: string; + datasetId: string; + /** Dataset display name */ + name: string; + /** How the entry was built. */ + method: VideoSearchIndexMethod; +} + +export interface VideoSearchQueryResponse { + success: boolean; + error?: string; + descriptor_count?: number; + model_available?: boolean; + results?: VideoSearchResult[]; + feedback_requests?: VideoSearchResult[]; +} + export { provideApi, useApi, diff --git a/client/dive-common/components/DatasetPicker.vue b/client/dive-common/components/DatasetPicker.vue index 1750a4afe..a48c9b065 100644 --- a/client/dive-common/components/DatasetPicker.vue +++ b/client/dive-common/components/DatasetPicker.vue @@ -182,7 +182,7 @@ export default defineComponent({ - mdi-check-all + mdi-select-all Select all{{ addable.length ? ` (${addable.length})` : '' }} diff --git a/client/dive-common/components/Review/ReviewCell.vue b/client/dive-common/components/Review/ReviewCell.vue index 17b0e2ac7..567f909c7 100644 --- a/client/dive-common/components/Review/ReviewCell.vue +++ b/client/dive-common/components/Review/ReviewCell.vue @@ -141,6 +141,11 @@ export default defineComponent({ type: String, default: '#00e5ff', }, + /** Outline the cell as accepted or rejected (e.g. search adjudication). */ + highlight: { + type: String as PropType<'' | 'positive' | 'negative'>, + default: '', + }, }, setup(props, { emit }) { /** Chips currently in edit mode, to outline the whole entry. */ @@ -244,7 +249,12 @@ export default defineComponent({ Train a model on the selected datasets @@ -646,18 +651,18 @@ export default defineComponent({ outlined small v-on="on" - @click="scoreSelected" + @click="indexSelected" > - mdi-chart-box-outline + mdi-database-plus - Score + Index - Score the selected datasets against ground truth + Build search indexes for the selected datasets Review the selected datasets' annotations as a grid + + + Score the selected datasets against ground truth +