Repository navigation
fix(exposure): reach past the color refs by one fraction of each span - #1373
Merged
Merged
Conversation
The bounds analysis widened every channel's color refs to the luma window by the same amount in log units. On a negative whose channels differ in density range, that reach is a different fraction of each channel's span, so a gray scale normalizes to a different value per channel, and a negative Luma Range Clip tints the frame as it widens the window. The reach is now one shared fraction of each channel's own span: a ratio of sums, sum(l_c - r_c) / sum(s_c). A mean of per-channel ratios (#1366) lets a near-flat channel inflate the reach for all three; the ratio of sums keeps the old mean log reach and widens every channel alike. Measured on 264 color frames from 14 rolls (preview decode, saved crop and unmix): gray tilt against each frame's own gray axis drops from 0.110/0.138 to 0.079/0.116 (R/B, log), the error on a synthetically faded copy from 0.074 to 0.049, and the channel spread of the window growth at Luma Range Clip -0.3 from 1.19 to 1.03. Saved edits keep their stored bounds. Bumps THUMBNAIL_RENDER_VERSION; recording its golden also picked up the autocrop_square and autocrop_squared defaults it was missing. Co-authored-by: Sean Harding <sharding@dogcow.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The bounds analysis widens each channel's color refs out to the luma window. On main that reach is the same in log units for every channel. On a negative whose channels differ in density range (a faded negative, for example), it is then a different fraction of each channel's span, so a gray scale normalizes to a different value per channel. A negative Luma Range Clip also tints the frame as it widens the window.
The reach is now one shared fraction of each channel's own span, computed as a ratio of sums:
h = Σ(l_c − r_c) / Σ s_c.This replaces #1366, which averaged the per-channel ratios. That version lets a near-flat channel drive the reach for all three: a negative Luma Range Clip margin becomes
m · s_c · mean(1/s). The ratio of sums keeps the old mean log reach and widens every channel by the same fraction. The tests and docs are adapted from #1366 (co-authored by Sean Harding).Measurements
264 color frames from 14 rolls, measured with the Roll Analysis decode path (saved crop, flat field and unmix). An A/B/C/D toggle in the app was used for visual checks.
On these frames this PR and #1366 match closely. They differ only when one channel's span is near flat, which none of these frames have. The new headroom test covers that case.
Known limit: a strongly green-dominant scene (lawn, forest) can read as unequal channel ranges and pick up a slight magenta cast in the shadows. Within one frame, scene content and real fading cannot be told apart.
Changes
normalization.py: ratio-of-sums reach. Spans of mixed sign keep the single log reach.THUMBNAIL_RENDER_VERSION3 → 4. The recorded golden also picked up the missingautocrop_square/autocrop_squareddefaults.docs/PIPELINE.md: bounds paragraph.Saved edits keep their stored bounds. A frame changes only when it is measured again.
Test plan
make all(lint, ty, full pytest)