Projects
Projects group related tasks and define shared labels.Creating Projects
from cvat_sdk import Client, models
client = Client(url="cvat.example.com")
client.login(("username", "password"))
# Define project specification
project_spec = models.ProjectWriteRequest(
name="Self-Driving Car Dataset",
labels=[
models.PatchedLabelRequest(
name="car",
color="#ff0000",
type="rectangle"
),
models.PatchedLabelRequest(
name="pedestrian",
color="#00ff00",
type="rectangle"
),
models.PatchedLabelRequest(
name="traffic_light",
color="#0000ff",
type="rectangle"
)
]
)
project = client.projects.create(spec=project_spec)
print(f"Created project {project.id}: {project.name}")
Creating Projects with Dataset
Import a dataset when creating a project:project = client.projects.create_from_dataset(
spec=project_spec,
dataset_path="annotations.zip",
dataset_format="COCO 1.0",
conv_mask_to_poly=False # Keep masks as is
)
Listing Projects
# List all projects
projects = client.projects.list()
for project in projects:
print(f"Project {project.id}: {project.name}")
print(f" Owner: {project.owner.username}")
print(f" Created: {project.created_date}")
print(f" Tasks: {len(project.tasks) if hasattr(project, 'tasks') else 'N/A'}")
Retrieving a Project
project = client.projects.retrieve(project_id=123)
print(f"Name: {project.name}")
print(f"Labels: {len(project.labels)}")
print(f"Status: {project.status}")
Updating Projects
# Update project name
project.update(models.PatchedProjectWriteRequest(name="Updated Project Name"))
# Refresh project data from server
project.fetch()
Working with Project Resources
# Get project tasks
tasks = project.get_tasks()
for task in tasks:
print(f"Task {task.id}: {task.name}")
# Get project labels
labels = project.get_labels()
for label in labels:
print(f"Label: {label.name} (ID: {label.id})")
# Get project annotations
annotations = project.get_annotations()
print(f"Total shapes: {len(annotations.shapes)}")
print(f"Total tags: {len(annotations.tags)}")
# Get project preview
preview = project.get_preview()
from PIL import Image
im = Image.open(preview)
im.show()
Exporting Project Dataset
# Export in various formats
project.export_dataset(
format_name="COCO 1.0",
filename="project_export.zip"
)
# Export with custom save image parameter
project.export_dataset(
format_name="YOLO 1.1",
filename="yolo_export.zip",
save_images=True
)
Importing Dataset to Project
project.import_dataset(
format_name="COCO 1.0",
filename="dataset.zip",
conv_mask_to_poly=True # Convert masks to polygons
)
Project Backup and Restore
# Download project backup
project.download_backup("project_backup.zip")
# Restore project from backup
restored_project = client.projects.create_from_backup(
filename="project_backup.zip"
)
Deleting Projects
# Delete a single project
project.remove()
# Delete multiple projects by ID
client.projects.remove_by_ids([123, 456, 789])
Tasks
Tasks contain the actual data (images/videos) to be annotated.Creating Tasks
from cvat_sdk.core.proxies.tasks import ResourceType
# Define task specification
task_spec = models.TaskWriteRequest(
name="Street Images - Batch 1",
project_id=project.id, # Optional: link to project
# If not in project, define labels here:
# labels=[...]
)
# Create task with local files
task = client.tasks.create_from_data(
spec=task_spec,
resources=["img1.jpg", "img2.jpg", "img3.jpg"],
resource_type=ResourceType.LOCAL,
data_params={
"image_quality": 95,
"chunk_size": 100,
"sorting_method": "lexicographical"
}
)
print(f"Created task {task.id}: {task.name}")
Resource Types
Tasks support three resource types:from cvat_sdk.core.proxies.tasks import ResourceType
# Local files from your machine
task = client.tasks.create_from_data(
spec=task_spec,
resources=["path/to/images/img1.jpg", "path/to/images/img2.jpg"],
resource_type=ResourceType.LOCAL
)
# Remote files (URLs)
task = client.tasks.create_from_data(
spec=task_spec,
resources=[
"https://example.com/image1.jpg",
"https://example.com/image2.jpg"
],
resource_type=ResourceType.REMOTE
)
# Server share files
task = client.tasks.create_from_data(
spec=task_spec,
resources=[
"share/dataset1/img1.jpg",
"share/dataset1/img2.jpg"
],
resource_type=ResourceType.SHARE
)
Listing Tasks
# List all tasks
tasks = client.tasks.list()
# Filter tasks by project
project_tasks = [t for t in tasks if t.project_id == project.id]
for task in tasks:
print(f"Task {task.id}: {task.name}")
print(f" Size: {task.size} frames")
print(f" Status: {task.status}")
print(f" Mode: {task.mode}")
Retrieving a Task
task = client.tasks.retrieve(task_id=456)
print(f"Name: {task.name}")
print(f"Project ID: {task.project_id}")
print(f"Size: {task.size}")
print(f"Mode: {task.mode}")
print(f"Owner: {task.owner.username}")
Updating Tasks
# Update task properties
task.update(models.PatchedTaskWriteRequest(
name="Updated Task Name",
subset="train" # Set dataset subset
))
# Fetch latest data
task.fetch()
Adding Data to Existing Tasks
# Upload additional images
task.upload_data(
resources=["new_img1.jpg", "new_img2.jpg"],
resource_type=ResourceType.LOCAL,
params={
"image_quality": 90,
"sorting_method": "natural"
},
wait_for_completion=True
)
Working with Task Frames
# Get task metadata
meta = task.get_meta()
print(f"Total frames: {len(meta.frames)}")
print(f"Image quality: {meta.image_quality}")
# Get frame information
frames_info = task.get_frames_info()
for frame in frames_info[:5]: # First 5 frames
print(f"Frame {frame.frame}: {frame.name} ({frame.width}x{frame.height})")
# Get a specific frame
frame_bytes = task.get_frame(frame_id=0, quality="original")
from PIL import Image
img = Image.open(frame_bytes)
img.show()
# Get task preview
preview_bytes = task.get_preview()
preview = Image.open(preview_bytes)
preview.show()
# Download multiple frames
task.download_frames(
frame_ids=[0, 1, 2, 3, 4],
outdir="downloaded_frames",
quality="original",
filename_pattern="frame_{frame_id:06d}{frame_ext}"
)
# Download a chunk
with open("chunk_0.zip", "wb") as f:
task.download_chunk(chunk_id=0, output_file=f, quality="compressed")
Removing Frames
# Remove specific frames by ID
task.remove_frames_by_ids([5, 10, 15])
Working with Task Jobs
# Get all jobs in a task
jobs = task.get_jobs()
for job in jobs:
print(f"Job {job.id}")
print(f" Status: {job.status}")
print(f" Stage: {job.stage}")
print(f" Start frame: {job.start_frame}")
print(f" Stop frame: {job.stop_frame}")
print(f" Assignee: {job.assignee.username if job.assignee else 'Unassigned'}")
Working with Task Labels
# Get task labels
labels = task.get_labels()
for label in labels:
print(f"Label: {label.name} (ID: {label.id})")
print(f" Type: {label.type}")
print(f" Color: {label.color}")
if label.attributes:
print(f" Attributes: {[a.name for a in label.attributes]}")
Task Annotations
# Get annotations
annotations = task.get_annotations()
print(f"Shapes: {len(annotations.shapes)}")
print(f"Tags: {len(annotations.tags)}")
print(f"Tracks: {len(annotations.tracks)}")
# Set (replace all) annotations
new_annotations = models.LabeledDataRequest(
shapes=[
models.LabeledShapeRequest(
type="rectangle",
frame=0,
label_id=labels[0].id,
points=[100.0, 100.0, 200.0, 200.0],
attributes=[]
)
],
tags=[],
tracks=[]
)
task.set_annotations(new_annotations)
# Update (add/modify/delete) annotations
from cvat_sdk.core.proxies.annotations import AnnotationUpdateAction
# Add new shapes
task.update_annotations(
models.PatchedLabeledDataRequest(
shapes=[
models.LabeledShapeRequest(
type="polygon",
frame=1,
label_id=labels[0].id,
points=[10.0, 10.0, 20.0, 10.0, 20.0, 20.0, 10.0, 20.0],
attributes=[]
)
]
),
action=AnnotationUpdateAction.CREATE
)
# Update existing annotations
task.update_annotations(
models.PatchedLabeledDataRequest(
shapes=[
models.LabeledShapeRequest(
id=12345, # Existing shape ID
type="rectangle",
frame=0,
label_id=labels[0].id,
points=[150.0, 150.0, 250.0, 250.0],
attributes=[]
)
]
),
action=AnnotationUpdateAction.UPDATE
)
# Delete specific annotations
task.remove_annotations(ids=[12345, 67890])
# Delete all annotations
task.remove_annotations()
Importing Annotations
# Import annotations from file
task.import_annotations(
format_name="YOLO 1.1",
filename="annotations.zip"
)
# With mask to polygon conversion
task.import_annotations(
format_name="COCO 1.0",
filename="coco_annotations.json",
conv_mask_to_poly=True
)
Exporting Task Dataset
# Export annotations and data
task.export_dataset(
format_name="CVAT for images 1.1",
filename="task_export.zip"
)
# Export only annotations
task.export_dataset(
format_name="COCO 1.0",
filename="coco_export.json",
save_images=False
)
Task Backup and Restore
# Download task backup
task.download_backup("task_backup.zip")
# Create task from backup
restored_task = client.tasks.create_from_backup(
filename="task_backup.zip"
)
Deleting Tasks
# Delete single task
task.remove()
# Delete multiple tasks
client.tasks.remove_by_ids([123, 456, 789])
Jobs
Jobs are subdivisions of tasks assigned to annotators.Listing Jobs
# List all jobs
jobs = client.jobs.list()
# Get jobs for a specific task
task_jobs = task.get_jobs()
for job in jobs:
print(f"Job {job.id}")
print(f" Task: {job.task_id}")
print(f" Status: {job.status}")
print(f" Stage: {job.stage}")
print(f" Assignee: {job.assignee.username if job.assignee else 'None'}")
Retrieving a Job
job = client.jobs.retrieve(job_id=789)
print(f"Job {job.id}")
print(f"Task ID: {job.task_id}")
print(f"Frame range: {job.start_frame} - {job.stop_frame}")
print(f"Status: {job.status}")
print(f"Stage: {job.stage}")
Updating Jobs
# Update job properties
job.update(models.PatchedJobWriteRequest(
status="completed",
stage="acceptance",
assignee=user_id
))
job.fetch()
Working with Job Frames
# Get job metadata
meta = job.get_meta()
frames_info = job.get_frames_info()
# Get specific frame
frame_bytes = job.get_frame(frame_id=job.start_frame)
# Download frames
job.download_frames(
frame_ids=list(range(job.start_frame, job.stop_frame + 1)),
outdir="job_frames"
)
# Remove frames
job.remove_frames_by_ids([10, 20])
Job Annotations
# Get job annotations
annotations = job.get_annotations()
# Set annotations
job.set_annotations(new_annotations)
# Update annotations
job.update_annotations(partial_annotations)
# Import annotations
job.import_annotations(
format_name="COCO 1.0",
filename="job_annotations.json"
)
# Export job dataset
job.export_dataset(
format_name="YOLO 1.1",
filename="job_export.zip"
)
Job Issues
# Get issues for a job
issues = job.get_issues()
for issue in issues:
print(f"Issue {issue.id}: {issue.message}")
print(f" Frame: {issue.frame}")
print(f" Position: {issue.position}")
print(f" Resolved: {issue.resolved}")
Job Labels
# Get labels available in the job
labels = job.get_labels()
for label in labels:
print(f"Label: {label.name} (ID: {label.id})")
Progress Reporting
Many operations support progress reporting withtqdm:
from tqdm import tqdm
from cvat_sdk.core.progress import ProgressReporter
# Create task with progress bar
with tqdm(desc="Uploading images", unit="bytes") as pbar:
task = client.tasks.create_from_data(
spec=task_spec,
resources=image_files,
pbar=pbar
)
# Import annotations with progress
with tqdm(desc="Importing annotations") as pbar:
task.import_annotations(
format_name="COCO 1.0",
filename="annotations.json",
pbar=pbar
)
Next Steps
- PyTorch Adapter - Use CVAT tasks for training PyTorch models
- Auto-Annotation - Automate annotation using models