How image measures lie quietly

Nineteen ways a hand-built image measure returns a plausible, wrong number without raising an error, and the check that catches each one.

Parallax Metrology · 29 October 2026 · from the lab log of the Image Structure Reader

The Image Structure Reader is a deterministic instrument for reading the structure of paintings: where the masses sit, how they balance, what the eye is drawn through. Over sixteen studies its lab log recorded every time a number turned out to be wrong. Almost none of those errors raised an exception. The code ran, the number looked plausible, and in most cases a first draft had already built an argument on it before a control caught it.

The failures are not specific to paintings or to this instrument. They live in the ordinary parts of image-measurement code: percentile normalisation, a threshold, a centroid, a ratio, a random null, a comparison set. Anyone building mass maps, balance scores, saliency summaries, colour statistics or composition indices will meet most of them.

Each entry below gives what happens, a case where it happened, and the check. Where the failure can be reproduced on a synthetic image, it is reproduced here, live, by a short script: every number in a figure caption is computed, not drawn.

The short version. Most of these were caught the same way: by building an input whose right answer was already known and checking that the measure returned it. A field that has collapsed, a mask that covers nothing, a score pinned at its ceiling and a ratio with a vanishing denominator all look healthy from outside. The checks are cheap. Not running them is what is expensive.
  1. The dead field
  2. Stretched dust
  3. The starved mask
  4. Ceilings that fake agreement
  5. Ratios with tiny denominators
  6. Resolution is part of the measurement
  7. Minimum mark size
  8. Cleaning changes some measures, not others
  9. A record needs a known-answer control
  10. A control has free parameters too
  11. A control's direction does not interpret itself
  12. Single random draws mislead
  13. A hand-picked comparison makes a false extreme
  14. Unseeded randomness
  15. The default lens is blind to the construction
  16. The measure reads the substrate
  17. A failure belongs to the situation
  18. Two things with the same name
  19. Worked is not contrasting

Normalisation

1The dead field

What happensPercentile normalisation maps the 2nd to the 98th percentile onto 0 to 1. When those two percentiles are equal, it returns all zeros. That happens whenever fewer than about 2% of pixels carry signal: a hard-edged shape on a flat ground, a document scan, an empty sky. Nothing downstream notices. A threshold at the field's 85th percentile is then a threshold at zero, which selects every pixel, and the centroid of every pixel is exactly the centre of the frame, wherever the shape actually is.

CaseA black square placed off-centre read as perfectly centred. Two false findings built on this ("the centroid is translation-invariant", "the torque instability is hard-edge aliasing") survived a full review round and corrupted three earlier rounds of control numbers before anyone instrumented the mask.

An off-centre square, its all-zero stretched edge field, a mask covering the whole frame, and a plot where the reported offset stays at zero as the square moves
Only 0.18% of pixels carry any gradient, so the stretched edge field is zero everywhere and its top 15% is 100% of the frame. The square's true offset is (+0.24, −0.21); the reported offset is (+0.00, +0.00). Right: the square moved across the frame.
Check. Test p98(field) > 0 before reading anything derived from the field, and refuse to label a dead one. A mask covering 100% of the frame is the symptom; the collapsed field is the cause.

2Stretched dust

What happensThe mirror image of the dead field. When a field is nearly constant but not exactly constant, min-max or percentile stretching expands rounding noise to full scale. The field then looks perfectly healthy, with a maximum of 1.0, while carrying no signal, so a health check on the stretched field passes it.

CaseA colour-boundary measure read its maximum possible value on a pure grey step, where the right answer is zero; the measure's own guard against empty colour was dead code, because the field reaching it had already been stretched to 1.0. The same fault turned up again in the Notan mass extracted from the instrument, where it affected seven of nine test images.

A two-grey image, its chroma stretched into a black and white step, and a log-scale bar chart comparing rounding-level chroma with real muted and clear colour
Two greys and no colour: the raw chroma never exceeds 3e-08. Stretched, that noise becomes a full-strength colour step and makes up 33% of a value-plus-colour mass. For scale, a barely tinted grey-brown reads 0.011, about five orders of magnitude higher.
Check. Inspect magnitude before normalisation, never after. Gate only at machine zero (below 1e-6 here): muted paintings read around 0.01 to 0.04, and a higher floor would erase exactly the quiet colour that carries them.

3The starved mask

What happensThe field is alive, so the check in entry 1 passes, but the mask built from it covers almost nothing. Every coordinate then describes one small fragment, not the picture.

CaseOn a colour-field painting the structural mask was 0.077% of the frame: one small dark mark in a corner. The summary label read "a strong connected structural mass" for a painting with no hard edges anywhere. This corrected an earlier conclusion that coverage was only a symptom: for this failure, coverage is the gate.

