Skip to content

A ND Sobel implementation is needed. #5702

@hjmjohnson

Description

@hjmjohnson

As identified in:

Description

The sobel operator is only supported in 2D.

Expected behavior

Sobel should provide an ND implementation.

Actual behavior

Compiler failures when instantiating N ! in [2,3]

Additional Information

AI Generated guess "write a c++ function that creates the n dimensional Sobel kernels?"

#include <vector>
#include <cstddef>
#include <stdexcept>

// Create N-dimensional Sobel kernels (one per axis).
// Each kernel is size 3^N, stored in row-major order with the last dimension varying fastest.
// 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)
{
    if (N == 0) {
        throw std::invalid_argument("Sobel kernels: N must be >= 1");
    }

    constexpr int d[3] = {-1, 0, 1};
    constexpr int s[3] = { 1, 2, 1};

    // total size = 3^N
    std::size_t total = 1;
    for (std::size_t i = 0; i < N; ++i) total *= 3;

    // 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;
    }

    // Allocate one kernel per axis
    std::vector<std::vector<int>> kernels(N, std::vector<int>(total, 0));

    // Iterate over all N-D indices in {0,1,2}^N (mapping to {-1,0,1})
    std::vector<int> idx(N, 0);
    for (std::size_t linear = 0; linear < total; ++linear)
    {
        // Convert linear index -> base-3 digits (idx[0..N-1])
        std::size_t t = linear;
        for (std::size_t j = 0; j < N; ++j) {
            idx[N - 1 - j] = static_cast<int>(t % 3);
            t /= 3;
        }

        // For each axis, compute Sobel value at this point
        for (std::size_t axis = 0; axis < N; ++axis)
        {
            int val = d[idx[axis]];
            if (val == 0) { // derivative center => whole product is 0
                kernels[axis][linear] = 0;
                continue;
            }

            for (std::size_t j = 0; j < N; ++j) {
                if (j == axis) continue;
                val *= s[idx[j]];
            }
            kernels[axis][linear] = val;
        }
    }

    return kernels;
}

Metadata

Metadata

Assignees

Labels

type:EnhancementImprovement of existing methods or implementation

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions