Analyze and visualize the colour properties of image datasets
Quick start: 1 · Drop in images or a folder. 2 · Review the data check suggestions and set Configuration preferences. 3 · Analyze Images, then read the Data tab for CSVs and dataset statistics, and the Visualization tab for dataset- and image-level visualizations.
JPG, PNG, WebP, GIF, BMP · nothing leaves your computer
Configuration
Choose 360° for equirectangular, fisheye, or tiny-planet / azimuthal imagery to enable solid-angle weighting, projection conversion, and polar spatial analysis.
360° imagery — projection, weighting & conversion
Input
Elev°full 360° = 90 / −90
Full angle°
Frame
Spatial
Geometry°
ExtentVertAzimuth
Exportneeds “Convert first”
preview — first image in the analysis frame
Choosing settings.Equirectangular: a standard 360 photo is 2:1 = 360°×180° — set Elev top 90 / bottom −90 (zenith to nadir). Use 90 / 0 only if your image is an upper-hemisphere crop (horizon at the bottom row). This range drives the cos(elevation) weighting and, when converting, which rows are sampled — so it must match your actual image. The disk edge° auto-fills from this range to cover the whole source (edge = 2·(top−bottom): 90/−90 → 360 full sphere; 90/0 → 180 hemisphere); edit it to crop. Fisheye: circular, centred — set Full angle to the lens FOV (usually 180); equidistant needs weighting, equisolid is already equal-area. Stereographic / tiny-planet: zenith-centred disk, Full angle 180 = horizon at the rim; the rim is hugely stretched (down-weighted ∝ cos⁴(θ/2)) — best for figures, not naive stats. Lambert equal-area: equal-area disk — naive stats are unbiased (good convert-first target). Azimuthal equidistant: radius ∝ elevation angle. Frame: use Native to keep resolution (weighting corrects the bias), or Convert first → Lambert for an unbiased equal-area analysis. Spatial: pick Polar for disk/azimuthal frames so grids and profiles read as rings (elevation) and wedges (azimuth).
Images are downsampled to this maximum dimension before analysis
K-means clustering (k-means++ init, fixed seed for reproducibility)
How transparent PNG areas are treated
Columns — colour spaces, statistics & scene metrics
Presets:
Colour spaces:
Statistics:
Scene metrics:
LAB/LCH raw values in the cluster & pixel tables follow the LAB/LCH space toggles above.
Local files (recommended) — drag and drop images or select a folder. Nothing is uploaded; analysis happens in your browser. EXIF (GPS, date, camera) is read from JPEGs and from PNGs carrying an eXIf chunk, including cut-outs exported by Image Cutter with GPS/EXIF preserved. Image URLs also work if the host allows cross-origin (CORS) access.
Core settings — Analysis resolution sets the working resolution; Colour Clusters sets the k-means palette size (k-means++, fixed seed, weighted when projection weighting is on); Transparency Handling defaults to Opaque pixels only (composite onto white/black/grey are alternatives).
Columns (collapsible) — choose which colour spaces (RGB, HSV, LAB, LCH), statistics (mean, median, std dev, range, IQR), and scene metrics to export, or use the Core / Full / Minimal presets. Each row has an "all" toggle. Hue is treated circularly (mean, median, circular variance). Scene metrics: colourfulness, redness index, CCT, RMS contrast, dark-channel haze, warm/cool/neutral, hue entropy, and chromaticity (u′, v′, duv). Column names follow a consistent SPACE_CHANNEL_STAT scheme (e.g. HSV_V_mean, LAB_L_median, LCH_C_range).
Geometry sidecar (SunSync 360) — an equirectangular frame's x axis is only a compass if you know which way the camera was pointing, and consumer 360 cameras do not record it. Load the geometry CSV that SunSync 360 exports and each frame gains a heading, joined on filename stem (the same key the Compare tab uses, so cut-outs renamed by Image Cutter still line up). The join is reported before you run: how many images matched, how many sidecar rows have no image here, and whether any matched frame is unregistered. Two things then become available. Register azimuth to true north rotates the sampling lattice so column 0 is north — it changes the column profile, the grid, Moran's I and cluster centroids, and deliberately leaves the row profile untouched, because elevation profiles are rotation-invariant and stay trustworthy on unregistered frames. Scattering-angle bins re-index every pixel by its angular distance from the sun (Θ) instead of by where it sits in the frame; that is the quantity scattering theory makes predictions about, and unlike frame position it means the same thing across dates, times and sites, so it is what allows two datasets to be compared. Note that annuli near Θ=0° and Θ=180° cover far less sky than those near 90°, so read the n column beside the colour. Frames whose sidecar row is gated or unregistered keep their raw axis rather than borrowing another frame's heading, and the image-summary CSV carries yaw_offset_deg, yaw_source and registration_status so any figure can state how its frames were registered.
Histogram table (collapsible) — export per-image histograms for any of hue, saturation, and value, in long format with a channel column.
Imagery mode → 360° — switch to 360° for equirectangular, fisheye, or tiny-planet / azimuthal imagery and a projection panel opens directly below the Imagery mode selector. It exposes: an input projection (equirectangular, fisheye equidistant/equisolid, stereographic/tiny-planet, Lambert equal-area, equidistant azimuthal) with the matching solid-angle weighting so pixel counts don't bias means, medians, cluster percentages, histograms or colourfulness; an analysis frame choice — analyse natively in that projection, or convert to another projection first (e.g. Lambert equal-area for unbiased naive stats); a spatial mode (Cartesian x=azimuth/y=elevation, or polar with radial=elevation and angular=azimuth for disk frames); and a Convert & export button that reprojects your queued images and downloads each as a 300 dpi PNG (tiny-planet figures, or to feed back in).
Spatial structure (collapsible) — an X × Y grid (with an optional lock to each image's ratio for square cells) yields row/column colour profiles, a grid/tile table, per-cluster centroid and spatial spread, and Moran's I spatial autocorrelation computed per cell on any chosen channels or metrics (L*, C*ab, saturation, value, a*, b*, R, G, B, redness, CCT, colourfulness, RMS contrast, dark-channel).
Visualization (collapsible) — enable per-image views and pick which to offer: Original image, Palette, Cluster-region image, Grid, Grid heatmap (coloured by a chosen channel/statistic with a legend), Row/column profile, H/S/V histogram, and Chromaticity (u′v′). Each opens from a dropdown on the result and downloads as a crisp PNG tagged at 300 dpi. A heatmap-palette selector switches the ramp used by heatmaps and dataset grids (viridis default; cividis; blue–yellow diverging, centred at 0 for b*).
Dataset visualizations — across the whole set: a summed hue/saturation/value histogram, an aggregate palette (all dominant colours combined, sorted by hue), and a metric-distribution view (histogram of any image-level metric or Moran's I value, with mean and median marked). With Spatial structure on, also dataset spatial composites — a mean composite grid, a variability (SD) grid, mean elevation and azimuth profiles, and a cluster-centroid density map — with vertical (horizon→zenith / fixed) and azimuth (none / brightest column / compass N / sun) registration for frames that aren't perfectly aligned. Downloads as 300 dpi PNG.
Compare tab — beside Data / Visualization, always available: runs two-set ΔE2000 comparisons (matched on filename stems, with unmatched files reported) and flags outlier images in the current results.
Outputs — cluster-level, image-level, and optional pixel-level, histogram, and spatial (profiles, grid) tables, each downloadable as CSV. Everything runs locally; nothing is uploaded.