fix(gabor): keep filter-response magnitudes real-valued, then vet GABOR vs scikit-image - #393
Open
darkclad wants to merge 1 commit into
Open
fix(gabor): keep filter-response magnitudes real-valued, then vet GABOR vs scikit-image#393darkclad wants to merge 1 commit into
darkclad wants to merge 1 commit into
Conversation
…OR vs scikit-image
The Gabor pipeline stored each filter-response magnitude in a PixIntens (unsigned int)
image and thresholded that, so sub-integer responses were floored to 0 -- e.g. several
ROIs reported GABOR = 0.0 at the higher frequencies where the true response is small but
nonzero. Keep the response real-valued end to end:
- CPU (gabor.cpp): GaborEnergy writes double; calculate() scores from a std::vector<double>
instead of a PixIntens ImageMatrix.
- non-trivial (gabor_nontriv.cpp): GaborEnergy_NT2 drops the (PixIntens) cast on the
magnitude. (Also flags a separate pre-existing bug: osized_calculate leaves originalScore
at 0, so the out-of-core baseline score is not wired in.)
- GPU (gabor.cu, cache.h/.cpp, gabor.cpp): the energy montage and host buffers become
real-valued -- RealPixIntens (float, 4 bytes like PixIntens, so device/host buffer sizes
are unchanged) for the device montage; double for the host scoring buffers.
Then VET GABOR vs scikit-image (was regression, flagged no-mainstream-oracle):
- Nyxus' Gabor kernel is the canonical Gabor filter: it equals skimage.filters.gabor_kernel
(frequency = f0/2pi, sigma_x = sig2lam*2pi/f0, sigma_y = sigma_x/gamma) to ~1e-18.
- An independent reimplementation of the L1-normalize / full-convolve / crop / score
pipeline reproduces all 16 golden values (4 DSB2018 ROIs x 4 frequencies) exactly.
- New generator tests/vetting/oracles/gen_gabor_skimage.py (offline; needs scikit-image).
gabor_truth updated to the corrected real-valued scores; the gtest is renamed
test_gabor_skimage. gabor 0/1 -> 1/1.
GPU build VERIFIED locally (CUDA 13.1, RTX 2070 SUPER / sm_75): the whole suite compiles and
runaAllTests runs. Fixing the truncation surfaced two pre-existing, independent issues in the
GPU gabor path that this commit works around minimally rather than fixing:
- tests/test_gabor_regression.cc called calculate_gpu_multi_filter with the wrong arg count
(never compiled under USEGPU=OFF); switched to the 1-arg calculate_gpu.
- the GPU gabor result (FFT convolution) diverges from the direct-convolution CPU path on
these ROIs, so the skimage-vetted value assertions run for the CPU path only; the GPU
branch just verifies the kernels compile and run. (Also note: tests/CMakeLists.txt uses
the stale CUDA_INCLUDE_DIRS instead of CUDAToolkit_INCLUDE_DIRS, so a USEGPU gtest build
needs -DCUDA_INCLUDE_DIRS set until that is corrected.)
gtest 717/717 (CPU and GPU builds); pytest 72 passed (7 arrow fails are the tiff-only local
build; the pytest gabor tests exercise parameter plumbing / CPU-GPU consistency, not feature
values). Coverage 604 -> 605 / 758.
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.
The Gabor pipeline stored each filter-response magnitude in a PixIntens (unsigned int) image and thresholded that, so sub-integer responses were floored to 0 -- e.g. several ROIs reported GABOR = 0.0 at the higher frequencies where the true response is small but nonzero. Keep the response real-valued end to end:
instead of a PixIntens ImageMatrix.
Then VET GABOR vs scikit-image (was regression, flagged no-mainstream-oracle):
gtest 717/717; pytest 72 passed (7 arrow fails are the tiff-only local build; the pytest gabor tests exercise parameter plumbing / CPU-GPU consistency, not feature values). Coverage 604 -> 605 / 758.