Overview
This quickstart demonstrates the core workflow for computing artwork metrics from an image file. You’ll go from a Procreate export to benchmark-ready metrics in under 5 minutes.
Prerequisites
You need:
- An artwork image file (PNG or JPG from Procreate export)
- Artwork metadata from Procreate stats extraction:
- File size in bytes
- Drawing time in minutes
- Brush stroke count
Basic Metric Computation
Example Data
Let’s use realistic example values:
# Artwork file path
img_path <- "~/artworks/landscape-sunset.png"
# Metadata from Procreate stats
file_sz <- 1847293 # ~1.8 MB file
draw_mins <- 145 # 2 hours 25 minutes
strokes <- 52340 # 52k brush strokesCompute All Metrics
One function call computes everything:
metrics <- calc_art_metrics(
img_path = img_path,
file_sz = file_sz,
draw_mins = draw_mins,
strokes = strokes
)
# View results
print(metrics)Output structure:
metric_key value
1: canvas_coverage 91.234567
2: n_unique_colors 9876.000000
3: share_of_spectrum 0.000589
...
Interpreting Metric Values
Understanding what the values mean helps validate results:
Canvas Coverage
metrics[metric_key == "canvas_coverage"]
#> metric_key value
#> 1: canvas_coverage 91.23457
# 91% = Artist used most of the canvas
# Low values (<50%) might indicate small artwork or lots of white space
# High values (>95%) suggest full canvas utilizationColor Palette Size
metrics[metric_key == "n_unique_colors"]
#> metric_key value
#> 1: n_unique_colors 9876
# ~10k colors = Rich, detailed digital painting
# <1000 colors = Limited palette or simple illustration
# >20k colors = Complex artwork with extensive blendingSpectrum Coverage
metrics[metric_key == "share_of_spectrum"]
#> metric_key value
#> 1: share_of_spectrum 0.00058873
# 0.00059 = 0.059% of RGB color space
# Total RGB space = 16,777,216 colors (256^3)
# This artwork uses 9,876 / 16,777,216 = 0.059%
# Higher values indicate broader color explorationBlending Quality
metrics[metric_key == "ave_blend_rate"]
#> metric_key value
#> 1: ave_blend_rate 0.8123456
# 0.81 = High blending rate (many colors created relative to strokes)
# Formula: 1 - (strokes / unique_colors)
# Higher values = more blending and color mixing
# Lower values = discrete strokes without much blendingUsing Predictions
When Procreate stats aren’t available, estimate metrics from color count alone:
Extract Color Count from Image
# Get raster data
rast_data <- get_image_rast(img_path)
# Count unique colors
n_colors <- nrow(rast_data$colors)
print(n_colors)
#> [1] 9876Predict Missing Metrics
# Predict brush strokes
strokes_pred <- predict_strokes(n_colors)
print(strokes_pred)
#> n_unique_colors pred_strokes
#> 1 9876 53201
# Predict drawing time
minutes_pred <- predict_minutes(n_colors)
print(minutes_pred)
#> n_unique_colors pred_minutes
#> 1 9876 142Accuracy note: Predictions are estimates based on ML models. For our example with actual values:
- Actual strokes: 52,340
- Predicted strokes: 53,201
- Error: ~1.6%
Good enough for benchmarking unverified artworks, but always prefer actual Procreate stats when available.
Preparing for Database Insert
Add identifiers to make metrics database-ready:
# Artwork and artist UUIDs from the upload process
metrics[, `:=`(
art_uuid = "99a61148-1d3b-4340-8cf6-92ad26046b0f",
artist_uuid = "746b8207-72f5-4ab6-8d19-a91d03daec3d",
created_utc = Sys.time()
)]
# Now ready for insertion into artwork_stats table
# Usually handled by artutils::insert_artwork_metrics()Quick Reference: Core Metrics
| Metric Key | Category | What It Measures |
|---|---|---|
canvas_coverage |
Time & Effort | % of canvas with color |
n_unique_colors |
Skill & Artistry | Palette diversity |
share_of_spectrum |
Skill & Artistry | RGB color space utilization |
ave_blend_rate |
Skill & Artistry | Color blending quality |
ave_colors_pstroke |
Complexity & Detail | Colors per brush stroke |
q75_color_freq |
Complexity & Detail | Color frequency distribution |
Common Pitfalls
Issue: All metrics return NA or error
Cause: Invalid image path or corrupt image file
Solution: Verify file exists and is readable by ImageMagick:
file.exists(img_path)
magick::image_read(img_path)Issue: Canvas coverage = 0%
Cause: Image is all white/black or transparent
Solution: Check the artwork visually - may need different background filtering
Issue: Predictions way off from actual values
Cause: Artwork outside normal range (e.g., simple line art with high stroke count)
Solution: Predictions work best for typical digital paintings. Use actual stats when available.
Next Steps
- Get Started - Complete workflow guide with detailed explanations
- Advanced Workflow - Batch processing and custom analysis
- Function Reference - Full API documentation
For integration with platform benchmarking, see artutils::update_artist_benchmarks().
