🎨 Image Annotations - Your Visual Data Toolkit!
Welcome to the world of image annotations! Whether you're training an AI model, analyzing medical images, or cataloging your photo collection, annotations are your tools for marking, labeling, and understanding visual data. Let's dive into the exciting possibilities!
📋 Classification - Simple Yet Powerful
Single Item Classification
Need to label an entire image? Here's how to add a simple classification:
# Get item from the platform
item = dataset.items.get(filepath='/your-image-file-path.jpg')
# Create a builder instance
builder = item.annotations.builder()
# Add classification label
builder.add(annotation_definition=dl.Classification(label=label))
# Save to platform
item.annotations.upload(builder)
Batch Classification
Got multiple images to classify? Let's do it efficiently:
# Create a filter for batch processing
filters = dl.Filters()
# Add filter - only files
filters.add(field='type', values='file')
# Get filtered items
pages = dataset.items.list(filters=filters)
# Process each item
for page in pages:
for item in page:
builder = item.annotations.builder()
builder.add(annotation_definition=dl.Classification(label='your-label'))
item.annotations.upload(builder)
📍 Points & Poses - Precision Marking
Point Annotations
Perfect for marking specific locations in your image:
# Get your canvas ready
item = dataset.items.get(filepath='/your-image-file-path.jpg')
builder = item.annotations.builder()
# Add a point with attributes
builder.add(annotation_definition=dl.Point(x=100,
y=100,
label='my-label',
attributes={'color': 'red'}))
# Save your work
item.annotations.upload(builder)
Pose Annotations - Digital Skeletons
Create pose templates for tracking key points on subjects:
# Get your pose template ID
template_id = recipe.get_annotation_template_id(template_name="my_template_name")
# Create the parent pose annotation
parent_annotation = item.annotations.upload(
dl.Annotation.new(annotation_definition=dl.Pose(
label='my_parent_label',
template_id=template_id,
instance_id=None # Optional for tracking specific instances
))
)[0]
# Add the skeleton points
builder = item.annotations.builder()
builder.add(annotation_definition=dl.Point(x=x,
y=y,
label='my_point_label'),
parent_id=parent_annotation.id)
builder.upload()
📦 Boxes & Cuboids - Defining Regions
Bounding Box
The classic way to mark regions of interest:
# Create a simple box
builder.add(annotation_definition=dl.Box(top=10,
left=10,
bottom=100,
right=100,
label='my-label'))
3D Cuboid
Working in 3D? Choose your preferred method:
# Method 1: Using front and back rectangles
builder.add(annotation_definition=dl.Cube.from_boxes_and_angle(
label="label",
front_top=100,
front_left=100,
front_right=300,
front_bottom=300,
back_top=200,
back_left=200,
back_right=400,
back_bottom=400,
angle=0
))
# Method 2: Using 8 corner points
builder.add(annotation_definition=dl.Cube(
label="label",
front_tl=[200, 200], # Front top left
front_tr=[500, 250], # Front top right
front_br=[500, 550], # Front bottom right
front_bl=[200, 500], # Front bottom left
back_tl=[300, 300], # Back top left
back_tr=[600, 350], # Back top right
back_br=[600, 650], # Back bottom right
back_bl=[300, 600] # Back bottom left
))
🔷 Advanced Shapes - Creative Freedom
Ellipse Annotations
Perfect for circular or oval regions:
builder.add(annotation_definition=dl.Ellipse(
x=center_x,
y=center_y,
rx=radius_x,
ry=radius_y,
angle=rotation_angle,
label=label
))
Polygons & Polylines
For when predefined shapes won't cut it:
# Create a polygon
builder.add(annotation_definition=dl.Polygon(
geo=[[100, 50], [80, 120], [110, 130]],
label='my-label'
))
# Create a polyline
builder.add(annotation_definition=dl.Polyline(
geo=[[100, 50], [80, 120], [110, 130]],
label='my-label'
))
🎭 Segmentation - Pixel-Perfect Precision
Basic Segmentation
Create a binary mask for your annotations:
# Create a mask
mask = np.zeros(shape=(item.height, item.width), dtype=np.uint8)
mask[50:100, 200:250] = 1 # Mark region of interest
# Add segmentation annotation
builder.add(annotation_definition=dl.Segmentation(
geo=mask,
label='my-label'
))
Converting Between Formats
Mask to Polygon
# Convert segmentation to polygon
builder.add(dl.Polygon.from_segmentation(
mask=mask_annotation.geo,
label=mask_annotation.label,
max_instances=None
))
Polygon to Mask
# Convert polygon to segmentation
builder.add(dl.Segmentation.from_polygon(
geo=polygon_annotation.geo,
label=annotation.label,
shape=img.size[::-1] # (height, width)
))
Segmentation from Instance Mask
Create segmentation from instance masks:
# Create random instance mask
mask = np.random.randint(low=0, high=2, size=(item.height, item.width))
instance_map = {"background": 0, "foreground": 1}
# Convert to segmentation annotations
builder.from_instance_mask(mask=mask, instance_map=instance_map)
📝 Metadata & Description
Item Description
Add context to your images:
# Add or update item description
item.set_description(text="Detailed description of the image")
Working with Attributes
Enrich your annotations with metadata:
builder.add(annotation_definition=dl.Box(...),
attributes={
'confidence': 0.95,
'category': 'vehicle',
'condition': 'new'
})
🚀 Advanced Tutorials
Copying Annotations Between Items
Want to reuse annotations across different images? Here's how to copy them between items:
# Set the source item with the annotations we want to copy
project = dl.projects.get(project_name='second-project_name')
dataset = project.datasets.get(dataset_name='second-dataset_name')
item = dataset.items.get(item_id='first-id-number')
annotations = item.annotations.list()
# Set the target item where we want to copy to
item = dataset.items.get(item_id='second-id-number')
item.annotations.upload(annotations=annotations)
# Want to copy to multiple items? Use filters!
filters = dl.Filters()
filters.add(field='filename', values='/fighting/**') # Get files from directory (recursive)
filters.add(field='type', values='file') # Only files
pages = dataset.items.list(filters=filters)
# Copy annotations to all filtered items
for page in pages:
for item in page:
item.annotations.upload(annotations=annotations)
Visualizing Images & Annotations
Want to see your annotations? Here's how to visualize them:
from PIL import Image
# Get your item
item = dataset.items.get(item_id='write-your-id-number')
# Download and open the image
buffer = item.download(save_locally=False)
image = Image.open(buffer)
# Get annotations as an image overlay
annotations = item.annotations.show(
width=image.size[0],
height=image.size[1],
thickness=3
)
annotations = Image.fromarray(annotations.astype(np.uint8))
# View annotations and image separately
annotations.show()
image.show()
# Or view them combined!
image.paste(annotations, (0, 0), annotations)
image.show()
Working with JSON Annotations
Need to load annotations from a JSON file? We've got you covered:
from PIL import Image
import json
# Read annotations from JSON
with open(r'C:/home/project/images/annotation.json', 'r') as f:
data = json.load(f)
# Display each annotation
for annotation in data['annotations']:
annotations = dl.Annotation.from_json(annotation)
mask = annotations.show(
width=640,
height=480,
thickness=3,
color=(255, 0, 0)
)
mask = Image.fromarray(mask.astype(np.uint8))
mask.show()
Counting Annotations
Need to know how many annotations you have? Here's a quick way:
# Create annotation filters
filters = dl.Filters(resource=dl.FiltersResource.ANNOTATION)
filters.page_size = 0
# Get the total count
annotations_count = dataset.annotations.list(filters=filters).items_count
Working with Parent-Child Relationships
Create hierarchical relationships between annotations:
Creating Parent-Child While Uploading
# Create parent box
builder = item.annotations.builder()
builder.add(annotation_definition=dl.Box(
top=10, left=10, bottom=100, right=100,
label='my-parent-label'
))
# Upload parent and get its ID
annotations = item.annotations.upload(annotations=builder)
# Create child box linked to parent
builder = item.annotations.builder()
builder.add(
annotation_definition=dl.Box(
top=10, left=10, bottom=100, right=100,
label='my-child-label'
),
parent_id=annotations[0].id
)
# Upload the complete family
item.annotations.upload(annotations=builder)
Linking Existing Annotations
# Create and upload parent
builder = item.annotations.builder()
builder.add(annotation_definition=dl.Box(
top=10, left=10, bottom=100, right=100,
label='my-parent-label'
))
parent_annotation = item.annotations.upload(annotations=builder)[0]
# Create and upload child
builder = item.annotations.builder()
builder.add(annotation_definition=dl.Box(
top=10, left=10, bottom=100, right=100,
label='my-child-label'
))
child_annotation = item.annotations.upload(annotations=builder)[0]
# Link child to parent
child_annotation.parent_id = parent_annotation.id
child_annotation.update(system_metadata=True)
Bulk Label Updates
Need to change labels across multiple annotations? Here's how:
# Create a new label (optional)
dataset.add_label(label_name='newLabel', color=(2, 43, 123))
# Find all annotations with the old label
filters = dl.Filters()
filters.resource = dl.FiltersResource.ANNOTATION
filters.add(field='label', values='oldLabel')
pages = dataset.annotations.list(filters=filters)
# Update each annotation's label
for annotation in pages.all():
annotation.label = 'newLabel'
annotation.update()
💡 Pro Tips & Best Practices
Annotation Quality
- Double-check coordinates and dimensions
- Use consistent labeling schemes
- Verify segmentation masks match image dimensions
- Keep attributes consistent across similar annotations
Performance Optimization
- Use batch operations for multiple items
- Convert between formats efficiently
- Consider memory usage with large masks
- Cache frequently used templates
Workflow Tips
- Create templates for common annotation patterns
- Use filters for batch operations
- Implement quality control checks
- Document your annotation guidelines
🔧 Troubleshooting Common Issues
Coordinate Systems
- Remember: (0,0) is top-left corner
- Verify coordinate ranges match image dimensions
- Check angle calculations for rotated shapes
- Validate polygon point sequences
Data Validation
- Verify mask dimensions match image size
- Check for closed polygons
- Validate attribute formats
- Test annotation visibility
Need help? Check out our other tutorials or reach out to our support team. Happy annotating! 🎨✨