diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e24fe57..f853efa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Context image disappears after undo/redo () - Using combined data sources (directory and image) when create a task () - Creating task with labels in project () +- Move task and autoannotation modals were invisible from project page () ## \[1.4.0] - 2021-05-18 diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index e1a4936e..2fb6941d 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1244,9 +1244,9 @@ "dev": true }, "@types/lodash": { - "version": "4.14.170", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz", - "integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==" + "version": "4.14.171", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.171.tgz", + "integrity": "sha512-7eQ2xYLLI/LsicL2nejW9Wyko3lcpN6O/z0ZLHrEQsg280zIdCv1t/0m6UtBjUHokCGBQ3gYTbHzDkZ1xOBwwg==" }, "@types/minimatch": { "version": "3.0.3", @@ -1267,9 +1267,9 @@ "dev": true }, "@types/platform": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/platform/-/platform-1.3.3.tgz", - "integrity": "sha512-1fuOulBHWIxAPLBtLms+UtbeRDt6rL7gP5R+Yugfzdg+poCLxXqXTE8i+FpYeiytGRLUEtnFkjsY/j+usbQBqw==" + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/platform/-/platform-1.3.4.tgz", + "integrity": "sha512-U0o4K+GNiK0PNxoDwd8xRnvLVe4kzei6opn3/FCjAriqaP+rfrDdSl1kP/hLL6Y3/Y3hhGnBwD4dCkkAqs1W/Q==" }, "@types/prop-types": { "version": "15.7.4", @@ -1283,9 +1283,9 @@ "dev": true }, "@types/react": { - "version": "16.14.10", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.10.tgz", - "integrity": "sha512-QadBsMyF6ldjEAXEhsmEW/L0uBDJT8yw7Qoe5sRnEKVrzMkiYoJwqoL5TKJOlArsn/wvIJM/XdVzkdL6+AS64Q==", + "version": "16.14.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.11.tgz", + "integrity": "sha512-Don0MtsZZ3fjwTJ2BsoqkyOy7e176KplEAKOpr/4XDdzinlyJBn9yfsKn5mcSgn4kh1B22+3tBnzBC1z63ybtQ==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -1293,26 +1293,26 @@ } }, "@types/react-color": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.4.tgz", - "integrity": "sha512-EswbYJDF1kkrx93/YU+BbBtb46CCtDMvTiGmcOa/c5PETnwTiSWoseJ1oSWeRl/4rUXkhME9bVURvvPg0W5YQw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.5.tgz", + "integrity": "sha512-0VZy8Uq5x04cW5QFz24Qw8MMMlsMi8Bb+XG5h59ATqPnWVq6OheHtrwv5LeakdTRDaECQnExJNSFOsSe4Eo/zQ==", "requires": { "@types/react": "*", "@types/reactcss": "*" } }, "@types/react-dom": { - "version": "16.9.13", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.13.tgz", - "integrity": "sha512-34Hr3XnmUSJbUVDxIw/e7dhQn2BJZhJmlAaPyPwfTQyuVS9mV/CeyghFcXyvkJXxI7notQJz8mF8FeCVvloJrA==", + "version": "16.9.14", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.14.tgz", + "integrity": "sha512-FIX2AVmPTGP30OUJ+0vadeIFJJ07Mh1m+U0rxfgyW34p3rTlXI+nlenvAxNn4BP36YyI9IJ/+UJ7Wu22N1pI7A==", "requires": { "@types/react": "^16" } }, "@types/react-redux": { - "version": "7.1.16", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.16.tgz", - "integrity": "sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw==", + "version": "7.1.18", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.18.tgz", + "integrity": "sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ==", "requires": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", @@ -1329,18 +1329,18 @@ } }, "@types/react-router": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.15.tgz", - "integrity": "sha512-z3UlMG/x91SFEVmmvykk9FLTliDvfdIUky4k2rCfXWQ0NKbrP8o9BTCaCTPuYsB8gDkUnUmkcA2vYlm2DR+HAA==", + "version": "5.1.16", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.16.tgz", + "integrity": "sha512-8d7nR/fNSqlTFGHti0R3F9WwIertOaaA1UEB8/jr5l5mDMOs4CidEgvvYMw4ivqrBK+vtVLxyTj2P+Pr/dtgzg==", "requires": { "@types/history": "*", "@types/react": "*" } }, "@types/react-router-dom": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.7.tgz", - "integrity": "sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz", + "integrity": "sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==", "requires": { "@types/history": "*", "@types/react": "*", @@ -1356,17 +1356,17 @@ } }, "@types/reactcss": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.3.tgz", - "integrity": "sha512-d2gQQ0IL6hXLnoRfVYZukQNWHuVsE75DzFTLPUuyyEhJS8G2VvlE+qfQQ91SJjaMqlURRCNIsX7Jcsw6cEuJlA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.4.tgz", + "integrity": "sha512-1rhVqteMSD6KQjO+dPBObE1OkKadw00HVJkG5WCYsyvMwGgdTZ530wF7Bkrg/4TWxB2AtINIzFotjW51eViw+w==", "requires": { "@types/react": "*" } }, "@types/redux-logger": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@types/redux-logger/-/redux-logger-3.0.8.tgz", - "integrity": "sha512-zM+cxiSw6nZtRbxpVp9SE3x/X77Z7e7YAfHD1NkxJyJbAGSXJGF0E9aqajZfPOa/sTYnuwutmlCldveExuCeLw==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/redux-logger/-/redux-logger-3.0.9.tgz", + "integrity": "sha512-cwYhVbYNgH01aepeMwhd0ABX6fhVB2rcQ9m80u8Fl50ZODhsZ8RhQArnLTkE7/Zrfq4Sz/taNoF7DQy9pCZSKg==", "requires": { "redux": "^4.0.0" } diff --git a/cvat-ui/package.json b/cvat-ui/package.json index b3bb6360..80a8f8f5 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -49,17 +49,17 @@ }, "dependencies": { "@ant-design/icons": "^4.6.2", - "@types/lodash": "^4.14.170", - "@types/platform": "^1.3.3", - "@types/react": "^16.14.10", - "@types/react-color": "^3.0.4", - "@types/react-dom": "^16.9.13", - "@types/react-redux": "^7.1.16", + "@types/lodash": "^4.14.171", + "@types/platform": "^1.3.4", + "@types/react": "^16.14.11", + "@types/react-color": "^3.0.5", + "@types/react-dom": "^16.9.14", + "@types/react-redux": "^7.1.18", "@types/react-resizable": "^1.7.2", - "@types/react-router": "^5.1.15", - "@types/react-router-dom": "^5.1.7", + "@types/react-router": "^5.1.16", + "@types/react-router-dom": "^5.1.8", "@types/react-share": "^3.0.3", - "@types/redux-logger": "^3.0.8", + "@types/redux-logger": "^3.0.9", "@types/resize-observer-browser": "^0.1.5", "antd": "^4.13.0", "copy-to-clipboard": "^3.3.1", diff --git a/cvat-ui/src/components/project-page/project-page.tsx b/cvat-ui/src/components/project-page/project-page.tsx index 385d58c5..ef44d031 100644 --- a/cvat-ui/src/components/project-page/project-page.tsx +++ b/cvat-ui/src/components/project-page/project-page.tsx @@ -17,6 +17,8 @@ import { CombinedState, Task } from 'reducers/interfaces'; import { getProjectsAsync } from 'actions/projects-actions'; import { cancelInferenceAsync } from 'actions/models-actions'; import TaskItem from 'components/tasks-page/task-item'; +import MoveTaskModal from 'components/move-task-modal/move-task-modal'; +import ModelRunnerDialog from 'components/model-runner-modal/model-runner-dialog'; import DetailsComponent from './details'; import ProjectTopBar from './top-bar'; @@ -109,6 +111,8 @@ export default function ProjectPageComponent(): JSX.Element { ))} + + ); } diff --git a/cvat-ui/src/components/project-page/top-bar.tsx b/cvat-ui/src/components/project-page/top-bar.tsx index dde03ecb..aa5720a7 100644 --- a/cvat-ui/src/components/project-page/top-bar.tsx +++ b/cvat-ui/src/components/project-page/top-bar.tsx @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // // SPDX-License-Identifier: MIT diff --git a/site/content/en/docs/manual/advanced/ai-tools.md b/site/content/en/docs/manual/advanced/ai-tools.md index 03d3c71a..53f5f1f2 100644 --- a/site/content/en/docs/manual/advanced/ai-tools.md +++ b/site/content/en/docs/manual/advanced/ai-tools.md @@ -8,7 +8,7 @@ The tool is designed for semi-automatic and automatic annotation using DL models The tool is available only if there is a corresponding model. For more details about DL models read the [Models](/docs/manual/advanced/models/) section. -### Interactors +## Interactors Interactors are used to create a polygon semi-automatically. Supported DL models are not bound to the label and can be used for any objects. @@ -17,6 +17,7 @@ For some kinds of segmentation negative points are available. Positive points are the points related to the object. Negative points should be placed outside the boundary of the object. In most cases specifying positive points alone is enough to build a polygon. +A list of available out-of-the-box interactors is placed below. - Before you start, select the magic wand on the controls sidebar and go to the `Interactors` tab. Then select a label for the polygon and a required DL model. @@ -44,7 +45,33 @@ In most cases specifying positive points alone is enough to build a polygon. - When the object is finished, you can edit it like a polygon. You can read about editing polygons in the [Annotation with polygons](/docs/manual/advanced/annotation-with-polygons/) section. -### Detectors +### Deep extreme cut (DEXTR) + +This is an optimized version of the original model, introduced at the end of 2017. +It uses the information about extreme points of an object to get its mask. The mask then converted to a polygon. +For now this is the fastest interactor on CPU. + +![](/images/dextr_example.gif) + +### Feature backpropagating refinement scheme (f-BRS) + +The model allows to get a mask for an object using positive points +(should be left-clicked on the foreground), and negative points +(should be right-clicked on the background, if necessary). +It is recommended to run the model on GPU, if possible. + +![](/images/fbrs_example.gif) + +### Inside-Outside-Guidance + +The model uses a bounding box and inside/outside points to create a mask. +First of all, you need to create a bounding box, wrapping the object. +Then you need to use positive and negative points to say the model where is a foreground, +and where is a background. Negative points are optional. + +![](/images/iog_example.gif) + +## Detectors Detectors are used to automatically annotate one frame. Supported DL models are suitable only for certain labels. diff --git a/site/content/en/images/dextr_example.gif b/site/content/en/images/dextr_example.gif new file mode 100644 index 00000000..cb4734b9 Binary files /dev/null and b/site/content/en/images/dextr_example.gif differ diff --git a/site/content/en/images/fbrs_example.gif b/site/content/en/images/fbrs_example.gif new file mode 100644 index 00000000..4e95c2dc Binary files /dev/null and b/site/content/en/images/fbrs_example.gif differ diff --git a/site/content/en/images/iog_example.gif b/site/content/en/images/iog_example.gif new file mode 100644 index 00000000..2141122c Binary files /dev/null and b/site/content/en/images/iog_example.gif differ diff --git a/tests/cypress/integration/actions_objects2/case_10_polygon_shape_track_label_points.js b/tests/cypress/integration/actions_objects2/case_10_polygon_shape_track_label_points.js index 6672cfb8..cc12eaeb 100644 --- a/tests/cypress/integration/actions_objects2/case_10_polygon_shape_track_label_points.js +++ b/tests/cypress/integration/actions_objects2/case_10_polygon_shape_track_label_points.js @@ -91,17 +91,58 @@ context('Actions on polygon', () => { }); describe(`Testing case "${caseId}"`, () => { - it('Draw a polygon shape, track', () => { + it('Draw a polygon shape, track.', () => { cy.createPolygon(createPolygonShape); cy.createPolygon(createPolygonTrack); }); - it('Draw a polygon shape, track with use parameter "number of points"', () => { + + it('Draw a polygon shape, track with use parameter "number of points".', () => { cy.createPolygon(createPolygonShapePoints); cy.createPolygon(createPolygonTrackPoints); }); - it('Draw a polygon shape, track with second label', () => { + + it('Draw a polygon shape, track with second label.', () => { cy.createPolygon(createPolygonShapeSwitchLabel); cy.createPolygon(createPolygonTrackSwitchLabel); }); + + it('Set start point.', () => { + let notFirtsPointCoords = { + x: 0, + y: 0, + }; + let firtsPointCoords = { + x: 0, + y: 0, + }; + cy.get('#cvat_canvas_shape_4') + .trigger('mousemove', {scrollBehavior: false}) + .trigger('mouseover', {scrollBehavior: false}) + .should('have.class', 'cvat_canvas_shape_activated'); + cy.get('.svg_select_points').not('.cvat_canvas_first_poly_point').first().then((notFirtsPoint) => { + notFirtsPointCoords.x = notFirtsPoint.attr('cx'); + notFirtsPointCoords.y = notFirtsPoint.attr('cy'); + }).rightclick({scrollBehavior: false}); + cy.get('.cvat-canvas-point-context-menu').contains('span', 'Set start point').click({scrollBehavior: false}); + cy.get('.cvat_canvas_first_poly_point').then((firtsPoint) => { + firtsPointCoords.x = firtsPoint.attr('cx'); + firtsPointCoords.y = firtsPoint.attr('cy'); + expect(notFirtsPointCoords).to.deep.equal(firtsPointCoords); + }); + }); + + it('Change direction.', () => { + let polyDirectionAttrDataAngle; + cy.get('#cvat_canvas_shape_4') + .trigger('mousemove', {scrollBehavior: false}) + .trigger('mouseover', {scrollBehavior: false}) + .should('have.class', 'cvat_canvas_shape_activated'); + cy.get('.cvat_canvas_poly_direction').then((polyDirection) => { + polyDirectionAttrDataAngle = polyDirection.attr('data-angle'); + }).click({scrollBehavior: false}) + cy.get('.cvat_canvas_poly_direction').then((afterChangePolyDirection) => { + expect(polyDirectionAttrDataAngle).not.equal(afterChangePolyDirection.attr('data-angle')); + }); + }); }); }); diff --git a/tests/cypress/integration/actions_objects2/case_11_polylines_shape_track_label_points.js b/tests/cypress/integration/actions_objects2/case_11_polylines_shape_track_label_points.js index 98101873..008edb6c 100644 --- a/tests/cypress/integration/actions_objects2/case_11_polylines_shape_track_label_points.js +++ b/tests/cypress/integration/actions_objects2/case_11_polylines_shape_track_label_points.js @@ -85,17 +85,49 @@ context('Actions on polylines', () => { }); describe(`Testing case "${caseId}"`, () => { - it('Draw a polylines shape, track', () => { + it('Draw a polylines shape, track.', () => { cy.createPolyline(createPolylinesShape); cy.createPolyline(createPolylinesTrack); }); - it('Draw a polylines shape, track with use parameter "number of points"', () => { + + it('Draw a polylines shape, track with use parameter "number of points".', () => { cy.createPolyline(createPolylinesShapePoints); cy.createPolyline(createPolylinesTrackPoints); }); - it('Draw a polylines shape, track with second label', () => { + + it('Draw a polylines shape, track with second label.', () => { cy.createPolyline(createPolylinesShapeSwitchLabel); cy.createPolyline(createPolylinesTrackSwitchLabel); }); + + it('Change direction.', () => { + let firtsPointCoords = { + x: 0, + y: 0, + }; + let lastPointCoords = { + x: 0, + y: 0, + }; + cy.get('#cvat_canvas_shape_4') + .trigger('mousemove', {scrollBehavior: false}) + .trigger('mouseover', {scrollBehavior: false}) + .should('have.class', 'cvat_canvas_shape_activated'); + cy.get('.svg_select_points_point').first().then((firtsPoint) => { + firtsPointCoords.x = firtsPoint.attr('cx'); + firtsPointCoords.y = firtsPoint.attr('cy'); + cy.get('.svg_select_points_point').last().then((lastPoint) => { + lastPointCoords.x = lastPoint.attr('cx'); + lastPointCoords.y = lastPoint.attr('cy'); + cy.get('.cvat_canvas_first_poly_point') + .should('have.attr', 'cx', firtsPointCoords.x) + .and('have.attr', 'cy', firtsPointCoords.y) + cy.get('.cvat_canvas_poly_direction').click({scrollBehavior: false}); + cy.get('.cvat_canvas_first_poly_point') + .should('have.attr', 'cx', lastPointCoords.x) + .and('have.attr', 'cy', lastPointCoords.y) + }); + }); + }); }); }); diff --git a/tests/cypress/integration/actions_projects_models/case_94_move_task_between_projects.js b/tests/cypress/integration/actions_projects_models/case_94_move_task_between_projects.js index 99c5a6bd..decc03b7 100644 --- a/tests/cypress/integration/actions_projects_models/case_94_move_task_between_projects.js +++ b/tests/cypress/integration/actions_projects_models/case_94_move_task_between_projects.js @@ -80,8 +80,7 @@ context('Move a task between projects.', () => { }); describe(`Testing "Case ${caseID}"`, () => { - // Waiting to fix https://github.com/openvinotoolkit/cvat/issues/3281 - it.skip('Move a task between projects from a project.', () => { + it('Move a task between projects from a project.', () => { checkTask(secondProject.name, 'not.exist'); checkTask(firtsProject.name, 'exist'); cy.movingTask(taskName, secondProject.name, firtsProject.label, secondProject.label); diff --git a/tests/cypress/integration/actions_tasks/case_100_settings_default_number_of_points_in_polygon_approximation.js b/tests/cypress/integration/actions_tasks/case_100_settings_default_number_of_points_in_polygon_approximation.js new file mode 100644 index 00000000..819cb4a9 --- /dev/null +++ b/tests/cypress/integration/actions_tasks/case_100_settings_default_number_of_points_in_polygon_approximation.js @@ -0,0 +1,64 @@ +// Copyright (C) 2021 Intel Corporation +// +// SPDX-License-Identifier: MIT + +/// + +import { taskName } from '../../support/const'; + +context('Settings. Default number of points in polygon approximation.', () => { + const caseId = '100'; + + function testOpenSettingsWorkspace() { + cy.document().then((doc) => { + const settingsModal = Array.from(doc.querySelectorAll('.cvat-settings-modal')); + if (settingsModal.length === 0) { + cy.openSettings(); + cy.contains('[role="tab"]', 'Workspace').click(); + } + }); + } + + function testCheckSliderAttrValuenow(expectedValue) { + testOpenSettingsWorkspace(); + cy.get('.cvat-workspace-settings-approx-poly-threshold').find('[role="slider"]').then((slider) => { + expect(slider.attr('aria-valuenow')).to.be.equal(expectedValue); + }); + } + + function generateString(countPointsToMove) { + let action = ''; + for (let i = 0; i < countPointsToMove; i++) { + action += '{rightarrow}'; + } + return action; + } + + before(() => { + cy.openTaskJob(taskName); + }); + + describe(`Testing case "${caseId}"`, () => { + it('Change the setting value for "Default number of points in polygon approximation".', () => { + testOpenSettingsWorkspace(); + cy.get('.cvat-workspace-settings-approx-poly-threshold') + .find('[role="slider"]') + .type(generateString(4)) + .then((slider) => { + const sliderAttrValueNow = slider.attr('aria-valuenow'); + const sliderAttrValuemin = slider.attr('aria-valuemin'); + const sliderAttrValuemax = slider.attr('aria-valuemax'); + cy.saveSettings(); + cy.closeNotification('.cvat-notification-notice-save-settings-success'); + cy.closeSettings(); + cy.reload(); + cy.closeModalUnsupportedPlatform(); // If the Firefox browser closes the modal window after reload + testCheckSliderAttrValuenow(sliderAttrValueNow); + cy.contains('strong', 'less').click(); + testCheckSliderAttrValuenow(sliderAttrValuemin); + cy.contains('strong', 'more').click(); + testCheckSliderAttrValuenow(sliderAttrValuemax); + }); + }); + }); +});