Thibaut's picture
Add complete metrics evaluation subproject structure
b7d2408
# CVAT API Usage Guide
Complete guide for working with CVAT tasks, jobs, and annotations.
## Table of Contents
- [Installation](#installation)
- [Initialization](#initialization)
- [Common Workflows](#common-workflows)
- [Download and Update Job Annotations](#download-and-update-job-annotations)
- [Download and Update Task Annotations](#download-and-update-task-annotations)
- [Update Job Metadata](#update-job-metadata)
- [Update Task Metadata](#update-task-metadata)
- [Complete Examples](#complete-examples)
## Installation
```bash
pip install -r requirements.txt
```
## Initialization
```python
from cvat_api import CvatApiClient
from pathlib import Path
# Initialize client
client = CvatApiClient(
cvat_host="https://app.cvat.ai",
cvat_username="your_username",
cvat_password="your_password",
cvat_organization="your_organization"
)
```
## Common Workflows
### Download and Update Job Annotations
Complete workflow for downloading annotations, modifying them, and uploading back:
```python
# 1. Download annotations
job_id = 2355063
annotations = client.annotations.get_job_annotations(job_id)
# 2. Modify annotations
# Add a new shape
from shared.schema.cvat import CvatApiShape
new_shape = CvatApiShape(
id=0, # Will be assigned by server
type="rectangle",
frame=0,
label_id=1,
points=[100.0, 100.0, 200.0, 200.0],
occluded=False,
z_order=0,
source="manual",
attributes=[]
)
annotations.shapes.append(new_shape)
# Or modify existing shapes
for shape in annotations.shapes:
if shape.label_id == 5:
shape.occluded = True # Mark as occluded
# 3. Upload modified annotations
updated_annotations = client.annotations.put_job_annotations(
job_id=job_id,
annotations=annotations
)
print(f"✅ Updated {len(updated_annotations.shapes)} shapes")
```
### Download and Update Task Annotations
Same workflow but at task level:
```python
# 1. Download task annotations
task_id = 1322143
annotations = client.annotations.get_task_annotations(task_id)
# 2. Modify annotations (same as above)
# ... make your changes ...
# 3. Upload modified annotations
updated_annotations = client.annotations.put_task_annotations(
task_id=task_id,
annotations=annotations
)
```
### Update Job Metadata
Update job status, assignee, stage, etc.:
```python
# 1. Get current job details
job_id = 2355063
job_details = client.jobs.get_job_details(job_id)
# 2. Modify job metadata
job_details.state = "completed" # Change state
job_details.stage = "acceptance" # Change stage
# 3. Update job
updated_job = client.jobs.update_job(
job_id=job_id,
job_data=job_details
)
print(f"✅ Job {job_id} updated: {updated_job.state} / {updated_job.stage}")
```
### Update Task Metadata
Update task name, assignee, labels, etc.:
```python
# 1. Get current task details
task_id = 1322143
task_details = client.tasks.get_task_details(task_id)
# 2. Modify task metadata
task_details.name = "Updated Task Name"
# Note: Use model_dump(exclude_unset=True) in update method to only send changed fields
# 3. Update task
updated_task = client.tasks.update_task(
task_id=task_id,
task_data=task_details
)
print(f"✅ Task {task_id} updated: {updated_task.name}")
```
## Complete Examples
### Example 1: Batch Process Job Annotations
Process annotations for all jobs in a task:
```python
from cvat_api import CvatApiClient
# Initialize
client = CvatApiClient(...)
# Get all jobs in task
task_id = 1322143
job_ids = client.tasks.get_task_job_ids(task_id)
# Process each job
for job_id in job_ids:
# Download annotations
annotations = client.annotations.get_job_annotations(job_id)
# Apply your modifications
for shape in annotations.shapes:
if shape.label_id == 5: # Example: filter by label
# Modify shape properties
shape.occluded = True
# Upload modified annotations
client.annotations.put_job_annotations(job_id, annotations)
print(f"✅ Processed job {job_id}")
```
### Example 2: Download All Images and Annotations
Download complete dataset from a task:
```python
from pathlib import Path
task_id = 1322143
output_dir = Path("./output")
# 1. Download all images
images = client.downloads.download_task_images(
task_id=task_id,
output_dir=output_dir / "images"
)
print(f"Downloaded {len(images)} images")
# 2. Download annotations
annotations = client.annotations.get_task_annotations(task_id)
# 3. Save annotations to file
import json
output_file = output_dir / "annotations.json"
output_file.write_text(annotations.model_dump_json(indent=2))
print(f"Saved annotations to {output_file}")
```
### Example 3: Quality Control Workflow
Implement a QC workflow that marks reviewed jobs:
```python
from shared.schema.cvat import CvatApiJobsListRequest
# List all jobs in "annotation" stage
request = CvatApiJobsListRequest(
task_id=1322143,
stage="annotation",
state="completed"
)
response = client.jobs.list_jobs(request)
for job in response.results:
# Download and review annotations
annotations = client.annotations.get_job_annotations(job.id)
# Run your QC checks
issues_found = run_quality_checks(annotations)
# Update job based on QC results
job_details = client.jobs.get_job_details(job.id)
if not issues_found:
job_details.stage = "acceptance"
job_details.state = "completed"
else:
job_details.state = "rejected"
client.jobs.update_job(job.id, job_details)
print(f"✅ QC processed job {job.id}")
```
### Example 4: Export Annotations with Metadata
Export complete annotation dataset with metadata:
```python
# Get project details
project_id = 239220
project = client.projects.get_project_details(project_id)
labels = client.projects.get_project_labels(project_id)
# Get all tasks
task_ids = client.projects.get_project_tasks(project_id)
# Build export structure
export_data = {
"project": project.model_dump(),
"labels": [label.model_dump() for label in labels],
"tasks": []
}
# Export each task
for task_id in task_ids:
task_details = client.tasks.get_task_details(task_id)
annotations = client.annotations.get_task_annotations(task_id)
export_data["tasks"].append({
"task": task_details.model_dump(),
"annotations": annotations.model_dump()
})
# Save export
import json
Path("export.json").write_text(json.dumps(export_data, indent=2))
print(f"✅ Exported {len(task_ids)} tasks")
```
## Tips and Best Practices
### 1. Use Partial Updates
When updating jobs or tasks, use only the fields you want to change:
```python
# Good - only update specific fields
job_details = client.jobs.get_job_details(job_id)
job_details.state = "completed"
client.jobs.update_job(job_id, job_details)
```
### 2. Handle Errors
Always handle potential errors:
```python
try:
annotations = client.annotations.get_job_annotations(job_id)
except requests.HTTPError as e:
print(f"Failed to get annotations: {e}")
# Handle error appropriately
```
### 3. Batch Operations
For multiple jobs/tasks, use batch operations:
```python
job_ids = client.tasks.get_task_job_ids(task_id)
for job_id in job_ids:
try:
# Process each job
process_job(client, job_id)
except Exception as e:
print(f"Error processing job {job_id}: {e}")
continue # Continue with next job
```
### 4. Validate Before Upload
Validate annotations before uploading:
```python
annotations = client.annotations.get_job_annotations(job_id)
# Validate
for shape in annotations.shapes:
assert shape.label_id in valid_label_ids
assert len(shape.points) >= 4 # For rectangles
# Upload after validation
client.annotations.put_job_annotations(job_id, annotations)
```
## Error Handling
The client includes automatic retry logic for transient errors (500/502/503/504):
```python
# This will automatically retry up to 10 times for server errors
annotations = client.annotations.get_job_annotations(job_id)
```
For custom error handling:
```python
import requests
from requests.exceptions import Timeout, ConnectionError
try:
annotations = client.annotations.get_job_annotations(job_id)
except Timeout:
print("Request timed out")
except ConnectionError:
print("Connection failed")
except requests.HTTPError as e:
if e.response.status_code == 404:
print("Job not found")
elif e.response.status_code == 403:
print("Access denied")
else:
print(f"HTTP error: {e}")
```
## See Also
- [API Documentation](./client.py) - Complete API reference
- [Test Suite](../tests/test_cvat_api/) - Usage examples in tests
- [CVAT API Docs](https://app.cvat.ai/api/docs/) - Official CVAT API documentation