Skip to content

Commit

Permalink
Add auto-annotation support to SDK and CLI (#6483)
Browse files Browse the repository at this point in the history
Introduce a `cvat-sdk auto-annotate` command that downloads data for a task,
then runs a function on the local computer on that data, and uploads
resulting annotations back to the task.

To support this functionality, add a new SDK module,
`cvat_sdk.auto_annotation`, that contains an interface that the
functions must follow, and a driver that applies a function to a task.

This will let users easily annotate their tasks with custom DL models.
  • Loading branch information
SpecLad authored Aug 2, 2023
1 parent c56f2e9 commit 1c0a49f
Show file tree
Hide file tree
Showing 18 changed files with 1,293 additions and 8 deletions.
13 changes: 8 additions & 5 deletions .github/workflows/full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,19 @@ jobs:
name: expected_schema
path: cvat/schema-expected.yml

- name: Running REST API and SDK tests
id: run_tests
- name: Generate SDK
run: |
pip3 install -r cvat-sdk/gen/requirements.txt
./cvat-sdk/gen/generate.sh
pip3 install -r ./tests/python/requirements.txt
pip3 install -e ./cvat-sdk
pip3 install -e ./cvat-cli
- name: Install SDK
run: |
pip3 install -r ./tests/python/requirements.txt \
-e './cvat-sdk[pytorch,ultralytics]' -e ./cvat-cli
- name: Running REST API and SDK tests
id: run_tests
run: |
pytest tests/python/
- name: Creating a log file from cvat containers
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ jobs:
- name: Install SDK
run: |
pip3 install -r ./tests/python/requirements.txt \
-e './cvat-sdk[pytorch]' -e ./cvat-cli
-e './cvat-sdk[pytorch,ultralytics]' -e ./cvat-cli
- name: Run REST API and SDK tests
id: run_tests
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- \[SDK\] A `DeferredTqdmProgressReporter` class, which doesn't have glitchy output
like `TqdmProgressReporter` in certain circumstances
(<https://github.com/opencv/cvat/pull/6556>)
- \[SDK, CLI\] A `cvat_sdk.auto_annotation` module that provides
functionality for automatically annotating a task by running a
user-provided function on the local machine, and a corresponding CLI command
(`auto-annotate`)
(<https://github.com/opencv/cvat/pull/6483>)

### Changed

Expand Down
1 change: 1 addition & 0 deletions cvat-cli/src/cvat_cli/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def main(args: List[str] = None):
"upload": CLI.tasks_upload,
"export": CLI.tasks_export,
"import": CLI.tasks_import,
"auto-annotate": CLI.tasks_auto_annotate,
}
parser = make_cmdline_parser()
parsed_args = parser.parse_args(args)
Expand Down
33 changes: 32 additions & 1 deletion cvat-cli/src/cvat_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@

from __future__ import annotations

import importlib
import importlib.util
import json
from typing import Dict, List, Sequence, Tuple
from pathlib import Path
from typing import Dict, List, Optional, Sequence, Tuple

import cvat_sdk.auto_annotation as cvataa
from cvat_sdk import Client, models
from cvat_sdk.core.helpers import DeferredTqdmProgressReporter
from cvat_sdk.core.proxies.tasks import ResourceType
Expand Down Expand Up @@ -140,3 +144,30 @@ def tasks_import(self, filename: str, *, status_check_period: int = 2) -> None:
status_check_period=status_check_period,
pbar=DeferredTqdmProgressReporter(),
)

def tasks_auto_annotate(
self,
task_id: int,
*,
function_module: Optional[str] = None,
function_file: Optional[Path] = None,
clear_existing: bool = False,
allow_unmatched_labels: bool = False,
) -> None:
if function_module is not None:
function = importlib.import_module(function_module)
elif function_file is not None:
module_spec = importlib.util.spec_from_file_location("__cvat_function__", function_file)
function = importlib.util.module_from_spec(module_spec)
module_spec.loader.exec_module(function)
else:
assert False, "function identification arguments missing"

cvataa.annotate_task(
self.client,
task_id,
function,
pbar=DeferredTqdmProgressReporter(),
clear_existing=clear_existing,
allow_unmatched_labels=allow_unmatched_labels,
)
35 changes: 35 additions & 0 deletions cvat-cli/src/cvat_cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os
import textwrap
from distutils.util import strtobool
from pathlib import Path

from cvat_sdk.core.proxies.tasks import ResourceType

Expand Down Expand Up @@ -369,6 +370,40 @@ def make_cmdline_parser() -> argparse.ArgumentParser:
help="time interval between checks if archive processing was finished, in seconds",
)

#######################################################################
# Auto-annotate
#######################################################################
auto_annotate_task_parser = task_subparser.add_parser(
"auto-annotate",
description="Automatically annotate a CVAT task by running a function on the local machine.",
)
auto_annotate_task_parser.add_argument("task_id", type=int, help="task ID")

function_group = auto_annotate_task_parser.add_mutually_exclusive_group(required=True)

function_group.add_argument(
"--function-module",
metavar="MODULE",
help="qualified name of a module to use as the function",
)

function_group.add_argument(
"--function-file",
metavar="PATH",
type=Path,
help="path to a Python source file to use as the function",
)

auto_annotate_task_parser.add_argument(
"--clear-existing", action="store_true", help="Remove existing annotations from the task"
)

auto_annotate_task_parser.add_argument(
"--allow-unmatched-labels",
action="store_true",
help="Allow the function to declare labels not configured in the task",
)

return parser


Expand Down
17 changes: 17 additions & 0 deletions cvat-sdk/cvat_sdk/auto_annotation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright (C) 2023 CVAT.ai Corporation
#
# SPDX-License-Identifier: MIT

from .driver import BadFunctionError, annotate_task
from .interface import (
DetectionFunction,
DetectionFunctionContext,
DetectionFunctionSpec,
keypoint,
keypoint_spec,
label_spec,
rectangle,
shape,
skeleton,
skeleton_label_spec,
)
Loading

0 comments on commit 1c0a49f

Please sign in to comment.