BUG: Propagate rank to the last axis in FastApproximateRank#6580
Merged
hjmjohnson merged 1 commit intoJul 10, 2026
Merged
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
bf7a532 to
e9125ca
Compare
hjmjohnson
approved these changes
Jul 10, 2026
7 tasks
FastApproximateRankImageFilter is a separable mini-pipeline of one per-axis RankImageFilter per image dimension (m_Filters has ImageDimension entries; each sub-filter defaults to rank 0.5, the median). SetRank() looped over ImageDimension - 1 filters, so the sub-filter for the last axis never received the caller's rank and always ran at its default median. For 1-D images the loop body never executed, so the rank never propagated at all. Change the loop bound to ImageDimension so every per-axis sub-filter receives the requested rank. Add a regression test that drives a 2-D image constant along axis 0 and increasing along axis 1, so only the last-axis pass changes the result: with rank 0.02 the interior pixels must equal the window minimum, which fails before the fix (the last axis ran at the default median) and passes after it. Addresses item B18 of InsightSoftwareConsortium#6575.
e9125ca to
841f4b6
Compare
5692478
into
InsightSoftwareConsortium:main
15 of 18 checks passed
physwkim
added a commit
to physwkim/sitk-rs
that referenced
this pull request
Jul 12, 2026
Upstream's SetRank forwarded rank to only the first ImageDimension-1 of its per-axis filters, leaving the last axis permanently forced to RankImageFilter's own built-in default of 0.5 (median) regardless of the caller's requested rank -- and for 1-D images, whose only axis is axis 0 == ImageDimension-1, the loop body never ran at all. Fixed per upstream PR InsightSoftwareConsortium/ITK#6580, which widens the loop bound to ImageDimension: every axis's separable pass now receives the same rank. Rewrote the two tests that exploited the old forced-median default as a backdoor to pin the median tie-break convention (they now pass rank=0.5 explicitly instead), and renamed/rederived the two tests that pinned the bug itself (fast_approximate_rank_1d_honors_the_requested_rank, fast_approximate_rank_applies_rank_uniformly_to_every_axis_2d) to assert the corrected separable-max result instead of the old forced-median one.
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.
Addresses item B18 of #6575.
FastApproximateRankImageFilteris a separable mini-pipeline of one per-axisRankImageFilterper image dimension. ItsSetRank()forwards the caller's rank to only the firstImageDimension - 1sub-filters:so the last axis always runs at the sub-filter default of 0.5 — a median — regardless of the requested rank, and for 1-D images the loop body never runs at all.
GetRank()still reports the requested value, so the mismatch is silent. The fix is the loop bound:ImageDimension - 1→ImageDimension(MiniPipelineSeparableImageFilterholds exactlyImageDimensionsub-filters, one per axis).The new regression test isolates the last axis: a 7×7 image constant along axis 0 and strictly increasing along axis 1, radius (1, 1), rank 0.02. The axis-0 pass is an identity on constant data, so the axis-1 (last-axis) pass is the discriminator: per
RankHistogram's selection rule (target = rank * (entries - 1) + 1), rank 0.02 over a 3-sample window selects the minimum while the default 0.5 selects the median. Interior pixels must equal the window minimum100·y; unfixed, they come out as the median100·(y+1).Verified locally (Linux, GCC 13, Release): the new test fails on unmodified
main(interior pixels 200, expected 100 — the last axis still ran at rank 0.5) and passes with the fix; the full ITKReview suite plus the ITKImageStatistics, ITKLabelVoting, ITKDisplacementField, and ITKRegionGrowing suites pass with the fix applied.PR Checklist
AI assistance