diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml index 45ba18777610..66797a861090 100644 --- a/.github/ISSUE_TEMPLATE/bug.yaml +++ b/.github/ISSUE_TEMPLATE/bug.yaml @@ -8,7 +8,7 @@ body: options: - label: I searched the existing issues and did not find anything similar. required: true - - label: I read/searched [the docs](https://opencv.github.io/cvat/docs/) + - label: I read/searched [the docs](https://docs.cvat.ai/docs/) required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index ab7222ad3123..b06919d2be8c 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -8,7 +8,7 @@ body: options: - label: I searched the existing issues and did not find anything similar. required: true - - label: I read/searched [the docs](https://opencv.github.io/cvat/docs/) + - label: I read/searched [the docs](https://docs.cvat.ai/docs/) required: true - type: textarea attributes: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6346cf3ef9b7..d05c86d19a68 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,7 @@ - +Read the [Contribution guide](https://docs.cvat.ai/docs/contributing/). --> @@ -27,13 +27,13 @@ If you're unsure about any of these, don't hesitate to ask. We're here to help! - [ ] I have linked related issues (see [GitHub docs]( https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)) - [ ] I have increased versions of npm packages if it is necessary - ([cvat-canvas](https://github.com/opencv/cvat/tree/develop/cvat-canvas#versioning), - [cvat-core](https://github.com/opencv/cvat/tree/develop/cvat-core#versioning), - [cvat-data](https://github.com/opencv/cvat/tree/develop/cvat-data#versioning) and - [cvat-ui](https://github.com/opencv/cvat/tree/develop/cvat-ui#versioning)) + ([cvat-canvas](https://github.com/cvat-ai/cvat/tree/develop/cvat-canvas#versioning), + [cvat-core](https://github.com/cvat-ai/cvat/tree/develop/cvat-core#versioning), + [cvat-data](https://github.com/cvat-ai/cvat/tree/develop/cvat-data#versioning) and + [cvat-ui](https://github.com/cvat-ai/cvat/tree/develop/cvat-ui#versioning)) ### License - [ ] I submit _my code changes_ under the same [MIT License]( - https://github.com/opencv/cvat/blob/develop/LICENSE) that covers the project. + https://github.com/cvat-ai/cvat/blob/develop/LICENSE) that covers the project. Feel free to contact the maintainers if that's a concern. diff --git a/.github/workflows/cache.yml b/.github/workflows/cache.yml index 9cfc7d8766cb..654001994316 100644 --- a/.github/workflows/cache.yml +++ b/.github/workflows/cache.yml @@ -13,7 +13,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: ${{ github.repository }} - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000000..4a7317287819 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,67 @@ +name: Docs +on: + push: + branches: + - 'master' + - 'develop' + pull_request: + types: [ready_for_review, opened, synchronize, reopened] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + generate_github_pages: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: Generate CVAT SDK + run: | + pip3 install --user -r cvat-sdk/gen/requirements.txt + ./cvat-sdk/gen/generate.sh + + - name: Setup Hugo + run: | + wget https://github.com/gohugoio/hugo/releases/download/v0.110.0/hugo_extended_0.110.0_Linux-64bit.tar.gz + (mkdir hugo_extended_0.110.0_Linux-64bit && tar -xf hugo_extended_0.110.0_Linux-64bit.tar.gz -C hugo_extended_0.110.0_Linux-64bit) + + wget https://github.com/gohugoio/hugo/releases/download/v0.83.0/hugo_extended_0.83.0_Linux-64bit.tar.gz + (mkdir hugo_extended_0.83.0_Linux-64bit && tar -xf hugo_extended_0.83.0_Linux-64bit.tar.gz -C hugo_extended_0.83.0_Linux-64bit) + + mkdir hugo + cp hugo_extended_0.110.0_Linux-64bit/hugo hugo/hugo-0.110 + cp hugo_extended_0.83.0_Linux-64bit/hugo hugo/hugo-0.83 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '18.x' + + - name: Install npm packages + working-directory: ./site + run: | + npm ci + + - name: Build docs + run: | + pip install -r site/requirements.txt + python site/process_sdk_docs.py + PATH="$PWD/hugo:$PATH" python site/build_docs.py + env: + HUGO_ENV: production + + - name: Deploy + if: github.ref == 'refs/heads/develop' + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./public + force_orphan: true + cname: docs.cvat.ai diff --git a/.github/workflows/full.yml b/.github/workflows/full.yml index bd317dca1e81..b2a99ae1e502 100644 --- a/.github/workflows/full.yml +++ b/.github/workflows/full.yml @@ -22,7 +22,7 @@ jobs: build: needs: search_cache - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 with: @@ -94,7 +94,7 @@ jobs: rest_api_testing: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 with: @@ -187,7 +187,7 @@ jobs: unit_testing: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 with: @@ -247,7 +247,7 @@ jobs: e2e_testing: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big strategy: fail-fast: false matrix: diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml index d05bb5a24ee4..33c81b906663 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -21,7 +21,7 @@ jobs: github.event.pull_request.draft == false && !startsWith(github.event.pull_request.title, '[WIP]') && !startsWith(github.event.pull_request.title, '[Dependent]') - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 477968fd6dc4..9273aeb9aa7d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,7 +28,7 @@ jobs: build: needs: search_cache - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 @@ -127,7 +127,7 @@ jobs: rest_api_testing: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 @@ -208,7 +208,7 @@ jobs: unit_testing: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 @@ -274,7 +274,7 @@ jobs: e2e_testing: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big strategy: fail-fast: false matrix: @@ -385,63 +385,10 @@ jobs: name: cypress_screenshots_${{ matrix.specs }} path: ${{ github.workspace }}/tests/cypress/screenshots - generate_github_pages: - needs: [rest_api_testing, unit_testing, e2e_testing] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-depth: 0 - - - name: Download CVAT SDK - uses: actions/download-artifact@v3 - with: - name: cvat_sdk - path: /tmp/cvat_sdk/ - - - name: Setup Hugo - run: | - wget https://github.com/gohugoio/hugo/releases/download/v0.110.0/hugo_extended_0.110.0_Linux-64bit.tar.gz - (mkdir hugo_extended_0.110.0_Linux-64bit && tar -xf hugo_extended_0.110.0_Linux-64bit.tar.gz -C hugo_extended_0.110.0_Linux-64bit) - - wget https://github.com/gohugoio/hugo/releases/download/v0.83.0/hugo_extended_0.83.0_Linux-64bit.tar.gz - (mkdir hugo_extended_0.83.0_Linux-64bit && tar -xf hugo_extended_0.83.0_Linux-64bit.tar.gz -C hugo_extended_0.83.0_Linux-64bit) - - mkdir hugo - cp hugo_extended_0.110.0_Linux-64bit/hugo hugo/hugo-0.110 - cp hugo_extended_0.83.0_Linux-64bit/hugo hugo/hugo-0.83 - - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: '18.x' - - - name: Install npm packages - working-directory: ./site - run: | - npm ci - - - name: Build docs - run: | - pip install -r site/requirements.txt - python site/process_sdk_docs.py --input-dir /tmp/cvat_sdk/docs/ --site-root site/ - PATH="$PWD/hugo:$PATH" python site/build_docs.py - env: - HUGO_ENV: production - - - name: Deploy - if: github.ref == 'refs/heads/develop' - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./public - force_orphan: true - publish_dev_images: if: github.ref == 'refs/heads/develop' - needs: [rest_api_testing, unit_testing, e2e_testing, generate_github_pages] - runs-on: ubuntu-latest + needs: [rest_api_testing, unit_testing, e2e_testing] + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 @@ -480,7 +427,7 @@ jobs: docker push "${UI_IMAGE_REPO}:dev" codecov: - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big needs: [unit_testing, e2e_testing, rest_api_testing] steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/schedule.yml b/.github/workflows/schedule.yml index 0db0edec6a7b..2c1989b829aa 100644 --- a/.github/workflows/schedule.yml +++ b/.github/workflows/schedule.yml @@ -11,7 +11,7 @@ env: jobs: check_updates: - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big env: REPO: ${{ github.repository }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -44,7 +44,7 @@ jobs: build: needs: search_cache - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 @@ -107,7 +107,7 @@ jobs: unit_testing: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big steps: - uses: actions/checkout@v4 @@ -188,7 +188,7 @@ jobs: e2e_testing: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-latest-big strategy: fail-fast: false matrix: diff --git a/.vscode/launch.json b/.vscode/launch.json index d5c2a9ad9e7a..a9aa9de7fa6f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "configurations": [ { "name": "REST API tests: Attach to server", - "type": "python", + "type": "debugpy", "request": "attach", "connect": { "host": "127.0.0.1", @@ -26,7 +26,7 @@ }, { "name": "REST API tests: Attach to RQ annotation worker", - "type": "python", + "type": "debugpy", "request": "attach", "connect": { "host": "127.0.0.1", @@ -46,7 +46,7 @@ }, { "name": "REST API tests: Attach to RQ export worker", - "type": "python", + "type": "debugpy", "request": "attach", "connect": { "host": "127.0.0.1", @@ -66,7 +66,7 @@ }, { "name": "REST API tests: Attach to RQ import worker", - "type": "python", + "type": "debugpy", "request": "attach", "connect": { "host": "127.0.0.1", @@ -86,7 +86,7 @@ }, { "name": "REST API tests: Attach to RQ quality reports worker", - "type": "python", + "type": "debugpy", "request": "attach", "connect": { "host": "127.0.0.1", @@ -106,7 +106,7 @@ }, { "name": "REST API tests: Attach to RQ analytics reports worker", - "type": "python", + "type": "debugpy", "request": "attach", "connect": { "host": "127.0.0.1", @@ -158,7 +158,7 @@ }, { "name": "server: django", - "type": "python", + "type": "debugpy", "request": "launch", "stopOnEntry": false, "justMyCode": false, @@ -196,7 +196,7 @@ }, { "name": "server: RQ - import", - "type": "python", + "type": "debugpy", "request": "launch", "stopOnEntry": false, "justMyCode": false, @@ -218,7 +218,7 @@ }, { "name": "server: RQ - export", - "type": "python", + "type": "debugpy", "request": "launch", "stopOnEntry": false, "justMyCode": false, @@ -240,7 +240,7 @@ }, { "name": "server: RQ - quality reports", - "type": "python", + "type": "debugpy", "request": "launch", "stopOnEntry": false, "justMyCode": false, @@ -262,7 +262,7 @@ }, { "name": "server: RQ - analytics reports", - "type": "python", + "type": "debugpy", "request": "launch", "stopOnEntry": false, "justMyCode": false, @@ -284,7 +284,7 @@ }, { "name": "server: RQ - scheduler", - "type": "python", + "type": "debugpy", "request": "launch", "stopOnEntry": false, "justMyCode": false, @@ -303,7 +303,7 @@ }, { "name": "server: RQ - annotation", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -322,7 +322,7 @@ }, { "name": "server: RQ - webhooks", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -341,7 +341,7 @@ }, { "name": "server: RQ - cleaning", - "type": "python", + "type": "debugpy", "request": "launch", "stopOnEntry": false, "justMyCode": false, @@ -363,7 +363,7 @@ }, { "name": "server: migrate", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -379,7 +379,7 @@ }, { "name": "server: tests", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -399,7 +399,7 @@ }, { "name": "server: REST API tests", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -413,7 +413,7 @@ }, { "name": "sdk: tests", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -427,7 +427,7 @@ }, { "name": "cli: tests", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -441,7 +441,7 @@ }, { "name": "api client: Postprocess generator output", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -456,7 +456,7 @@ }, { "name": "docs: Postprocess SDK docs", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -471,7 +471,7 @@ }, { "name": "docs: Build docs", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, @@ -482,7 +482,7 @@ }, { "name": "server: Generate REST API Schema", - "type": "python", + "type": "debugpy", "request": "launch", "justMyCode": false, "stopOnEntry": false, diff --git a/CHANGELOG.md b/CHANGELOG.md index 86f28f3fe29b..1dcb33c6fa21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,75 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 + +## \[2.11.3\] - 2024-04-02 + +### Added + +- Tooltips for long names on cards (projects, tasks, cloud storages, and models) + () + +### Removed + +- The `POST /api/tasks/{id}/data` endpoint no longer accepts several + parameters that didn't have any useful function: `size`, + `compressed_chunk_type`, `original_chunk_type` + () + +### Fixed + +- Duplicated notifications for automatic annotation + () + +- Made quality report update job scheduling more efficient + () + +- Incorrect file name usage when importing annotations from a cloud storage + () + +- Using single shape annotation mode with multiple labels + () + +- Part of sidebar not visible in attribute annotation mode when there are a lot of attribute values + () + +- Changed interpolation behavior in `annotation.py`, now correctly keep the last frame +- Insert last frame if it is key to the track, fixes data corruption when tracks crossing more than 1 jobs + () + +- Label constructor validation of empty label names + () + +- Incorrect alignment of empty job list component + () + +- Remove underlying pixels feature is not applied immediately + () + +- Corrected the formula for per-class accuracy in quality reports; + the old formula is now exposed as the `jaccard_index` key + () + +- Sending `/events` request from logged-out user () + +- Fixed accuracy being displayed incorrectly on the task analytics page + () + +- Fixed an invalid default overlap size being selected for video tasks + with small segments + () + +- Fixed redundant jobs being created for tasks with non-zero overlap + in certain cases + () + +- Accumulation of confusion matrix across all jobs in a task when creating a quality report + () + +- 90 deg-rotated video was added with "Prefer Zip Chunks" disabled +was warped, fixed using the static cropImage function. + () + ## \[2.11.2\] - 2024-03-11 diff --git a/CITATION.cff b/CITATION.cff index 04b9fcf014f5..2934a318342f 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -13,7 +13,7 @@ authors: identifiers: - type: doi value: 10.5281/zenodo.4009388 -repository-code: 'https://github.com/opencv/cvat' +repository-code: 'https://github.com/cvat-ai/cvat' url: 'https://cvat.ai/' abstract: >- Annotate better with CVAT, the industry-leading diff --git a/Dockerfile.ui b/Dockerfile.ui index 1cf05dd101ad..9de104298460 100644 --- a/Dockerfile.ui +++ b/Dockerfile.ui @@ -34,7 +34,7 @@ DISABLE_SOURCE_MAPS="${DISABLE_SOURCE_MAPS}" \ UI_APP_CONFIG="${UI_APP_CONFIG}" \ SOURCE_MAPS_TOKEN="${SOURCE_MAPS_TOKEN}" yarn run build:cvat-ui -FROM nginx:mainline-alpine +FROM nginx:1.25.4-alpine3.18 # Replace default.conf configuration to remove unnecessary rules COPY cvat-ui/react_nginx.conf /etc/nginx/conf.d/default.conf COPY --from=cvat-ui /tmp/cvat-ui/dist /usr/share/nginx/html/ diff --git a/README.md b/README.md index 8d617c01eb9b..60c4800412f1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,11 @@ -![CVAT logo](site/content/en/images/cvat_poster_with_name.png) +

+ CVAT Platform +

+

+ + Start Annotating Now + +

# Computer Vision Annotation Tool (CVAT) @@ -18,30 +25,27 @@ AI approach. Start using CVAT online: [cvat.ai](https://cvat.ai). You can use it for free, or [subscribe](https://www.cvat.ai/pricing/cloud) to get unlimited data, -organizations, autoannotations, and [Roboflow and HuggingFace integration]( - https://www.cvat.ai/post/integrating-hugging-face-and-roboflow-models). +organizations, autoannotations, and [Roboflow and HuggingFace integration](https://www.cvat.ai/post/integrating-hugging-face-and-roboflow-models). Or set CVAT up as a self-hosted solution: -[Self-hosted Installation Guide](https://opencv.github.io/cvat/docs/administration/basics/installation/). +[Self-hosted Installation Guide](https://docs.cvat.ai/docs/administration/basics/installation/). We provide [Enterprise support](https://www.cvat.ai/pricing/on-prem) for self-hosted installations with premium features: SSO, LDAP, Roboflow and HuggingFace integrations, and advanced analytics (coming soon). We also do trainings and a dedicated support with 24 hour SLA. -![CVAT screencast](site/content/en/images/cvat-ai-screencast.gif) - ## Quick start ⚡ -- [Installation guide](https://opencv.github.io/cvat/docs/administration/basics/installation/) -- [Manual](https://opencv.github.io/cvat/docs/manual/) -- [Contributing](https://opencv.github.io/cvat/docs/contributing/) +- [Installation guide](https://docs.cvat.ai/docs/administration/basics/installation/) +- [Manual](https://docs.cvat.ai/docs/manual/) +- [Contributing](https://docs.cvat.ai/docs/contributing/) - [Datumaro dataset framework](https://github.com/cvat-ai/datumaro/blob/develop/README.md) - [Server API](#api) - [Python SDK](#sdk) - [Command line tool](#cli) -- [XML annotation format](https://opencv.github.io/cvat/docs/manual/advanced/xml_format/) -- [AWS Deployment Guide](https://opencv.github.io/cvat/docs/administration/basics/aws-deployment-guide/) -- [Frequently asked questions](https://opencv.github.io/cvat/docs/faq/) +- [XML annotation format](https://docs.cvat.ai/docs/manual/advanced/xml_format/) +- [AWS Deployment Guide](https://docs.cvat.ai/docs/administration/basics/aws-deployment-guide/) +- [Frequently asked questions](https://docs.cvat.ai/docs/faq/) - [Where to ask questions](#where-to-ask-questions) ## Partners ❤️ @@ -76,7 +80,7 @@ This is an online version of CVAT. It's free, efficient, and easy to use. to 10 tasks there and upload up to 500Mb of data to annotate. It will only be visible to you or the people you assign to it. -For now, it does not have [analytics features](https://opencv.github.io/cvat/docs/administration/advanced/analytics/) +For now, it does not have [analytics features](https://docs.cvat.ai/docs/administration/advanced/analytics/) like management and monitoring the data annotation team. It also does not allow exporting images, just the annotations. We plan to enhance [cvat.ai](https://cvat.ai) with new powerful features. Stay tuned! @@ -95,19 +99,20 @@ The images have been downloaded more than 1M times so far. Here are some screencasts showing how to use CVAT. + [Computer Vision Annotation Course](https://www.youtube.com/playlist?list=PL0to7Ng4PuuYQT4eXlHb_oIlq_RPeuasN): we introduce our course series designed to help you annotate data faster and better using CVAT. This course is about CVAT deployment and integrations, it includes presentations and covers the following topics: - **Speeding up your data annotation process: introduction to CVAT and Datumaro**. -What problems do CVAT and Datumaro solve, and how they can speed up your model -training process. Some resources you can use to learn more about how to use them. + What problems do CVAT and Datumaro solve, and how they can speed up your model + training process. Some resources you can use to learn more about how to use them. - **Deployment and use CVAT**. Use the app online at [app.cvat.ai](app.cvat.ai). -A local deployment. A containerized local deployment with Docker Compose (for regular use), -and a local cluster deployment with Kubernetes (for enterprise users). A 2-minute -tour of the interface, a breakdown of CVAT’s internals, and a demonstration of how -to deploy CVAT using Docker Compose. + A local deployment. A containerized local deployment with Docker Compose (for regular use), + and a local cluster deployment with Kubernetes (for enterprise users). A 2-minute + tour of the interface, a breakdown of CVAT’s internals, and a demonstration of how + to deploy CVAT using Docker Compose. [Product tour](https://www.youtube.com/playlist?list=PL0to7Ng4Puua37NJVMIShl_pzqJTigFzg): in this course, we show how to use CVAT, and help to get familiar with CVAT functionality and interfaces. This course does not cover integrations and is dedicated solely to CVAT. It covers the following topics: @@ -119,19 +124,19 @@ For feedback, please see [Contact us](#contact-us) ## API -- [Documentation](https://opencv.github.io/cvat/docs/api_sdk/api/) +- [Documentation](https://docs.cvat.ai/docs/api_sdk/api/) ## SDK - Install with `pip install cvat-sdk` - [PyPI package homepage](https://pypi.org/project/cvat-sdk/) -- [Documentation](https://opencv.github.io/cvat/docs/api_sdk/sdk/) +- [Documentation](https://docs.cvat.ai/docs/api_sdk/sdk/) ## CLI - Install with `pip install cvat-cli` - [PyPI package homepage](https://pypi.org/project/cvat-cli/) -- [Documentation](https://opencv.github.io/cvat/docs/api_sdk/cli/) +- [Documentation](https://docs.cvat.ai/docs/api_sdk/cli/) ## Supported annotation formats @@ -141,14 +146,14 @@ after clicking the **Upload annotation** and **Dump annotation** buttons. additional dataset transformations with its command line tool and Python library. For more information about the supported formats, see: -[Annotation Formats](https://opencv.github.io/cvat/docs/manual/advanced/formats/). +[Annotation Formats](https://docs.cvat.ai/docs/manual/advanced/formats/). | Annotation format | Import | Export | | ------------------------------------------------------------------------------------------------ | ------ | ------ | -| [CVAT for images](https://opencv.github.io/cvat/docs/manual/advanced/xml_format/#annotation) | ✔️ | ✔️ | -| [CVAT for a video](https://opencv.github.io/cvat/docs/manual/advanced/xml_format/#interpolation) | ✔️ | ✔️ | +| [CVAT for images](https://docs.cvat.ai/docs/manual/advanced/xml_format/#annotation) | ✔️ | ✔️ | +| [CVAT for a video](https://docs.cvat.ai/docs/manual/advanced/xml_format/#interpolation) | ✔️ | ✔️ | | [Datumaro](https://github.com/cvat-ai/datumaro) | ✔️ | ✔️ | | [PASCAL VOC](http://host.robots.ox.ac.uk/pascal/VOC/) | ✔️ | ✔️ | | Segmentation masks from [PASCAL VOC](http://host.robots.ox.ac.uk/pascal/VOC/) | ✔️ | ✔️ | @@ -182,7 +187,7 @@ up to 10x. Here is a list of the algorithms we support, and the platforms they c | Name | Type | Framework | CPU | GPU | | ------------------------------------------------------------------------------------------------------- | ---------- | ---------- | --- | --- | -| [Segment Anything](/serverless/pytorch/facebookresearch/sam/nuclio/) | interactor | PyTorch | ✔️ | ✔️ | +| [Segment Anything](/serverless/pytorch/facebookresearch/sam/nuclio/) | interactor | PyTorch | ✔️ | ✔️ | | [Deep Extreme Cut](/serverless/openvino/dextr/nuclio) | interactor | OpenVINO | ✔️ | | | [Faster RCNN](/serverless/openvino/omz/public/faster_rcnn_inception_resnet_v2_atrous_coco/nuclio) | detector | OpenVINO | ✔️ | | | [Mask RCNN](/serverless/openvino/omz/public/mask_rcnn_inception_resnet_v2_atrous_coco/nuclio) | detector | OpenVINO | ✔️ | | @@ -251,8 +256,8 @@ questions and get our support. [docker-server-image-url]: https://hub.docker.com/r/cvat/server [docker-ui-pulls-img]: https://img.shields.io/docker/pulls/cvat/ui.svg?style=flat-square&label=UI%20pulls [docker-ui-image-url]: https://hub.docker.com/r/cvat/ui -[ci-img]: https://github.com/opencv/cvat/actions/workflows/main.yml/badge.svg?branch=develop -[ci-url]: https://github.com/opencv/cvat/actions +[ci-img]: https://github.com/cvat-ai/cvat/actions/workflows/main.yml/badge.svg?branch=develop +[ci-url]: https://github.com/cvat-ai/cvat/actions [gitter-img]: https://img.shields.io/gitter/room/opencv-cvat/public?style=flat [gitter-url]: https://gitter.im/opencv-cvat/public [coverage-img]: https://codecov.io/github/opencv/cvat/branch/develop/graph/badge.svg diff --git a/changelog.d/20240313_014112_umangapatel123_refactor_into_usereducer.md b/changelog.d/20240313_014112_umangapatel123_refactor_into_usereducer.md deleted file mode 100644 index ac7ca1a92b5e..000000000000 --- a/changelog.d/20240313_014112_umangapatel123_refactor_into_usereducer.md +++ /dev/null @@ -1,4 +0,0 @@ -### Fixed - -- Incorrect file name usage when importing annotations from a cloud storage - () diff --git a/changelog.d/20240313_200940_syedbarimnajan_long_cardname_tooltip.md b/changelog.d/20240313_200940_syedbarimnajan_long_cardname_tooltip.md deleted file mode 100644 index 9887c6e24a82..000000000000 --- a/changelog.d/20240313_200940_syedbarimnajan_long_cardname_tooltip.md +++ /dev/null @@ -1,4 +0,0 @@ -### Added - -- Tooltips for long names on cards (projects, tasks, cloud storages, and models) - () diff --git a/changelog.d/20240314_105752_boris_fixed_ssa.md b/changelog.d/20240314_105752_boris_fixed_ssa.md deleted file mode 100644 index 1756e3924c99..000000000000 --- a/changelog.d/20240314_105752_boris_fixed_ssa.md +++ /dev/null @@ -1,4 +0,0 @@ -### Fixed - -- Using single shape annotation mode with multiple labels - () diff --git a/changelog.d/20240314_162039_boris_added_scroll_aam.md b/changelog.d/20240314_162039_boris_added_scroll_aam.md deleted file mode 100644 index d254041a2270..000000000000 --- a/changelog.d/20240314_162039_boris_added_scroll_aam.md +++ /dev/null @@ -1,4 +0,0 @@ -### Fixed - -- Part of sidebar not visible in attribute annotation mode when there are a lot of attribute values - () diff --git a/changelog.d/20240320_174524_andrew.yunxiang.md b/changelog.d/20240320_174524_andrew.yunxiang.md new file mode 100644 index 000000000000..5929c0c8c376 --- /dev/null +++ b/changelog.d/20240320_174524_andrew.yunxiang.md @@ -0,0 +1,4 @@ +### Fixed + +- Creating tasks with special characters in uploaded filename + () diff --git a/changelog.d/20240322_004121_krishavrajsingh_Count_Annotations.md b/changelog.d/20240322_004121_krishavrajsingh_Count_Annotations.md new file mode 100644 index 000000000000..5e8daf3729b7 --- /dev/null +++ b/changelog.d/20240322_004121_krishavrajsingh_Count_Annotations.md @@ -0,0 +1,4 @@ +### Added + +- Number of objects on the frame is shown on the right sidebar + () diff --git a/changelog.d/20240402_143458_boris.md b/changelog.d/20240402_143458_boris.md new file mode 100644 index 000000000000..4423e43ec69c --- /dev/null +++ b/changelog.d/20240402_143458_boris.md @@ -0,0 +1,4 @@ +### Fixed + +- Objects menu is invisible for GT objects in GT job + () diff --git a/changelog.d/20240403_144021_maria_update_module_versions.md b/changelog.d/20240403_144021_maria_update_module_versions.md new file mode 100644 index 000000000000..b5a1d2ced54f --- /dev/null +++ b/changelog.d/20240403_144021_maria_update_module_versions.md @@ -0,0 +1,4 @@ +### Fixed + +- Missing RegisterSerializerEx `email_verification_required` and `key` parameters now are included in the server schema + () diff --git a/changelog.d/20240403_153414_syedbarimnajan_empty_list_components.md b/changelog.d/20240403_153414_syedbarimnajan_empty_list_components.md new file mode 100644 index 000000000000..edd359ad2f73 --- /dev/null +++ b/changelog.d/20240403_153414_syedbarimnajan_empty_list_components.md @@ -0,0 +1,4 @@ +### Fixed + +- Standardize the alignment of empty-list components + () diff --git a/changelog.d/20240403_181532_roman_update_urls.md b/changelog.d/20240403_181532_roman_update_urls.md new file mode 100644 index 000000000000..c541e21c85b8 --- /dev/null +++ b/changelog.d/20240403_181532_roman_update_urls.md @@ -0,0 +1,5 @@ +### Changed + +- Updated links to the documentation website to point to the new domain, + `docs.cvat.ai` + () diff --git a/changelog.d/20240404_122043_mzhiltso_update_datumaro_dep.md b/changelog.d/20240404_122043_mzhiltso_update_datumaro_dep.md new file mode 100644 index 000000000000..0b98f8285851 --- /dev/null +++ b/changelog.d/20240404_122043_mzhiltso_update_datumaro_dep.md @@ -0,0 +1,7 @@ +### Fixed + +- Labels in WiderFace dataset example + () +- Export without images in Datumaro format - + no empty "media" and "point_cloud" fields should be present + () diff --git a/changelog.d/fragment.j2 b/changelog.d/fragment.j2 index 700bccd0c6e5..0016248a6323 100644 --- a/changelog.d/fragment.j2 +++ b/changelog.d/fragment.j2 @@ -1,4 +1,4 @@ ### {{ config.categories | join('|') }} - Describe your change here... - () + () diff --git a/cvat-core/package.json b/cvat-core/package.json index 5e57ad15cc68..ab537343f248 100644 --- a/cvat-core/package.json +++ b/cvat-core/package.json @@ -1,6 +1,6 @@ { "name": "cvat-core", - "version": "15.0.1", + "version": "15.0.2", "type": "module", "description": "Part of Computer Vision Tool which presents an interface for client-side integration", "main": "src/api.ts", diff --git a/cvat-core/src/index.ts b/cvat-core/src/index.ts index e4bdde9ba091..2843767e254d 100644 --- a/cvat-core/src/index.ts +++ b/cvat-core/src/index.ts @@ -160,7 +160,7 @@ export default interface CVATCore { enabled: boolean; onEmptyMaskOccurrence: () => void | null; }; - onOrganizationChange: typeof config.onOrganizationChange; + onOrganizationChange: (newOrgId: number | null) => void | null; globalObjectsCounter: typeof config.globalObjectsCounter; }, client: { diff --git a/cvat-core/src/lambda-manager.ts b/cvat-core/src/lambda-manager.ts index c0c41cb63288..39301cf853ac 100644 --- a/cvat-core/src/lambda-manager.ts +++ b/cvat-core/src/lambda-manager.ts @@ -106,7 +106,7 @@ class LambdaManager { async listen( requestID: string, - functionID: string, + functionID: string | number, callback: (status: RQStatus, progress: number, message?: string) => void, ): Promise { const model = this.cachedList.find((_model) => _model.id === functionID); diff --git a/cvat-core/src/logger.ts b/cvat-core/src/logger.ts index d13b1d7a6fe3..1e8fdb174213 100644 --- a/cvat-core/src/logger.ts +++ b/cvat-core/src/logger.ts @@ -225,6 +225,8 @@ Object.defineProperties(Logger.prototype.save, { // potentially new events may be generated during saving // that is why we add this.collection this.collection = [...collectionToSend, ...this.collection]; + + throw error; } finally { this.saving = false; } diff --git a/cvat-core/src/quality-report.ts b/cvat-core/src/quality-report.ts index 652241527e86..13cbb1e5c7cf 100644 --- a/cvat-core/src/quality-report.ts +++ b/cvat-core/src/quality-report.ts @@ -85,8 +85,7 @@ export default class QualityReport { validCount: this.#summary.valid_count, dsCount: this.#summary.ds_count, gtCount: this.#summary.gt_count, - accuracy: (this.#summary.valid_count / - (this.#summary.ds_count + this.#summary.gt_count - this.#summary.valid_count)) * 100, + accuracy: (this.#summary.valid_count / this.#summary.total_count) * 100, precision: (this.#summary.valid_count / this.#summary.gt_count) * 100, recall: (this.#summary.valid_count / this.#summary.ds_count) * 100, conflictsByType: { diff --git a/cvat-core/src/server-response-types.ts b/cvat-core/src/server-response-types.ts index 658fa2ff20e0..d3bed8ba7f25 100644 --- a/cvat-core/src/server-response-types.ts +++ b/cvat-core/src/server-response-types.ts @@ -307,6 +307,7 @@ export interface SerializedQualityReportData { valid_count: number; ds_count: number; gt_count: number; + total_count: number; error_count: number; warning_count: number; conflicts_by_type: { diff --git a/cvat-data/src/ts/cvat-data.ts b/cvat-data/src/ts/cvat-data.ts index 105e0adc3c1b..a01dcbb7ca2e 100644 --- a/cvat-data/src/ts/cvat-data.ts +++ b/cvat-data/src/ts/cvat-data.ts @@ -200,6 +200,36 @@ export class FrameDecoder { return null; } + static cropImage( + imageBuffer: ArrayBuffer, + imageWidth: number, + imageHeight: number, + width: number, + height: number, + ): ImageData { + if (width === imageWidth && height === imageHeight) { + return new ImageData(new Uint8ClampedArray(imageBuffer), width, height); + } + const source = new Uint32Array(imageBuffer); + + const bufferSize = width * height * 4; + if (imageWidth === width) { + return new ImageData(new Uint8ClampedArray(imageBuffer, 0, bufferSize), width, height); + } + + const buffer = new ArrayBuffer(bufferSize); + const rgbaInt32 = new Uint32Array(buffer); + const rgbaInt8Clamped = new Uint8ClampedArray(buffer); + let writeIdx = 0; + for (let row = 0; row < height; row++) { + const start = row * imageWidth; + rgbaInt32.set(source.subarray(start, start + width), writeIdx); + writeIdx += width; + } + + return new ImageData(rgbaInt8Clamped, width, height); + } + async startDecode(): Promise { const blockToDecode = { ...this.requestedChunkToDecode }; const release = await this.mutex.acquire(); @@ -239,8 +269,13 @@ export class FrameDecoder { const height = Math.round(this.renderHeight / scaleFactor); const width = Math.round(this.renderWidth / scaleFactor); - const array = new Uint8ClampedArray(e.data.buf.slice(0, width * height * 4)); - createImageBitmap(new ImageData(array, width)).then((bitmap) => { + createImageBitmap(FrameDecoder.cropImage( + e.data.buf, + e.data.width, + e.data.height, + width, + height, + )).then((bitmap) => { decodedFrames[keptIndex] = bitmap; this.chunkIsBeingDecoded.onDecode(keptIndex, decodedFrames[keptIndex]); diff --git a/cvat-sdk/README.md b/cvat-sdk/README.md index cf5732aaeba7..fa68c0e5d40d 100644 --- a/cvat-sdk/README.md +++ b/cvat-sdk/README.md @@ -10,7 +10,7 @@ The SDK API includes several layers: - PyTorch adapter. Located at `cvat_sdk.pytorch`. * Auto-annotation support. Located at `cvat_sdk.auto_annotation`. -Package documentation is available [here](https://opencv.github.io/cvat/docs/api_sdk/sdk). +Package documentation is available [here](https://docs.cvat.ai/docs/api_sdk/sdk). ## Installation & Usage @@ -26,7 +26,7 @@ To use the PyTorch adapter, request the `pytorch` extra: pip install "cvat-sdk[pytorch]" ``` -To install from the local directory, follow [the developer guide](https://opencv.github.io/cvat/docs/api_sdk/sdk/developer_guide). +To install from the local directory, follow [the developer guide](https://docs.cvat.ai/docs/api_sdk/sdk/developer_guide). After installation you can import the package: diff --git a/cvat-sdk/gen/templates/openapi-generator/api_doc.mustache b/cvat-sdk/gen/templates/openapi-generator/api_doc.mustache index 95be916e1cfe..7a885a6c00dd 100644 --- a/cvat-sdk/gen/templates/openapi-generator/api_doc.mustache +++ b/cvat-sdk/gen/templates/openapi-generator/api_doc.mustache @@ -38,7 +38,7 @@ Name | Type | Description | Notes {{/optionalParams}} There are also optional kwargs that control the function invocation behavior. -[Read more here](https://opencv.github.io/cvat/docs/api_sdk/sdk/lowlevel-api/#sending-requests). +[Read more here](https://docs.cvat.ai/docs/api_sdk/sdk/lowlevel-api/#sending-requests). ### Returned values @@ -49,7 +49,7 @@ Returns a tuple with 2 values: `({{#returnType}}parsed_response{{/returnType}}{{ {{#returnType}}The first value is a model parsed from the response data.{{/returnType}}{{^returnType}}This endpoint does not have any return value, so `None` is always returned as the first value.{{/returnType}} The second value is the raw response, which can be useful to get response parameters, such as status code, headers, or raw response data. Read more about invocation parameters -and returned values [here](https://opencv.github.io/cvat/docs/api_sdk/sdk/lowlevel-api/#sending-requests). +and returned values [here](https://docs.cvat.ai/docs/api_sdk/sdk/lowlevel-api/#sending-requests). ### Authorization diff --git a/cvat-ui/README.md b/cvat-ui/README.md index b89fc6449423..5205041568e6 100644 --- a/cvat-ui/README.md +++ b/cvat-ui/README.md @@ -36,5 +36,5 @@ yarn run build yarn run build --mode=development # without a minification ``` -Important: You also have to run CVAT REST API server (please read `https://opencv.github.io/cvat/docs/contributing/`) +Important: You also have to run CVAT REST API server (please read `https://docs.cvat.ai/docs/contributing/`) to correct working since UI gets all necessary data (tasks, users, annotations) from there diff --git a/cvat-ui/package.json b/cvat-ui/package.json index dfcdc29a5da4..bdba3d5ae999 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.63.2", + "version": "1.63.6", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index 091fe1e80d55..bab89b190575 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -13,7 +13,7 @@ import { RectDrawingMethod, CuboidDrawingMethod, Canvas, CanvasMode as Canvas2DMode, } from 'cvat-canvas-wrapper'; import { - getCore, MLModel, JobType, Job, QualityConflict, + getCore, MLModel, JobType, Job, QualityConflict, ObjectState, } from 'cvat-core-wrapper'; import logger, { EventScope } from 'cvat-logger'; import { getCVATStore } from 'cvat-store'; @@ -34,7 +34,7 @@ import { updateJobAsync } from './jobs-actions'; import { switchToolsBlockerState } from './settings-actions'; interface AnnotationsParameters { - filters: string[]; + filters: object[]; frame: number; showAllInterpolationTracks: boolean; showGroundTruth: boolean; @@ -266,7 +266,7 @@ export function highlightConflict(conflict: QualityConflict | null): AnyAction { }; } -async function fetchAnnotations(frameNumber?: number): Promise<{ +async function fetchAnnotations(predefinedFrame?: number): Promise<{ states: CombinedState['annotation']['annotations']['states']; history: CombinedState['annotation']['annotations']['history']; minZ: number; @@ -277,10 +277,22 @@ async function fetchAnnotations(frameNumber?: number): Promise<{ jobInstance, showGroundTruth, groundTruthInstance, } = receiveAnnotationsParameters(); - const fetchFrame = typeof frameNumber === 'undefined' ? frame : frameNumber; - const states = await jobInstance.annotations.get(fetchFrame, showAllInterpolationTracks, filters); + const fetchFrame = typeof predefinedFrame === 'undefined' ? frame : predefinedFrame; + let states = await jobInstance.annotations.get(fetchFrame, showAllInterpolationTracks, filters); const [minZ, maxZ] = computeZRange(states); - if (showGroundTruth && groundTruthInstance) { + if (jobInstance.type === JobType.GROUND_TRUTH) { + states = states.map((state: ObjectState) => new Proxy(state, { + get(_state, prop) { + if (prop === 'isGroundTruth') { + // ground truth objects are not considered as gt objects, relatively to a gt jobs + // to avoid extra css styles, or restrictions applied + return false; + } + + return Reflect.get(_state, prop); + }, + })); + } else if (showGroundTruth && groundTruthInstance) { const gtStates = await groundTruthInstance.annotations.get(fetchFrame, showAllInterpolationTracks, filters); states.push(...gtStates); } @@ -934,9 +946,9 @@ export function getJobAsync({ )) || job.startFrame; const frameData = await job.frames.get(frameNumber); - // call first getting of frame data before rendering interface - // to load and decode first chunk try { + // call first getting of frame data before rendering interface + // to load and decode first chunk await frameData.data(); } catch (error) { // do nothing, user will be notified when data request is done @@ -944,7 +956,6 @@ export function getJobAsync({ const states = await job.annotations.get(frameNumber, showAllInterpolationTracks, filters); const issues = await job.issues(); - const [minZ, maxZ] = computeZRange(states); const colors = [...cvat.enums.colors]; let groundTruthJobFramesMeta = null; @@ -981,11 +992,10 @@ export function getJobAsync({ frameData, colors, filters, - minZ, - maxZ, }, }); + dispatch(fetchAnnotationsAsync()); dispatch(changeFrameAsync(frameNumber, false)); } catch (error) { dispatch({ diff --git a/cvat-ui/src/actions/models-actions.ts b/cvat-ui/src/actions/models-actions.ts index 233751b0f3d3..38a991816234 100644 --- a/cvat-ui/src/actions/models-actions.ts +++ b/cvat-ui/src/actions/models-actions.ts @@ -1,5 +1,5 @@ // Copyright (C) 2020-2022 Intel Corporation -// Copyright (C) 2022-2023 CVAT.ai Corporation +// Copyright (C) 2022-2024 CVAT.ai Corporation // // SPDX-License-Identifier: MIT @@ -20,6 +20,7 @@ export enum ModelsActionTypes { DELETE_MODEL = 'DELETE_MODEL', DELETE_MODEL_SUCCESS = 'DELETE_MODEL_SUCCESS', DELETE_MODEL_FAILED = 'DELETE_MODEL_FAILED', + GET_INFERENCES_SUCCESS = 'GET_INFERENCES_SUCCESS', START_INFERENCE_FAILED = 'START_INFERENCE_FAILED', GET_INFERENCE_STATUS_SUCCESS = 'GET_INFERENCE_STATUS_SUCCESS', GET_INFERENCE_STATUS_FAILED = 'GET_INFERENCE_STATUS_FAILED', @@ -45,6 +46,9 @@ export const modelsActions = { error, }), fetchMetaFailed: (error: any) => createAction(ModelsActionTypes.FETCH_META_FAILED, { error }), + getInferencesSuccess: (requestedInferenceIDs: Record) => ( + createAction(ModelsActionTypes.GET_INFERENCES_SUCCESS, { requestedInferenceIDs }) + ), getInferenceStatusSuccess: (taskID: number, activeInference: ActiveInference) => ( createAction(ModelsActionTypes.GET_INFERENCE_STATUS_SUCCESS, { taskID, @@ -64,9 +68,10 @@ export const modelsActions = { error, }) ), - cancelInferenceSuccess: (taskID: number) => ( + cancelInferenceSuccess: (taskID: number, activeInference: ActiveInference) => ( createAction(ModelsActionTypes.CANCEL_INFERENCE_SUCCESS, { taskID, + activeInference, }) ), cancelInferenceFailed: (taskID: number, error: any) => ( @@ -119,8 +124,9 @@ interface InferenceMeta { function listen(inferenceMeta: InferenceMeta, dispatch: (action: ModelsActions) => void): void { const { taskID, requestID, functionID } = inferenceMeta; + core.lambda - .listen(requestID, functionID, (status: RQStatus, progress: number, message: string) => { + .listen(requestID, functionID, (status: RQStatus, progress: number, message?: string) => { if (status === RQStatus.FAILED || status === RQStatus.UNKNOWN) { dispatch( modelsActions.getInferenceStatusFailed( @@ -129,7 +135,7 @@ function listen(inferenceMeta: InferenceMeta, dispatch: (action: ModelsActions) status, progress, functionID, - error: message, + error: message as string, id: requestID, }, new Error(`Inference status for the task ${taskID} is ${status}. ${message}`), @@ -144,7 +150,7 @@ function listen(inferenceMeta: InferenceMeta, dispatch: (action: ModelsActions) status, progress, functionID, - error: message, + error: message as string, id: requestID, }), ); @@ -163,13 +169,16 @@ function listen(inferenceMeta: InferenceMeta, dispatch: (action: ModelsActions) } export function getInferenceStatusAsync(): ThunkAction { - return async (dispatch): Promise => { + return async (dispatch, getState): Promise => { const dispatchCallback = (action: ModelsActions): void => { dispatch(action); }; + const { requestedInferenceIDs } = getState().models; + try { const requests = await core.lambda.requests(); + const newListenedIDs: Record = {}; requests .map((request: any): object => ({ taskID: +request.function.task, @@ -177,8 +186,12 @@ export function getInferenceStatusAsync(): ThunkAction { functionID: request.function.id, })) .forEach((inferenceMeta: InferenceMeta): void => { - listen(inferenceMeta, dispatchCallback); + if (!(inferenceMeta.requestID in requestedInferenceIDs)) { + listen(inferenceMeta, dispatchCallback); + newListenedIDs[inferenceMeta.requestID] = true; + } }); + dispatch(modelsActions.getInferencesSuccess(newListenedIDs)); } catch (error) { dispatch(modelsActions.fetchMetaFailed(error)); } @@ -201,6 +214,7 @@ export function startInferenceAsync(taskId: number, model: MLModel, body: object }, dispatchCallback, ); + dispatch(modelsActions.getInferencesSuccess({ [requestID]: true })); } catch (error) { dispatch(modelsActions.startInferenceFailed(taskId, error)); } @@ -212,7 +226,7 @@ export function cancelInferenceAsync(taskID: number): ThunkAction { try { const inference = getState().models.inferences[taskID]; await core.lambda.cancel(inference.id, inference.functionID); - dispatch(modelsActions.cancelInferenceSuccess(taskID)); + dispatch(modelsActions.cancelInferenceSuccess(taskID, inference)); } catch (error) { dispatch(modelsActions.cancelInferenceFailed(taskID, error)); } diff --git a/cvat-ui/src/components/annotation-page/canvas/views/canvas2d/brush-tools.tsx b/cvat-ui/src/components/annotation-page/canvas/views/canvas2d/brush-tools.tsx index 142967634002..f8370a47047d 100644 --- a/cvat-ui/src/components/annotation-page/canvas/views/canvas2d/brush-tools.tsx +++ b/cvat-ui/src/components/annotation-page/canvas/views/canvas2d/brush-tools.tsx @@ -83,7 +83,6 @@ function BrushTools(): React.ReactPortal | null { useEffect(() => { const label = labels.find((_label: any) => _label.id === defaultLabelID); - getCore().config.removeUnderlyingMaskPixels.enabled = removeUnderlyingPixels; if (visible && label && canvasInstance instanceof Canvas) { const onUpdateConfiguration = ({ brushTool }: any): void => { if (brushTool?.size) { @@ -122,6 +121,10 @@ function BrushTools(): React.ReactPortal | null { } }, [currentTool, brushSize, brushForm, visible, defaultLabelID, editableState]); + useEffect(() => { + getCore().config.removeUnderlyingMaskPixels.enabled = removeUnderlyingPixels; + }, [removeUnderlyingPixels]); + useEffect(() => { setApplicableLabels(filterApplicableForType(LabelType.MASK, labels)); }, [labels]); diff --git a/cvat-ui/src/components/annotation-page/single-shape-workspace/styles.scss b/cvat-ui/src/components/annotation-page/single-shape-workspace/styles.scss index 195dffd51814..57863624ee0e 100644 --- a/cvat-ui/src/components/annotation-page/single-shape-workspace/styles.scss +++ b/cvat-ui/src/components/annotation-page/single-shape-workspace/styles.scss @@ -11,6 +11,7 @@ .cvat-single-shape-annotation-sidebar { padding: $grid-unit-size; overflow: auto; + background: $background-color-2; .cvat-single-shape-annotation-sidebar-label-select, .cvat-single-shape-annotation-sidebar-label-type-selector { diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/issues-list.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/issues-list.tsx index 463089d414ae..6718fc63f844 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/issues-list.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/issues-list.tsx @@ -74,6 +74,9 @@ export default function LabelsListComponent(): JSX.Element {
+ {`Items: ${frameIssues.length}`} + + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/labels-list.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/labels-list.tsx index c90ecab7d79d..60248bae006c 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/labels-list.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/labels-list.tsx @@ -1,5 +1,5 @@ // Copyright (C) 2020-2022 Intel Corporation -// Copyright (C) 2022 CVAT.ai Corporation +// Copyright (C) 2022-2024 CVAT.ai Corporation // // SPDX-License-Identifier: MIT @@ -12,6 +12,7 @@ import { CombinedState, ObjectType } from 'reducers'; import { rememberObject, updateAnnotationsAsync } from 'actions/annotation-actions'; import LabelItemContainer from 'containers/annotation-page/standard-workspace/objects-side-bar/label-item'; import GlobalHotKeys from 'utils/mousetrap-react'; +import Text from 'antd/lib/typography/Text'; function LabelsListComponent(): JSX.Element { const dispatch = useDispatch(); @@ -21,7 +22,6 @@ function LabelsListComponent(): JSX.Element { const activeObjectType = useSelector((state: CombinedState) => state.annotation.drawing.activeObjectType); const states = useSelector((state: CombinedState) => state.annotation.annotations.states); const keyMap = useSelector((state: CombinedState) => state.shortcuts.keyMap); - const labelIDs = labels.map((label: any): number => label.id); const [keyToLabelMapping, setKeyToLabelMapping] = useState>( @@ -100,6 +100,9 @@ function LabelsListComponent(): JSX.Element { return (
+
+ {`Items: ${labels.length}`} +
{labelIDs.map( (labelID: number): JSX.Element => ( { // wrap to internal use effect to avoid issues // with chinese keyboard - // https://github.com/opencv/cvat/pull/6916 + // https://github.com/cvat-ai/cvat/pull/6916 if (localAttrValue !== attrValue) { changeAttribute(attrID, localAttrValue); } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-list-header.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-list-header.tsx index 304e6a1f225c..714f89e43415 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-list-header.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-list-header.tsx @@ -13,6 +13,7 @@ import Icon, { UnlockOutlined, } from '@ant-design/icons'; import { Col, Row } from 'antd/lib/grid'; +import Text from 'antd/lib/typography/Text'; import StatesOrderingSelector from 'components/annotation-page/standard-workspace/objects-side-bar/states-ordering-selector'; import CVATTooltip from 'components/common/cvat-tooltip'; @@ -29,6 +30,7 @@ interface Props { switchLockAllShortcut: string; switchHiddenAllShortcut: string; showGroundTruth: boolean; + count: number; changeStatesOrdering(value: StatesOrdering): void; lockAllStates(): void; unlockAllStates(): void; @@ -44,7 +46,7 @@ function LockAllSwitcher(props: Props): JSX.Element { statesLocked, switchLockAllShortcut, unlockAllStates, lockAllStates, } = props; return ( - + {statesLocked ? : } @@ -57,7 +59,7 @@ function HideAllSwitcher(props: Props): JSX.Element { statesHidden, switchHiddenAllShortcut, showAllStates, hideAllStates, } = props; return ( - +