diff --git a/Dockerfile b/Dockerfile index 2ce2cd35c95d..9323339310ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -73,6 +73,8 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -yq \ apache2 \ libapache2-mod-xsendfile \ + libgomp1 \ + libgl1 \ supervisor \ libldap-2.4-2 \ libsasl2-2 \ diff --git a/cvat-core/src/annotation-formats.js b/cvat-core/src/annotation-formats.js index 795c98630e7e..0bad3b7fb8a2 100644 --- a/cvat-core/src/annotation-formats.js +++ b/cvat-core/src/annotation-formats.js @@ -15,6 +15,7 @@ format: initialData.ext, version: initialData.version, enabled: initialData.enabled, + dimension: initialData.dimension, }; Object.defineProperties(this, { @@ -58,6 +59,16 @@ */ get: () => data.enabled, }, + dimension: { + /** + * @name dimension + * @type {string} + * @memberof module:API.cvat.enums.DimensionType + * @readonly + * @instance + */ + get: () => data.dimension, + }, }); } } @@ -74,6 +85,7 @@ format: initialData.ext, version: initialData.version, enabled: initialData.enabled, + dimension: initialData.dimension, }; Object.defineProperties(this, { @@ -117,6 +129,16 @@ */ get: () => data.enabled, }, + dimension: { + /** + * @name dimension + * @type {string} + * @memberof module:API.cvat.enums.DimensionType + * @readonly + * @instance + */ + get: () => data.dimension, + }, }); } } diff --git a/cvat-core/src/api-implementation.js b/cvat-core/src/api-implementation.js index f3e2aa26aa09..1d2dbff5c54c 100644 --- a/cvat-core/src/api-implementation.js +++ b/cvat-core/src/api-implementation.js @@ -10,7 +10,7 @@ isBoolean, isInteger, isEnum, isString, checkFilter, } = require('./common'); - const { TaskStatus, TaskMode } = require('./enums'); + const { TaskStatus, TaskMode, DimensionType } = require('./enums'); const User = require('./user'); const { AnnotationFormats } = require('./annotation-formats'); @@ -176,6 +176,7 @@ search: isString, status: isEnum.bind(TaskStatus), mode: isEnum.bind(TaskMode), + dimension: isEnum.bind(DimensionType), }); if ('search' in filter && Object.keys(filter).length > 1) { @@ -198,7 +199,7 @@ } const searchParams = new URLSearchParams(); - for (const field of ['name', 'owner', 'assignee', 'search', 'status', 'mode', 'id', 'page', 'projectId']) { + for (const field of ['name', 'owner', 'assignee', 'search', 'status', 'mode', 'id', 'page', 'projectId', 'dimension']) { if (Object.prototype.hasOwnProperty.call(filter, field)) { searchParams.set(field, filter[field]); } diff --git a/cvat-core/src/enums.js b/cvat-core/src/enums.js index 107bc86fcc5c..4ce6d80c08c6 100644 --- a/cvat-core/src/enums.js +++ b/cvat-core/src/enums.js @@ -33,6 +33,20 @@ COMPLETED: 'completed', }); + /** + * Task dimension + * @enum + * @name DimensionType + * @memberof module:API.cvat.enums + * @property {string} DIMENSION_2D '2d' + * @property {string} DIMENSION_3D '3d' + * @readonly + */ + const DimensionType = Object.freeze({ + DIMENSION_2D: '2d', + DIMENSION_3D: '3d', + }); + /** * Review statuses * @enum {string} @@ -333,5 +347,6 @@ RQStatus, colors, Source, + DimensionType, }; })(); diff --git a/cvat-core/src/session.js b/cvat-core/src/session.js index 19bc32df6014..5b6aa41fc466 100644 --- a/cvat-core/src/session.js +++ b/cvat-core/src/session.js @@ -974,6 +974,7 @@ use_zip_chunks: undefined, use_cache: undefined, copy_data: undefined, + dimension: undefined, }; let updatedFields = { @@ -1452,6 +1453,16 @@ updatedFields = fields; }, }, + dimension: { + /** + * @name enabled + * @type {string} + * @memberof module:API.cvat.enums.DimensionType + * @readonly + * @instance + */ + get: () => data.dimension, + }, }), ); diff --git a/cvat-ui/src/components/actions-menu/actions-menu.tsx b/cvat-ui/src/components/actions-menu/actions-menu.tsx index 723bf68e1452..644f29454793 100644 --- a/cvat-ui/src/components/actions-menu/actions-menu.tsx +++ b/cvat-ui/src/components/actions-menu/actions-menu.tsx @@ -11,6 +11,7 @@ import { MenuInfo } from 'rc-menu/lib/interface'; import DumpSubmenu from './dump-submenu'; import LoadSubmenu from './load-submenu'; import ExportSubmenu from './export-submenu'; +import { DimensionType } from '../../reducers/interfaces'; interface Props { taskID: number; @@ -22,7 +23,7 @@ interface Props { dumpActivities: string[] | null; exportActivities: string[] | null; inferenceIsActive: boolean; - + taskDimension: DimensionType; onClickMenu: (params: MenuInfo, file?: File) => void; } @@ -47,6 +48,7 @@ export default function ActionsMenuComponent(props: Props): JSX.Element { dumpActivities, exportActivities, loadActivity, + taskDimension, } = props; let latestParams: MenuInfo | null = null; @@ -102,6 +104,7 @@ export default function ActionsMenuComponent(props: Props): JSX.Element { dumpers, dumpActivities, menuKey: Actions.DUMP_TASK_ANNO, + taskDimension, })} {LoadSubmenu({ loaders, @@ -110,11 +113,13 @@ export default function ActionsMenuComponent(props: Props): JSX.Element { onClickMenuWrapper(null, file); }, menuKey: Actions.LOAD_TASK_ANNO, + taskDimension, })} {ExportSubmenu({ exporters: dumpers, exportActivities, menuKey: Actions.EXPORT_TASK_DATASET, + taskDimension, })} {!!bugTracker && Open bug tracker} diff --git a/cvat-ui/src/components/actions-menu/dump-submenu.tsx b/cvat-ui/src/components/actions-menu/dump-submenu.tsx index 5f71273f3d24..91721ac6bb81 100644 --- a/cvat-ui/src/components/actions-menu/dump-submenu.tsx +++ b/cvat-ui/src/components/actions-menu/dump-submenu.tsx @@ -6,6 +6,7 @@ import React from 'react'; import Menu from 'antd/lib/menu'; import { DownloadOutlined, LoadingOutlined } from '@ant-design/icons'; import Text from 'antd/lib/typography/Text'; +import { DimensionType } from '../../reducers/interfaces'; function isDefaultFormat(dumperName: string, taskMode: string): boolean { return ( @@ -19,15 +20,19 @@ interface Props { menuKey: string; dumpers: any[]; dumpActivities: string[] | null; + taskDimension: DimensionType; } export default function DumpSubmenu(props: Props): JSX.Element { - const { taskMode, menuKey, dumpers, dumpActivities } = props; + const { + taskMode, menuKey, dumpers, dumpActivities, taskDimension, + } = props; return ( {dumpers .sort((a: any, b: any) => a.name.localeCompare(b.name)) + .filter((dumper: any): boolean => dumper.dimension === taskDimension) .map( (dumper: any): JSX.Element => { const pending = (dumpActivities || []).includes(dumper.name); diff --git a/cvat-ui/src/components/actions-menu/export-submenu.tsx b/cvat-ui/src/components/actions-menu/export-submenu.tsx index 28affd5f7b05..683565009155 100644 --- a/cvat-ui/src/components/actions-menu/export-submenu.tsx +++ b/cvat-ui/src/components/actions-menu/export-submenu.tsx @@ -6,20 +6,25 @@ import React from 'react'; import Menu from 'antd/lib/menu'; import Text from 'antd/lib/typography/Text'; import { ExportOutlined, LoadingOutlined } from '@ant-design/icons'; +import { DimensionType } from '../../reducers/interfaces'; interface Props { menuKey: string; exporters: any[]; exportActivities: string[] | null; + taskDimension: DimensionType; } export default function ExportSubmenu(props: Props): JSX.Element { - const { menuKey, exporters, exportActivities } = props; + const { + menuKey, exporters, exportActivities, taskDimension, + } = props; return ( {exporters .sort((a: any, b: any) => a.name.localeCompare(b.name)) + .filter((exporter: any): boolean => exporter.dimension === taskDimension) .map( (exporter: any): JSX.Element => { const pending = (exportActivities || []).includes(exporter.name); diff --git a/cvat-ui/src/components/actions-menu/load-submenu.tsx b/cvat-ui/src/components/actions-menu/load-submenu.tsx index 53bbe3c776b4..476e577fcb36 100644 --- a/cvat-ui/src/components/actions-menu/load-submenu.tsx +++ b/cvat-ui/src/components/actions-menu/load-submenu.tsx @@ -8,23 +8,26 @@ import Upload from 'antd/lib/upload'; import Button from 'antd/lib/button'; import Text from 'antd/lib/typography/Text'; import { UploadOutlined, LoadingOutlined } from '@ant-design/icons'; +import { DimensionType } from '../../reducers/interfaces'; interface Props { menuKey: string; loaders: any[]; loadActivity: string | null; onFileUpload(file: File): void; + taskDimension: DimensionType; } export default function LoadSubmenu(props: Props): JSX.Element { const { - menuKey, loaders, loadActivity, onFileUpload, + menuKey, loaders, loadActivity, onFileUpload, taskDimension, } = props; return ( {loaders .sort((a: any, b: any) => a.name.localeCompare(b.name)) + .filter((loader: any): boolean => loader.dimension === taskDimension) .map( (loader: any): JSX.Element => { const accept = loader.format diff --git a/cvat-ui/src/components/annotation-page/top-bar/annotation-menu.tsx b/cvat-ui/src/components/annotation-page/top-bar/annotation-menu.tsx index 3ac000f4c474..9400a20c2809 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/annotation-menu.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/annotation-menu.tsx @@ -161,6 +161,7 @@ export default function AnnotationMenuComponent(props: Props): JSX.Element { dumpers, dumpActivities, menuKey: Actions.DUMP_TASK_ANNO, + taskDimension: jobInstance.task.dimension, })} {LoadSubmenu({ loaders, @@ -169,11 +170,13 @@ export default function AnnotationMenuComponent(props: Props): JSX.Element { onClickMenuWrapper(null, file); }, menuKey: Actions.LOAD_JOB_ANNO, + taskDimension: jobInstance.task.dimension, })} {ExportSubmenu({ exporters: dumpers, exportActivities, menuKey: Actions.EXPORT_TASK_DATASET, + taskDimension: jobInstance.task.dimension, })} Remove annotations diff --git a/cvat-ui/src/components/model-runner-modal/detector-runner.tsx b/cvat-ui/src/components/model-runner-modal/detector-runner.tsx index 8a000e1ad125..db757867c138 100644 --- a/cvat-ui/src/components/model-runner-modal/detector-runner.tsx +++ b/cvat-ui/src/components/model-runner-modal/detector-runner.tsx @@ -21,6 +21,7 @@ import { Model, StringObject } from 'reducers/interfaces'; import { clamp } from 'utils/math'; import consts from 'consts'; +import { DimensionType } from '../../reducers/interfaces'; interface Props { withCleanup: boolean; @@ -127,7 +128,8 @@ function DetectorRunner(props: Props): JSX.Element { Model: