From aba9401ea69db0418b3e9048950d2c5cdfe84558 Mon Sep 17 00:00:00 2001 From: EBayego Date: Mon, 15 Apr 2024 18:35:03 +0200 Subject: [PATCH 1/2] [GSoC2024]Import annotations keeping current ones(#4747) Keep current annotations without deleting them, adding the imported ones. --- cvat-ui/src/actions/import-actions.ts | 12 +++++-- .../import-dataset/import-dataset-modal.tsx | 34 ++++++++++++++++++- .../src/components/import-dataset/styles.scss | 6 ++++ cvat/apps/dataset_manager/task.py | 17 ++++++---- cvat/apps/engine/views.py | 28 +++++++++++---- 5 files changed, 81 insertions(+), 16 deletions(-) diff --git a/cvat-ui/src/actions/import-actions.ts b/cvat-ui/src/actions/import-actions.ts index 4f54124daaa..a51f6f50b44 100644 --- a/cvat-ui/src/actions/import-actions.ts +++ b/cvat-ui/src/actions/import-actions.ts @@ -71,6 +71,7 @@ export const importDatasetAsync = ( sourceStorage: Storage, file: File | string, convMaskToPoly: boolean, + keepOldAnnotations: boolean, ): ThunkAction => ( async (dispatch, getState) => { const resource = instance instanceof core.classes.Project ? 'dataset' : 'annotation'; @@ -86,6 +87,7 @@ export const importDatasetAsync = ( await instance.annotations .importDataset(format, useDefaultSettings, sourceStorage, file, { convMaskToPoly, + keepOldAnnotations, updateStatusCallback: (message: string, progress: number) => ( dispatch(importActions.importDatasetUpdateStatus( instance, Math.floor(progress * 100), message, @@ -97,7 +99,10 @@ export const importDatasetAsync = ( throw Error('Only one importing of annotation/dataset allowed at the same time'); } dispatch(importActions.importDataset(instance, format)); - await instance.annotations.upload(format, useDefaultSettings, sourceStorage, file, { convMaskToPoly }); + await instance.annotations.upload(format, useDefaultSettings, sourceStorage, file, { + convMaskToPoly, + keepOldAnnotations, + }); } else { // job if (state.import.tasks.dataset.current?.[instance.taskId]) { throw Error('Annotations is being uploaded for the task'); @@ -108,7 +113,10 @@ export const importDatasetAsync = ( dispatch(importActions.importDataset(instance, format)); - await instance.annotations.upload(format, useDefaultSettings, sourceStorage, file, { convMaskToPoly }); + await instance.annotations.upload(format, useDefaultSettings, sourceStorage, file, { + convMaskToPoly, + keepOldAnnotations, + }); await instance.logger.log(EventScope.uploadAnnotations); await instance.annotations.clear(true); await instance.actions.clear(); diff --git a/cvat-ui/src/components/import-dataset/import-dataset-modal.tsx b/cvat-ui/src/components/import-dataset/import-dataset-modal.tsx index 5051b4a9654..3f4065a09e3 100644 --- a/cvat-ui/src/components/import-dataset/import-dataset-modal.tsx +++ b/cvat-ui/src/components/import-dataset/import-dataset-modal.tsx @@ -51,6 +51,7 @@ const initialValues: FormValues = { interface UploadParams { resource: 'annotation' | 'dataset' | null; convMaskToPoly: boolean; + keepOldAnnotations: boolean; useDefaultSettings: boolean; sourceStorage: Storage; selectedFormat: string | null; @@ -83,6 +84,7 @@ enum ReducerActionType { SET_FILE_NAME = 'SET_FILE_NAME', SET_SELECTED_FORMAT = 'SET_SELECTED_FORMAT', SET_CONV_MASK_TO_POLY = 'SET_CONV_MASK_TO_POLY', + SET_KEEP_OLD_ANNOTATIONS = 'SET_KEEP_OLD_ANNOTATIONS', SET_SOURCE_STORAGE = 'SET_SOURCE_STORAGE', SET_RESOURCE = 'SET_RESOURCE', } @@ -121,6 +123,9 @@ export const reducerActions = { setConvMaskToPoly: (convMaskToPoly: boolean) => ( createAction(ReducerActionType.SET_CONV_MASK_TO_POLY, { convMaskToPoly }) ), + setKeepOldAnnotations: (keepOldAnnotations: boolean) => ( + createAction(ReducerActionType.SET_KEEP_OLD_ANNOTATIONS, { keepOldAnnotations }) + ), setSourceStorage: (sourceStorage: Storage) => ( createAction(ReducerActionType.SET_SOURCE_STORAGE, { sourceStorage }) ), @@ -246,6 +251,16 @@ const reducer = (state: State, action: ActionUnion): Stat }; } + if (action.type === ReducerActionType.SET_KEEP_OLD_ANNOTATIONS) { + return { + ...state, + uploadParams: { + ...state.uploadParams, + keepOldAnnotations: action.payload.keepOldAnnotations, + }, + }; + } + if (action.type === ReducerActionType.SET_SOURCE_STORAGE) { return { ...state, @@ -292,6 +307,7 @@ function ImportDatasetModal(props: StateToProps): JSX.Element { uploadParams: { resource: null, convMaskToPoly: true, + keepOldAnnotations: true, useDefaultSettings: true, sourceStorage: new Storage({ location: StorageLocation.LOCAL, @@ -460,6 +476,7 @@ function ImportDatasetModal(props: StateToProps): JSX.Element { uploadParams.sourceStorage, uploadParams.file || uploadParams.fileName as string, uploadParams.convMaskToPoly, + uploadParams.keepOldAnnotations, )); const resToPrint = uploadParams.resource.charAt(0).toUpperCase() + uploadParams.resource.slice(1); Notification.info({ @@ -488,7 +505,7 @@ function ImportDatasetModal(props: StateToProps): JSX.Element { const handleImport = useCallback( (): void => { - if (isAnnotation()) { + if (isAnnotation() && !uploadParams.keepOldAnnotations) { confirmUpload(); } else { onUpload(); @@ -538,6 +555,7 @@ function ImportDatasetModal(props: StateToProps): JSX.Element { initialValues={{ ...initialValues, convMaskToPoly: uploadParams.convMaskToPoly, + keepOldAnnotations: uploadParams.keepOldAnnotations, }} onFinish={handleImport} layout='vertical' @@ -588,6 +606,20 @@ function ImportDatasetModal(props: StateToProps): JSX.Element { )} + + + { + dispatch(reducerActions.setKeepOldAnnotations(value)); + }} + /> + + Keep Current Annotations + Date: Mon, 15 Apr 2024 19:42:57 +0200 Subject: [PATCH 2/2] [GSoC2024]Add changelog.d(#4747) --- .../20240415_193335_ebayego_keep_old_annotations_on_import.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog.d/20240415_193335_ebayego_keep_old_annotations_on_import.md diff --git a/changelog.d/20240415_193335_ebayego_keep_old_annotations_on_import.md b/changelog.d/20240415_193335_ebayego_keep_old_annotations_on_import.md new file mode 100644 index 00000000000..c93d12238a9 --- /dev/null +++ b/changelog.d/20240415_193335_ebayego_keep_old_annotations_on_import.md @@ -0,0 +1,4 @@ +### Added + +- Added a feature that allows to keep current annotations without deleting them when new ones are imported, by checking the option. + ()