BUG: Fix boundary propagation, topology labeling and zero speed in FastMarchingImageFilterBase#6613
Conversation
|
| Filename | Overview |
|---|---|
| Modules/Filtering/FastMarching/include/itkFastMarchingImageFilterBase.h | Adds the next connected-component label counter used by the topology-labeling update. |
| Modules/Filtering/FastMarching/include/itkFastMarchingImageFilterBase.hxx | Fixes neighbor bounds, topology component labeling, iterator recentering, and zero-speed handling; near-zero speed handling still needs adjustment. |
| Modules/Filtering/FastMarching/itk-module.cmake | Adds ITKGoogleTest as a test dependency. |
| Modules/Filtering/FastMarching/test/CMakeLists.txt | Registers the new FastMarching GoogleTest driver. |
| Modules/Filtering/FastMarching/test/itkFastMarchingImageFilterBaseGTest.cxx | Adds regression tests for boundary propagation, NoHandles labeling, and zero-speed pixels. |
Reviews (1): Last reviewed commit: "BUG: Return large value for zero-speed n..." | Re-trigger Greptile
ff7a73d to
c32872d
Compare
|
Force-push |
|
Pushed ce821ed (maintainer edit, plain fast-forward): addresses the greptile P1 plus findings from a deeper multi-agent review of the NoHandles labeling scheme. What changed and why
Local validation: all 53 FastMarching ctests pass, including the three zero-tolerance |
UpdateNeighbors bounds-checked v against start/last instead of the candidate neighbor index v+s, and left the neighbor index at the center node when out of bounds instead of skipping that direction, so a seed on the last valid index never visited its +1 neighbor. Addresses item B36 of InsightSoftwareConsortium#6575.
CheckTopology only assigned a connected-component label to nodes that triggered a handle merge. Ordinary alive nodes kept label 0, so later merges compared unset labels as equal and were rejected as false handle violations. The merge-relabel scan also left the connected-component iterator past the end of the image; the label lookup right after it then read out of bounds. Addresses item B37 of InsightSoftwareConsortium#6575.
ce821ed to
09b68ce
Compare
Solve nudged a near-zero speed cc away from zero with itk::Math::eps before inverting it, so cc==0 still divided to a finite value rather than an unreachable arrival time. Return the large-value sentinel directly instead of leaning on divide-by-zero/inf propagation. Addresses item B38 of InsightSoftwareConsortium#6575.
Address code-review findings on the NoHandles labeling scheme: - Merge every distinct neighbor component label when a node joins fronts, including perpendicular-axis joins that raise no strict topology violation; previously such joins left the components with distinct labels, so a later reconnection closed an undetected handle. - Check all dimensions for opposite same-component neighbors instead of stopping at the first both-sides-Alive axis. - Read face-neighbor labels with GetPixel and relabel with ImageRegionIterator instead of constructing two radius-1 NeighborhoodIterators per accepted node. - Return unreachable for near-zero speeds whose reciprocal overflows. - Cast RelabelComponentImageFilter object count to the label type. - Add a GoogleTest that fronts wrapping a zero-speed obstacle may not close the ring into a handle.
|
First force-push = plain rebase on main; second = review fixes only, folded into the zero-speed commit: Review notes for the author (design-level, not acted on)
|
09b68ce to
3d1c79c
Compare
1a57db5
into
InsightSoftwareConsortium:main
Three defects in
FastMarchingImageFilterBase: boundary seeds never propagate in the+1direction, alive nodes are left unlabeled under theNoHandlestopology check, and a zero-speed node yields a finite arrival time. Addresses B36, B37 and B38 of #6575.B36 — boundary seeds do not propagate along both axis directions
UpdateNeighbors()bounds-checked the center indexvagainststart/lastinstead of the candidate neighborv + s, and on failure leftneighIndex[j]at the center value instead of skipping that direction. A seed placed at the last valid index along an axis therefore re-visited itself rather than its-1neighbor, and never visited its+1neighbor at all — that half of the axis stayed at the large-value sentinel.B37 — alive nodes carry no connected-component label
CheckTopology()assigned a connected-component label only to nodes that triggered a handle merge. Every other alive node kept label0, so a later merge comparing two unlabeled components saw0 == 0, concluded they were already the same component, and rejected the merge as a false handle violation.Every alive node now takes the label of an alive neighbour, or a fresh label from
m_NextConnectedComponentLabel(seeded inInitializeOutput()fromrelabeler->GetNumberOfObjects() + 1).The merge-relabel scan also walks the connected-component iterator to the end of the image; the label lookup that follows then read past the buffer. Re-centering
ItConiNodecloses that.B38 — zero speed yields a finite arrival time
Solve()nudged a near-zero speed away from zero withitk::Math::epsbefore inverting, so an exactly-zero speed produced a large-but-finite value that downstream comparisons treat as reachable. It now returns the large-value sentinel directly.Local validation
New GoogleTest
itkFastMarchingImageFilterBaseGTest.cxxin a newITKFastMarchingGTestsdriver, one test per item, each verified to fail onorigin/mainand pass with its fix:CornerSeedPropagatesAlongBothBoundaryAxes— fail-before3.40282347e+38vs expected100; pass-after.AliveNodesAreLabeledUnderNoHandlesTopologyCheck— fail-before; pass-after.ZeroSpeedNodeIsUnreachable— fail-before; pass-after.All 12 existing FastMarching ExternalData baseline tests (including
wm_multipleSeeds_NoHandlesTopo) pass atImageError = 0at each of the three commits. The out-of-bounds read in B37 was found by exactly that suite — it reproduced as a segfault on the 256x300x256 baseline while the small unit test passed.AI assistance