A soft green rectangle on maroon with one small dark mark, an edge mask containing only that mark, and a value-mass map showing the rectangle
Committed edges cover 0.02% of the frame, all of it the one mark, so the edge centroid sits in the corner at (+0.41, −0.40). A value-mass reading, which never touches the edge mask, puts the picture's weight at (+0.00, −0.00).
Check. Report mask coverage and refuse whole-image labels below a floor (0.5% worked: healthy paintings read 3 to 14%). Then look at what the mask actually contains.

4Ceilings that fake agreement

What happensA count capped at 20, or a score clipped to 0..1, reads the same maximum on every rich image. Two images then "agree" because both hit the cap.

CaseTwo very different pictures both read 20 regions and 10 active regions, and this was quoted as a resemblance; both numbers were ceilings. Separately, a "restlessness" index read exactly 1.000 at three resolutions; the unclipped value was 1.48.

An image of 80 blobs and a plot where the reported region count flattens at 20 while the true count keeps rising
A peak finder asked for at most 20 peaks. With 80 blobs it finds 76 uncapped and reports 20; with 200 it finds 168 and reports 20.
Check. Any bounded score should report when it is at its bound. When it is, fall back to the unclipped parts, and never quote it as a coordinate.

5Ratios with tiny denominators

What happensA ratio explodes as its denominator approaches zero, and the explosion looks like a record.

CaseA whole-versus-part balance ratio read about 31 on a painting whose parts were uniform (denominator 0.019). It was not even a property of the work: a synthetic square read 28 or 16 depending only on where it was placed.

Two plots: figure-to-ground ratio rising steeply as the ground darkens, and figure-minus-ground difference staying nearly flat
The arithmetic, on a contrast ratio. A figure of luminance 0.30 against a ground of 0.02 reads 15; against 0.002 it reads 150. The difference moves from 0.280 to 0.298.
Check. Report the denominator next to every ratio. When the parts are uniform, call the ratio unquotable, not extreme.

Scale and reproduction

6Resolution is part of the measurement

What happensYou never measure the painting. You measure the painting times the photograph, lens, compression and resize, at one scale window.

CaseThin-structure measures on a painting moved from 1.08 to 1.49 across a 400 to 4000 pixel sweep, and an early "highest stability" claim built on one of them was retracted. Dense-area measures barely moved and could be compared.

A Sierpinski triangle generated exactly, the same triangle resampled, and a plot of measured fractal dimension against size for three thresholds
A Sierpinski triangle generated at any power-of-two size reads its exact box-counting dimension, 1.585. Resample it once, the way a photograph is resampled, and the same object reads anywhere from 1.42 to 1.64, depending only on the output size and the threshold used to binarise it. At 600 px: 1.42 at threshold 0.5, 1.61 at 0.1.
Check. Sweep resolution before comparing images. Compare only measures that survive the sweep, or match the scale window, and report the window with the number.

7Minimum mark size

What happensA detector with a size floor finds nothing on a surface whose marks are smaller than the floor, and reports a clean zero.

CaseAn accent detector with a floor of about 41 pixels returned zero accents on broken-colour brushwork whose marks were about 16 pixels. Smoothing to brush scale first recovered them.

A field of small dots, and a plot of the share of marks found against mark size, with and without smoothing to mark scale
Sixty marks of each size. With 5 px marks the detector finds 0% of them; smoothed to the marks' own scale first, it finds 98%.
Check. When a result is a surprising zero, look under it at the sub-threshold field before reporting a null.

8Cleaning changes some measures, not others

What happensDenoising, or any preprocessing, inflates some readings, deflates others and leaves the rest untouched. It also changes what counts as an edge, because diffusion softens committed edges.

CaseOn a dark museum photograph, dust and grain inflated one dominance margin from 1.3x to 2.8x and hid six real accents, including the fingertip of a pointing hand, while tonal measures moved only in the fourth decimal. Separately, a change blamed on removing a painting's cracks came from downscaling, not from the crack removal: at fixed resolution the cleaning moved the number from 0.487 to 0.516, while downscaling alone moved it to 0.954.

Check. Re-run each measure with and without the cleaning, at the same resolution. Never compare edge-based numbers across pipelines that differ.

Controls and comparisons

9A record needs a known-answer control of the same kind

What happensAn extreme value looks like a property of the work until you measure an ideal synthetic example of the same class.

CaseA painting of a black square produced four "corpus records". A machine-perfect black square on a flat ground matched or beat all four: one score was 61.9 for the painting and 60.9 for any centred square. What remained was the deviation from the ideal, and every survivor was a deficit: the hand-tilt, not the square.

Check. Build the theorem case for the class, re-baseline against it, and quote the deviation from the ideal rather than the raw value.

10A control has free parameters too

What happensA control introduces its own settings: a noise level, an offset, a fill value. If those settings move the result as much as the effect being claimed, the control measures nothing.

