Skip to content

Conversation

@N-Dekker
Copy link
Contributor

@N-Dekker N-Dekker commented Jan 6, 2026


👉 Work in progress: The code still needs to have a clean-up. Moreover, it should still be confirmed that this is indeed the proper way to estimate those coefficients! An authoritative literature reference would be helpful, as well as more evidence that these are indeed the more commonly used coefficients!

@github-actions github-actions bot added type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module area:Documentation Issues affecting the Documentation module labels Jan 6, 2026
Copy link
Member

@dzenanz dzenanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we have dimensionality constraints somewhere? If so, we should lift them as part of this PR. Also, we probably want to add unit tests for higher dimensions.

@N-Dekker
Copy link
Contributor Author

N-Dekker commented Jan 6, 2026

Did we have dimensionality constraints somewhere? If so, we should lift them as part of this PR. Also, we probably want to add unit tests for higher dimensions.

Thanks for the reminder 😺 We would also have to generalize its Fill(const CoefficientVector &) member function, which is now 2D and 3D only:

SobelOperator<TPixel, VDimension, TAllocator>::Fill(const CoefficientVector & coeff)

So you see, it's really WIP!

// Standard Sobel definition: derivative = [-1, 0, 1], smoothing = [1, 2, 1].
// Kernel for axis a is: K_a(x) = d[x_a] * Π_{j != a} s[x_j], with x_j ∈ {-1,0,1}.
inline std::vector<std::vector<int>>
make_nd_sobel_kernels(std::size_t N)
Copy link
Member

@hjmjohnson hjmjohnson Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this function were templated on N (aka VDimension), it could also be constexpr.

Then the test for N == 0 could also be a static assert instead of a runtime test.

Copy link
Contributor Author

@N-Dekker N-Dekker Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Hans! I just gave constexpr a try: WIP: Make make_nd_sobel_kernels constexpr (updated link)

Note that in this context, make_nd_sobel_kernels would just be an internal helper function of itk::SobelOperator<TPixel, VDimension, TAllocator>, so it already "knows" VDimension, and there is no need to pass it as parameter. VDimension can never be zero, so the assert isn't really necessary anyway.

Still: this is all WIP. Especially because I don't really understand the AI generated code, do you?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the mean time, I think I found an AI hallucination! Looking at the original AI generated code at #5702 (comment) This part appears useless:

    // Precompute strides for row-major flattening (last dim fastest)
    std::vector<std::size_t> stride(N, 1);
    for (std::size_t i = 1; i < N; ++i) {
        stride[N - 1 - i] = stride[N - i] * 3;
    }

The rest of the code does not make use of those strides! So it's unnecessary! I think I'll remove this part of code with the next force-push!

@N-Dekker N-Dekker force-pushed the Make-SobelOperator-3D-consistent branch 2 times, most recently from 54d23a1 to 730a117 Compare January 7, 2026 17:07
@N-Dekker
Copy link
Contributor Author

N-Dekker commented Jan 7, 2026

FYI My intention is to squash most of these WIP commits before making the PR ready for review. (But before doing so, the PR should also offer a backward compatible legacy option, at least for 3D.)

@N-Dekker
Copy link
Contributor Author

N-Dekker commented Jan 8, 2026

/azp run ITK.Linux.Python

@N-Dekker
Copy link
Contributor Author

N-Dekker commented Jan 8, 2026

/azp run ITK.Linux

Comment on lines +134 to +137
const auto & kernel = sobelKernels[VDimension - 1 - direction];
return CoefficientVector(kernel.cbegin(), kernel.cend());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply kernel = sobelKernels[direction]? I still don't understand why the kernels returned by the AI generated function from #5702 (comment) are in the reverse order, compared by ITK 🤷

Aims to make the 3D coefficients more consistent with its 2D version, paving
the way for an ND extension, as request by issue InsightSoftwareConsortium#5702

The new coefficients are more commonly used by other toolkits, including scipy,
and correspond with https://en.wikipedia.org/wiki/Sobel_operator

Removed the reference to "An Isotropic 3x3x3 Volume Gradient Operator", Sobel,
1995, as it cannot be found anymore.
Suggested by Hans Johnson.

Replaced `std::vector` with `std::array`, in order to allow compile-time evaluation.

Removed the check `if (N == 0)`, because it's not really a problem. For N == 0,
the function returns an empty array, which is theoretically OK. In practice,
VDimension is always greater than zero anyway.

Removed the computation of "strides", as they appear unused. Possibly introduced
by an AI hallucination...?

Declared the local `kernels` variable in GenerateCoefficients() `static constexpr`
to enforce that it is evaluated only once, during compilation.
Following C++ Core Guidelines, Jul 8, 2025, "Minimize the use of `break` and
`continue` in loops",
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#res-continue

Apparently, AI did not read the guidelines  ;-)
Using the type alias from "itkIntTypes.h"
The symbols for product and "element of" were originally generated by AI.
Was accidentally removed by commit "WIP: Use AI generated make_nd_sobel_kernels
in SobelOperator".

The itkExceptionMacro message is more informative than `std::out_of_range`
message from `std::array::at`.
Aims to address Darwin-Build12920 Python errors at
https://open.cdash.org/viewBuildError.php?buildid=10942920 saying:

    Wrapping/Typedefs/itkSobelOperator.i:53: Error: Syntax error in input(3).
Another attempt to address Darwin-Build12920 Python errors at
https://open.cdash.org/viewBuildError.php?buildid=10942920 saying:

    Wrapping/Typedefs/itkSobelOperator.i:53: Error: Syntax error in input(3).
Allows the user to specify whether or not SobelOperator::GenerateCoefficients()
returns uses the old (ITK <= 5.4) coefficients for a 3D kernel.

Enabled by default, unless `ITK_FUTURE_LEGACY_REMOVE` is ON.
@N-Dekker N-Dekker force-pushed the Make-SobelOperator-3D-consistent branch from 4c20b2c to a20d509 Compare January 8, 2026 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Core Issues affecting the Core module area:Documentation Issues affecting the Documentation module type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants