Official Python SDK for Pictograph Context Engine - Computer Vision Annotation Platform
Project description
Pictograph Python SDK
Official Python SDK for Pictograph Context Engine - a powerful computer vision annotation platform for creating high-quality training datasets.
Features
- Simple, intuitive API - Get started with just a few lines of code
- Dataset management - List, download, and manage annotation datasets
- Image operations - Upload images, retrieve metadata, and manage assets
- Annotation tools - Get, save, and delete annotations in Pictograph JSON format
- Batch operations - Download entire datasets with parallel processing
- Automatic retries - Built-in retry logic for transient failures
- Rate limiting - Automatic handling of API rate limits
- Type hints - Full type annotations for better IDE support
Installation
pip install pictograph
Quick Start
from pictograph import Client
# Initialize the client with your API key
client = Client(api_key="pk_live_your_key_here")
# List all datasets
datasets = client.datasets.list()
for dataset in datasets:
print(f"{dataset['name']}: {dataset['image_count']} images")
# Download a complete dataset
client.datasets.download(
"dataset-uuid",
output_dir="./my_dataset",
mode="full" # Download images + annotations
)
# Upload an image
result = client.images.upload(
"dataset-uuid",
"/path/to/image.jpg",
folder_path="/train/images"
)
print(f"Uploaded: {result['image_id']}")
# Get annotations for an image
annotations = client.annotations.get("image-uuid")
for ann in annotations:
print(f"{ann['class']}: {ann['type']}")
# Save annotations
client.annotations.save("image-uuid", [
{
"id": "ann-1",
"class": "person",
"type": "bbox",
"bbox": [100, 200, 50, 80], # [x, y, width, height]
"confidence": 1.0
}
])
Authentication
Get your API key from the Pictograph dashboard.
from pictograph import Client
client = Client(api_key="pk_live_your_key_here")
You can also configure the base URL and timeout:
client = Client(
api_key="pk_live_your_key_here",
base_url="https://your-instance.pictograph.cloud",
timeout=60,
max_retries=5
)
Usage
Working with Datasets
List Datasets
# List all datasets
datasets = client.datasets.list()
# With pagination
datasets = client.datasets.list(limit=50, offset=0)
Get Dataset Details
# Get basic info
dataset = client.datasets.get("dataset-uuid")
print(dataset['name'], dataset['image_count'])
# Get with images included
dataset = client.datasets.get(
"dataset-uuid",
include_images=True,
images_limit=1000
)
for img in dataset['images']:
print(img['filename'], img['image_url'])
List Images in Dataset
# List all images
images = client.datasets.list_images("dataset-uuid")
# Filter by annotation status
completed_images = client.datasets.list_images(
"dataset-uuid",
status="complete",
limit=500
)
Download Dataset
# Download everything (images + annotations)
result = client.datasets.download(
"dataset-uuid",
output_dir="./dataset",
mode="full",
max_workers=20, # Parallel downloads
show_progress=True
)
print(f"Downloaded {result['images_downloaded']} images")
# Download only annotations
result = client.datasets.download(
"dataset-uuid",
output_dir="./annotations",
mode="annotations_only"
)
# Download only completed images
result = client.datasets.download(
"dataset-uuid",
output_dir="./completed",
mode="full",
status_filter="complete"
)
Working with Images
Get Image Metadata
image = client.images.get("image-uuid")
print(image['filename'])
print(image['image_url']) # CDN URL for viewing
print(image['annotation_count'])
Upload Image
# Simple upload
result = client.images.upload(
"dataset-uuid",
"/path/to/image.jpg"
)
# Upload to specific folder
result = client.images.upload(
"dataset-uuid",
"/path/to/image.jpg",
folder_path="/train/images",
filename="custom_name.jpg"
)
print(result['image_id'])
Delete Image
# Archive (soft delete)
client.images.delete("image-uuid")
# Permanent delete
client.images.delete("image-uuid", permanent=True)
Working with Annotations
Pictograph uses a JSON format that supports multiple annotation types:
- bbox - Bounding boxes
[x, y, width, height] - polygon - Polygons
[[x1, y1], [x2, y2], ...] - polyline - Polylines
[[x1, y1], [x2, y2], ...] - keypoint - Single points
[x, y]
Get Annotations
annotations = client.annotations.get("image-uuid")
for ann in annotations:
print(ann['id'], ann['class'], ann['type'])
if ann['type'] == 'bbox':
x, y, width, height = ann['bbox']
print(f" Bbox: ({x}, {y}) - {width}x{height}")
Save Annotations
# Bounding box
annotations = [
{
"id": "ann-1",
"class": "person",
"type": "bbox",
"bbox": [100, 200, 50, 80],
"confidence": 1.0
}
]
result = client.annotations.save("image-uuid", annotations)
print(result['new_count'])
# Polygon
annotations = [
{
"id": "ann-2",
"class": "car",
"type": "polygon",
"polygon": [[10, 20], [30, 40], [50, 60], [10, 20]],
"confidence": 1.0
}
]
client.annotations.save("image-uuid", annotations)
# Multiple annotations
annotations = [
{"id": "ann-1", "class": "person", "type": "bbox", "bbox": [100, 200, 50, 80]},
{"id": "ann-2", "class": "car", "type": "polygon", "polygon": [[10,20], [30,40], [50,60], [10,20]]},
{"id": "ann-3", "class": "road", "type": "polyline", "polyline": [[0,100], [50,100], [100,100]]},
{"id": "ann-4", "class": "landmark", "type": "keypoint", "keypoint": [150, 200]}
]
client.annotations.save("image-uuid", annotations)
Helper Methods
# Create properly formatted annotations
bbox = client.annotations.create_bbox(
"ann-1",
"person",
[100, 200, 50, 80],
confidence=0.95
)
polygon = client.annotations.create_polygon(
"ann-2",
"car",
[[10, 20], [30, 40], [50, 60], [10, 20]]
)
polyline = client.annotations.create_polyline(
"ann-3",
"road",
[[0, 100], [50, 100], [100, 100]]
)
keypoint = client.annotations.create_keypoint(
"ann-4",
"landmark",
[150, 200]
)
# Save them all
client.annotations.save("image-uuid", [bbox, polygon, polyline, keypoint])
Delete Annotations
# Delete all annotations for an image
result = client.annotations.delete("image-uuid")
print(result['deleted_count'])
Context Manager
Use the client as a context manager to ensure proper cleanup:
with Client(api_key="pk_live_your_key_here") as client:
datasets = client.datasets.list()
# Client session automatically closed when done
Error Handling
The SDK raises specific exceptions for different error types:
from pictograph import Client, AuthenticationError, RateLimitError, NotFoundError
client = Client(api_key="pk_live_your_key_here")
try:
dataset = client.datasets.get("invalid-uuid")
except AuthenticationError:
print("Invalid API key")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
except NotFoundError:
print("Dataset not found")
except Exception as e:
print(f"Unexpected error: {e}")
Advanced Usage
Batch Processing
from concurrent.futures import ThreadPoolExecutor
# Upload multiple images in parallel
def upload_image(image_path):
return client.images.upload("dataset-uuid", image_path)
image_paths = ["img1.jpg", "img2.jpg", "img3.jpg"]
with ThreadPoolExecutor(max_workers=10) as executor:
results = list(executor.map(upload_image, image_paths))
print(f"Uploaded {len(results)} images")
Custom Metadata
# Add custom metadata to annotations
annotation = client.annotations.create_bbox(
"ann-1",
"person",
[100, 200, 50, 80],
metadata={
"annotator": "john@example.com",
"difficulty": "easy",
"verified": True
}
)
client.annotations.save("image-uuid", [annotation])
Rate Limits
The SDK automatically handles rate limits:
- Free tier: 1,000 requests/hour
- Starter tier: 5,000 requests/hour
- Pro tier: 20,000 requests/hour
- Enterprise tier: 100,000 requests/hour
If you hit a rate limit, the SDK will automatically wait and retry (if retry time < 2 minutes).
Requirements
- Python 3.8+
- requests >= 2.31.0
- Pillow >= 10.0.0
- tqdm >= 4.65.0
Support
- Documentation: https://pictograph.cloud/docs
- Email: support@pictograph.cloud
- Issues: https://github.com/pictograph-labs/pictograph-sdk/issues
License
MIT License - see LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pictograph-0.1.1.tar.gz.
File metadata
- Download URL: pictograph-0.1.1.tar.gz
- Upload date:
- Size: 16.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d07556a3b6627bbc87307dde803fcc0f7f906bdec692a61af736b980dcba85ac
|
|
| MD5 |
9c096748b7f4d7b1f4e484fce1c8b003
|
|
| BLAKE2b-256 |
730f38a457fa92d2d4e9f02e0dbc33fe27a70da9b40a0793bcf5c4ed339eb5de
|
File details
Details for the file pictograph-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pictograph-0.1.1-py3-none-any.whl
- Upload date:
- Size: 15.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac496540b068eb049fd72a28f99453abbf736b47d531b19e0576d3d4d77cd5f4
|
|
| MD5 |
89f9478ba9565311a8b868457382112d
|
|
| BLAKE2b-256 |
f3903c795b3ff08047bac1e7ad76f7fc9632ba0a406762ecb46d9eee3a5fb682
|