CaseA control rested on a single grain amplitude that was never swept; sweeping it across an 8x range is what turned a coincidence into a finding. In another case, filling an ablated region with the median gave a score of 0.08, and filling it with white gave 2.05.

The same mass removed three ways, by median, white and black fill, and a bar chart of three different off-centre scores
One mass removed from a two-mass picture. The original reads 0.038. The same removal reads 0.250 with a median fill, 0.037 with white and 0.100 with black: a white or black fill is not an absence, it is a new mass.
Check. Sweep every free parameter of a control and report whether the ordering survives. For ablations, show that the result does not depend on the fill; a result that does is evidence the measure lives in a relation between regions, which is itself worth reporting.

11A control's direction does not interpret itself

What happensWhen a number drops under a control, three cases look identical from outside: the control removed noise (trust the new value more), removed signal (trust it less), or changed the question (the two values are not comparable).

CaseCompression collapsed a colour-boundary score correctly: a true chromatic boundary held 1.000 down to quality 12 while the noise-driven score died. Anisotropic diffusion collapsed the same score incorrectly, taking a known 1.000 to 0.000. A min-max normalisation returned about 1.0 whether the true ratio was 5x or 10x, because it is blind to magnitude by construction.

Check. Run the control on an input whose answer you already know before reading its effect on one whose answer you do not.

12Single random draws mislead

What happensA null built by scrambling the image gives a different answer every seed. One draw can land anywhere, and twenty is often not enough.

CaseA result looked significant after 20 seeds (p about 0.05) and was not after 100 (p = 0.11). For another measure the null was chaotic: across five seeds its maximum ranged from 0.22 to 10.97. The honest form there was "the work gives the same verdict every time; the nulls give a different one every seed".

A histogram of 400 phase-scrambled scores with the real score in the tail, and running p estimates for three seed orders converging slowly
A picture's off-centre score is 0.077; a single phase-scrambled copy scored 0.019, which looks like a decisive gap. Against all 400 copies, p = 0.025. Using only the first 20 draws, three different seed orders give p = 0.048, 0.143 and 0.048.
Check. Use 100 or more draws and quote an empirical percentile. With zero exceedances in n draws, write p ≤ 1/(n+1), never p = 0.

13A hand-picked comparison makes a false extreme

What happens"The most isolated mark" is only as good as the marks it was compared against, and foils chosen after seeing the target tend to lose.

CaseA calligraphic inscription was called the most isolated mark in a landscape, measured against six hand-chosen marks, every one of them ink embedded in other ink. A full grid over every inked cell found 74 to 278 cells more isolated than it, across every threshold and radius tried.

An ink field with a target mark and six foils chosen from dense clusters, and a histogram showing many cells more isolated than the target
Against six foils picked from the clusters (best 0.42), the target's isolation of 0.98 is the clear maximum. Against every one of the 447 inked cells, 14 are more isolated than it.
Check. Before any superlative, compare against a complete, unchosen reference set: the whole grid, the whole corpus, every mark.

14Unseeded randomness inside a "deterministic" pipeline

What happensOne library call uses randomness without a fixed seed, so the same script on the same image returns different numbers.

CaseA probabilistic Hough transform returned an orientation statistic between 0.10 and 0.20 across six back-to-back runs. The convergence point the lines defined was stable; the statistic over which lines survived was not.

An image of 40 lines and a strip plot: twelve unseeded runs scatter widely, twelve seeded runs sit on one value
Twelve runs of probabilistic_hough_line on the same 40 lines, with no seed: the statistic ranges from 0.04 to 0.26. With rng=0, all twelve runs return the same value. (This figure is itself unseeded, so its range changes each time the page is rebuilt.)
Check. Run everything twice. Seed every random step, and report anything that depends on randomness as a range over repeated runs.

What the measure is actually reading

15The default lens is blind to whatever the work is built from

What happensA mass map built mostly from edges under-reads exactly what a given picture uses most. Colour fields hide from luminance, flat value masses hide from edges, colour-only shapes hide from both.

CaseA painted crowd of praying figures carried 9% of the edge-based mass and 48% of the value mass: the painting's largest mass, visible only to a texture-robust squint. The same blind spot appeared in a colour-field painting (structure only in chroma) and in a cow painted only in colour.

A flat dark ellipse and a small noisy patch; an edge-led mass map that sees only the ellipse's outline and the patch; a value-mass map that sees only the ellipse
The flat dark mass covers 18% of the frame. An edge-led blend gives it 4% of the mass and gives a small busy patch (7% of the frame) 23%. A value mass gives them 93% and 1%. Neither is neutral: the value lens is blind to texture that averages to the ground's tone.
Check. Before running, name how the picture is built (by value, colour, line or texture) and expect the default lens to under-read there. Reach for the lens that matches before the first read, not after the null surprises you.

16The measure reads the substrate

