Documentation
Color Analysis
Extract dominant colors and search images by color properties
Automatic on Upload
Color extraction runs automatically whenever you upload images — no extra call needed. Use client.colors.get() to retrieve colors after upload. The extract() method is only needed to re-run extraction with different settings (e.g., fewer colors or force refresh).
Get Image Colors
Retrieve colors from an uploaded image
async with AionVision(api_key="aion_...") as client: # Upload an image (colors extracted automatically) upload = await client.upload_one("furniture.jpg")
# Get the extracted colors result = await client.colors.get(upload.image_id)
if result.is_completed: for color in result.color_analysis.dominant_colors: print(f"{color.name}: {color.hex} ({color.percentage:.1f}%)") print(f" Family: {color.family}") print(f" RGB: ({color.rgb.r}, {color.rgb.g}, {color.rgb.b})")Re-extraction (Optional)
Colors are extracted automatically on upload with up to 16 colors. Use extract() only if you need to re-run with different settings.
# Re-extract with fewer colors (3-16 range)result = await client.colors.extract( image_id, n_colors=6)
# Force re-extraction even if colors already existresult = await client.colors.extract( image_id, force=True, n_colors=8)Color Analysis Structure
Understanding the color analysis response
result = await client.colors.get(image_id)
if result.is_completed: analysis = result.color_analysis
# Dominant colors (ordered by percentage) for color in analysis.dominant_colors: print(f"{color.rank}. {color.name} ({color.hex})") print(f" Coverage: {color.percentage:.1f}%") print(f" Family: {color.family}")
# Multiple color spaces available print(f" RGB: ({color.rgb.r}, {color.rgb.g}, {color.rgb.b})") print(f" HSL: ({color.hsl.h:.0f}, {color.hsl.s:.0f}%, {color.hsl.l:.0f}%)") print(f" LAB: ({color.lab.l:.1f}, {color.lab.a:.1f}, {color.lab.b:.1f})")
# Overall analytics temp = analysis.analytics.temperature print(f"Temperature: {temp.value} (score: {temp.score:.2f})")
brightness = analysis.analytics.brightness print(f"Brightness: {brightness.category} (avg: {brightness.average:.0f})")
saturation = analysis.analytics.saturation print(f"Saturation: {saturation.category} (avg: {saturation.average:.0f})")Search by Color
Search by Hex Code
Find images matching a specific color with perceptual tolerance
# Search for walnut/brown colorsresults = await client.colors.search( hex_code="#8B4513", delta_e_threshold=20.0, # Perceptual difference tolerance (0-100, default: 15.0) min_percentage=10.0 # Minimum color coverage (default: 5.0))
print(f"Found {results.total_count} images")
for r in results.results: print(f"Image {r.image_id}: score {r.match_score:.2f}") if r.thumbnail_url: print(f" Thumbnail: {r.thumbnail_url}")Delta-E Color Matching
Understanding perceptual color difference
| Delta-E | Perception | Use Case |
|---|---|---|
| 0-5 | Imperceptible to slight | Exact color matching |
| 5-15 | Noticeable | Similar color search |
| 15-30 | Obvious difference | Same color family |
| 30+ | Different colors | Broad category matching |
Search by Color Family
Find images by semantic color category
# Find all earth-toned imagesearth_tones = await client.colors.search( color_family="earth_tone", limit=100)
# Find earth tones with significant presencewarm_earth = await client.colors.search( color_family="earth_tone", min_percentage=20.0 # Significant presence)
# Find metallic colorsmetallic = await client.colors.search( color_family="metallic")Search by Color Name
Search using semantic color names
# Find brass-colored materialsbrass = await client.colors.search(color_name="brass")
# Find walnut-colored itemswalnut = await client.colors.search(color_name="walnut")
# Find marble/white stonemarble = await client.colors.search(color_name="marble")Paginated Search
Handle large result sets with pagination
# Paginate through all resultsall_results = []offset = 0
while True: page = await client.colors.search( color_family="neutral", limit=50, offset=offset ) all_results.extend(page.results)
if not page.has_more: break offset += len(page.results)
print(f"Total: {len(all_results)} images")Auto-Pagination
Use search_all() to automatically iterate through all pages
# Iterate through all matching results automaticallyasync for result in client.colors.search_all(color_family="earth_tone"): print(f"Image {result.image_id}: {len(result.colors)} colors")Color Families
List Available Families
Get all color families with descriptions
families = await client.colors.list_families()
for family in families: print(f"{family.display_name}") print(f" {family.description}") print(f" Examples: {', '.join(family.example_colors[:3])}")Available Color Families
| Family | Description |
|---|---|
neutral | Blacks, whites, grays - versatile foundation colors |
earth_tone | Warm, natural colors inspired by earth and nature |
warm | Reds, oranges, yellows - energizing and inviting |
cool | Blues, greens, purples - calming and sophisticated |
metallic | Metallic and shimmer colors — gold, silver, bronze, copper |
pastel | Soft, muted colors with white undertones |
vibrant | Bold, highly saturated colors |
Batch Operations
Batch Re-extraction (Optional)
Colors are extracted automatically on upload. Use batch re-extraction only to re-run with different settings across multiple images.
# Force re-extraction with different color countresult = await client.colors.batch_extract( image_ids, force=True, # Re-extract even if colors exist n_colors=6 # Use fewer colors per image)
print(f"Queued {result.queued_count} images")
# Check status of individual images laterfor image_id in image_ids: status = await client.colors.get(image_id) print(f"{image_id}: {status.status}")Checking Extraction Status
Status Properties
Check the state of color extraction
result = await client.colors.get(image_id)
# Check status using propertiesif result.is_completed: print("Colors ready!") print(f"Extracted at: {result.extracted_at}")elif result.is_pending: print("Still processing...")else: print(f"Status: {result.status}")
# Access status as enumfrom aion.types.colors import ColorExtractionStatus
status_enum = result.status_enumif status_enum == ColorExtractionStatus.COMPLETED: # Process colors passelif status_enum == ColorExtractionStatus.FAILED: # Handle failure passExtraction Status Values
| Status | Meaning |
|---|---|
pending | Extraction not yet started |
queued | Queued for processing |
processing | Currently being processed |
completed | Colors extracted successfully |
failed | Extraction failed |
Type Reference
ColorExtractionResult
Returned by client.colors.get() and client.colors.extract()
@dataclass(frozen=True)class ColorExtractionResult: image_id: str status: str # pending | queued | processing | completed | failed color_analysis: Optional[ColorAnalysis] extracted_at: Optional[datetime]
# Properties @property def status_enum(self) -> Optional[ColorExtractionStatus]
@property def is_completed(self) -> bool
@property def is_pending(self) -> boolColorAnalysis
Complete color analysis for an image
@dataclass(frozen=True)class ColorAnalysis: version: str # Analysis algorithm version dominant_colors: list[DominantColor] # Ordered by percentage analytics: ColorAnalytics # Overall analytics extracted_at: Optional[datetime]DominantColor
A single dominant color
@dataclass(frozen=True)class DominantColor: rank: int # 1 = most dominant percentage: float # Coverage percentage rgb: RGB # RGB values hsl: HSL # HSL values lab: LAB # LAB values (for Delta-E) hex: str # Hex code (e.g., "#C4A87C") name: str # Semantic name (e.g., "Walnut") family: str # Color family
@property def family_enum(self) -> Optional[ColorFamily]Color Space Types
Color values in different color spaces
@dataclass(frozen=True)class RGB: r: int # 0-255 g: int # 0-255 b: int # 0-255
@dataclass(frozen=True)class HSL: h: float # Hue (0-360) s: float # Saturation (0-100) l: float # Lightness (0-100)
@dataclass(frozen=True)class LAB: l: float # Lightness (0-100) a: float # Green-Red (-128 to 127) b: float # Blue-Yellow (-128 to 127)ColorAnalytics
Overall image color analytics
@dataclass(frozen=True)class ColorAnalytics: temperature: ColorTemperature # warm | cool | neutral brightness: ColorBrightness # dark | medium | light saturation: ColorSaturation # muted | medium | vivid
@dataclass(frozen=True)class ColorTemperature: value: str # "warm", "cool", or "neutral" score: float # Confidence (0-1)
@dataclass(frozen=True)class ColorBrightness: average: float # Average brightness (0-100) category: str # "dark", "medium", or "light"
@dataclass(frozen=True)class ColorSaturation: average: float # Average saturation (0-100) category: str # "muted", "medium", or "vivid"ColorSearchResponse
Returned by client.colors.search()
@dataclass(frozen=True)class ColorSearchResponse: results: list[ColorSearchResult] total_count: int limit: int offset: int
@property def has_more(self) -> bool # More results available
@dataclass(frozen=True)class ColorSearchResult: image_id: str match_score: float # Lower = better match thumbnail_url: Optional[str] color_analysis: Optional[ColorAnalysis]ColorFamilyInfo
Returned by client.colors.list_families()
@dataclass(frozen=True)class ColorFamilyInfo: name: str # Internal name (e.g., "earth_tone") display_name: str # Display name (e.g., "Earth Tones") description: str # Description example_colors: list[str] # Example hex codes
@property def family_enum(self) -> Optional[ColorFamily]BatchColorExtractionResult
Returned by client.colors.batch_extract()
@dataclass(frozen=True)class BatchColorExtractionResult: queued_count: int # Number of images queued message: str # Status messageEnums
class ColorFamily(str, Enum): NEUTRAL = "neutral" EARTH_TONE = "earth_tone" WARM = "warm" COOL = "cool" METALLIC = "metallic" PASTEL = "pastel" VIBRANT = "vibrant"
class ColorExtractionStatus(str, Enum): PENDING = "pending" QUEUED = "queued" PROCESSING = "processing" COMPLETED = "completed" FAILED = "failed"