Skip to contents

Introduction

artbenchmark computes image-derived metrics for artwork analysis within the Artalytics benchmark framework. The package extracts color, coverage, and complexity metrics from artwork images to support portfolio-relative benchmarking across three categories:

  • Time & Effort - Canvas coverage, drawing hours, stroke volume
  • Skill & Artistry - Color palette diversity, spectrum coverage, blending quality
  • Complexity & Detail - Brushing precision, color variability, detail density

This guide walks you through the core workflows for computing and using these metrics.

Installation

# Install from GitHub (requires GITHUB_PAT)
# pak::pkg_install("artalytics/artbenchmark")

library(artbenchmark)

Package Hierarchy

artbenchmark is a computation package focused purely on metric extraction from images. It has no database or API dependencies, making it suitable for standalone analysis workflows.

appPlatform / mod* packages (application layer)
        |
    artutils (data access + benchmarking layer)
        |
    artbenchmark (metric computation)  ← This package

Dependencies: - data.table - Fast data manipulation - magick - Image processing via ImageMagick - stats - Statistical functions for quantiles - stringr - String pattern matching for color filtering

Used by: - artutils::update_artist_benchmarks() - Portfolio-relative percentile calculations - Shiny modules for artwork upload and profiling

A Complete Workflow: Computing Artwork Metrics

This workflow demonstrates how to compute metrics for a Procreate artwork with full metadata.

Step 1: Prepare Input Data

Artwork metrics require four inputs from the artwork upload process:

# Path to the main artwork image (typically main.png from Procreate export)
img_path <- "/path/to/artwork/main.png"

# File size in bytes (from file.info or upload metadata)
file_sz <- file.info(img_path)$size
# Example: 1500000 (1.5 MB)

# Drawing time in minutes (from Procreate stats extraction)
draw_mins <- 120
# Example: 2 hours of active drawing

# Brush stroke count (from Procreate stats extraction)
strokes <- 45000
# Example: 45,000 total brush strokes

Step 2: Compute Metrics

calc_art_metrics() is the primary function - it extracts raster data and computes all metrics in one call:

metrics <- calc_art_metrics(
    img_path = img_path,
    file_sz = file_sz,
    draw_mins = draw_mins,
    strokes = strokes
)

# Returns a data.table with metric_key and value columns
print(metrics)
#>          metric_key        value
#>  1: canvas_coverage    87.234567
#>  2: n_unique_colors  8234.000000
#>  3: share_of_spectrum   0.000491
#>  4:  ave_blend_rate      0.817234
#>  5: ave_colors_pstroke  0.183011
#>  ...

Step 3: Understanding the Output

The metrics are returned in long format (one row per metric) for easy database insertion:

Core Metrics (Used in Benchmarks)

These six metrics feed into portfolio-relative benchmarking:

  • canvas_coverage - Percentage of canvas with color (0-100)
  • n_unique_colors - Unique color count in palette
  • share_of_spectrum - Proportion of RGB color space used (0-1)
  • ave_blend_rate - Blending smoothness indicator
  • ave_colors_pstroke - Colors created per brush stroke
  • q75_color_freq - 75th percentile of color frequency distribution

Extended Metrics (Stored for Analytics)

Additional metrics stored but not used in the core 16-metric framework:

  • Color frequency quantiles: q25_color_freq, q50_color_freq, count_dom_colors
  • Time-based productivity: ave_bits_psec, ave_strokes_psec, ave_colors_psec
  • Complexity ratios: ave_bits_pstroke, ave_bits_pcolor

Step 4: Prepare for Database Insert

Add identifiers before persisting to the database:

# Add artwork and artist identifiers
metrics[, `:=`(
    art_uuid = "99a61148-1d3b-4340-8cf6-92ad26046b0f",
    artist_uuid = "746b8207-72f5-4ab6-8d19-a91d03daec3d",
    created_utc = Sys.time()
)]

# Now ready for database insert via artutils functions

Working with Raster Data

For custom analysis beyond the standard metrics, you can extract raster data directly.

Extract Color Palette

get_image_rast() processes the image and returns filtered color data:

rast_data <- get_image_rast(img_path)

# Returns a list with three elements:
# - colors: data.table with col (hex color) and N (pixel count)
# - total_px: Total pixels in resized image
# - colored_px: Pixels with color (after background removal)

Custom Metric Examples

# Calculate custom coverage metric
custom_coverage <- (rast_data$colored_px / rast_data$total_px) * 100

# Find dominant colors (top 10 by frequency)
dominant_colors <- rast_data$colors[order(-N)][1:10]

# Check palette size
palette_size <- nrow(rast_data$colors)

Background Filtering

The raster extraction automatically filters:

  • Transparent pixels - Removed before analysis
  • Near-white colors - Patterns like #f[fedc8a]*
  • Near-black colors - Patterns like #0[012]*

This ensures metrics reflect actual artwork content, not canvas background.

Predictions for Missing Metrics

When Procreate stats are unavailable (e.g., photos of physical art, scanned drawings), use prediction functions:

Predict from Color Count

# Extract color count from image
rast_data <- get_image_rast(img_path)
n_colors <- nrow(rast_data$colors)

# Predict missing metrics
strokes_pred <- predict_strokes(n_colors)
minutes_pred <- predict_minutes(n_colors)

print(strokes_pred)
#>   n_unique_colors pred_strokes
#> 1            8234        45123

print(minutes_pred)
#>   n_unique_colors pred_minutes
#> 1            8234          118

Important: These are estimates based on ML models trained on verified artworks. Actual metrics from Procreate stats are always preferred when available.

Using the Metric Framework

The package provides authoritative reference functions for the benchmark framework:

Get All Metric Definitions

# Complete framework with 16 metrics
defs <- get_metric_definitions()
print(defs)
#>         category         metric_key            metric_name         source
#>  1:  time_effort      drawing_hours          Drawing Time stats_extraction
#>  2:  time_effort            ave_bpm          Drawing Speed stats_extraction
#>  3:  time_effort      brush_strokes          Brush Strokes stats_extraction
#>  ...

Check Which Metrics artbenchmark Computes

# Get metrics with source = "image_analysis"
image_metrics <- get_artbenchmark_metrics()
print(image_metrics)
#> [1] "canvas_coverage"    "ave_blend_rate"     "n_unique_colors"
#> [4] "share_of_spectrum"  "ave_colors_pstroke" "q75_color_freq"

Lookup Display Names

# Get official name for UI display
get_metric_name("canvas_coverage")
#> [1] "Canvas Coverage"

# Get category for grouping
get_metric_category("n_unique_colors")
#> [1] "skill_artistry"

Next Steps

For integration with the full platform benchmarking system, see the artutils package documentation.