What happensA colour statistic computed relative to the image's own distribution reports the paper, silk or ground when that dominates the picture.

CaseA colour score was higher on a patch of bare silk (0.84) than on the whole calligraphy (0.73). On colour-field paintings the same score did not move when the colour was desaturated, so it was not reading the colour at all; it fails on an empty sheet and on a full colour field for the same reason, because it assumes a figure on a neutral ground.

Grey ink strokes on warm tinted paper, and a bar chart where the whole image and a bare patch of paper score the same
Grey ink on tinted paper; the ink covers 3% of the frame. A score for how much of the image's colour sits in the empty space reads 0.99, which sounds like a finding about colour in the void. A bare patch of paper reads 1.00, and removing the colour reads 0.00. The score is reading the paper.
Check. The three-way test: the real image, a colour-stripped copy, and a bare patch of the substrate. If the bare patch scores like the work, the measure is reading the support.

17A failure belongs to the situation, not the object

What happensA measure fails on one figure, and the failure gets read as a property of that figure.

CaseA painter's self-portrait in black against a shadowed wall could not be separated from its ground, and a first draft read this as how the artist had painted himself, "without a boundary". Every dark-on-dark figure in the painting failed the same way, and a shadowed attendant failed harder (chosen component 0.9% of its box against the painter's 9.1%). The study had simply not measured the others.

Check. Before attributing a failure to an object, test a second object in the same tonal situation. Calibrate against a figure of the same class, never a lit one.

18Two things with the same name

What happens"The largest mass" from an edge mask and from a density map can be different objects. "Share" can have two denominators.

CaseA summary sentence attached the edge mask's largest component to the density map's anchor; they were different objects in different parts of the frame. A "committed edge" share was compared against a threshold meant for a different denominator, and 85% became 47%, rank 4 of 7.

Check. Name which subsystem each number comes from, and match each metric to its denominator.

19Worked is not the same as contrasting

What happensA measure of coherent, worked form says nothing about tonal contrast. A region can be intricately worked and almost invisible at once.

CaseAn engraved gold halo read highly worked (coherence 0.993) while being only about 0.02 darker than the flat gold around it, and the face painted against it dissolved into it (contrast about 0.010).

Check. When an argument is about figure and ground, or about what the eye separates, measure contrast directly. Do not let one axis stand in for another because the words sound close.

The checklist

#FailureCheck
1Dead fieldp98(field) > 0 before reading it
2Stretched dustRaw magnitude before normalising; gate at machine zero
3Starved maskMask coverage floor; look at what the mask holds
4CeilingsReport when a score sits at its bound
5Tiny denominatorsReport the denominator with the ratio
6ResolutionSweep it; compare only what survives
7Mark-size floorLook under a surprising zero
8CleaningWith and without, at the same resolution
9RecordsKnown-answer ideal of the same class; quote the deviation
10Control parametersSweep them; fill-invariance for ablations
11Control directionRun the control on a known answer first
12Single drawsn ≥ 100; p ≤ 1/(n+1), never 0
13Hand-picked foilsComplete, unchosen reference set
14Unseeded randomnessRun twice; seed everything
15Default lensName the construction mode before the run
16SubstrateReal, colour-stripped, bare-substrate
17Situation, not objectSecond object in the same situation
18Same name, two thingsName the subsystem and the denominator
19Worked vs contrastingMeasure the axis the argument is about

What these have in common

Read together, the entries fall into three families. Some are faults in shared plumbing, the normalisation and thresholding every measure passes through (1 to 5); they are the most dangerous because one fault reaches every number at once, and the most fixable, because a guard written once protects all of them. Some are faults of scale and reproduction (6 to 8), where the number is a fact about the photograph as much as the picture. And the rest are faults of inference (9 to 19): the number is correct, and the sentence built on it is not.

The common cure is the known-answer input: an image built so that the right answer is not in doubt. A black square that must read off-centre, a grey that must read colourless, a mark that must be found, a scramble that must not beat the original. A small set of such images, for testing mass and composition measures, ships with the notan package, and the scripts behind every figure here are in the companion repository. When a measure surprises you, look underneath it before believing it, and before discarding it: in the lab log, several of these failures became the sharpest results.

Method

The cases are taken from the Image Structure Reader's lab log, written up from its numbered instrument findings; their numbers are the log's, measured on museum photographs of paintings, and are not recomputed here. The figures are synthetic reproductions of the same failure modes, generated by one script with numpy, scipy, scikit-image and matplotlib (entries 2, 3, 15 and 16 also use the Notan mass from the notan package); each caption's numbers are read from that script's output when the page is built. The demonstrations use deliberately ordinary code (percentile stretch, percentile threshold, weighted centroid, capped peak finding) so that they show the pattern, not a particular implementation. The code for every figure is in the companion repository. The analysis and this page were built with an AI assistant under the author's direction.