cucim icon indicating copy to clipboard operation
cucim copied to clipboard

[FEA] Add an interface equivalent to OpenCV's Sobel

Open grlee77 opened this issue 2 years ago • 0 comments

We have a sobel filter, but it is only for the common case of first order 3x3 kernels. I had a request to provide an equivalent to OpenCV's Sobel which also supports larger kernel sizes (as well as order > 1).

We already have the underlying CUDA convolution kernels, so we mainly just need an interface to generate the appropriate kernels and call our existing convolution functions.

The following python function should generate the equivalent kernels to the ones provided in OpenCV (reference)

def get_sobel_kernel(ksize, order):
    # Note: OpenCV docs refer to a max size of 7 but any
    #       odd size seems to work in practice.
    if ksize % 2 ~= 1:
        raise ValueError("ksize must be odd")

    if ksize <= 0:
        # docs say ksize = -1 for this CV_Scharr case, but in
        # practice any nonpositive ksize gives the Scharr kernel
        if order == 0:
            k = np.array([3, 10, 3])
        elif order == 1:
            k = np.array([-1, 0, 1])
        else:
            raise ValueError("order must be < ksize")
    if ksize == 1:
        # Case without any smoothing
        if order == 0:
            k = np.array([1])
        elif order == 1:
            k = np.array([-1, 0, 1])
        else:
            raise ValueError("order must be < ksize")
    elif order >= ksize:
        raise ValueError("order must be < ksize")
    elif ksize == 3:
        if order == 0:
            k = np.array([1, 2, 1])
        elif order == 1:
            k = np.array([-1, 0, 1])
        else:
            k = np.array([1, -2, 1])
    else:
        k = np.zeros(ksize + 1)
        k[0] = 1
        for i in range(ksize - order - 1):
            oldval = k[0]
            for j in range(1, ksize + 1):
                newval = k[j] + k[j - 1]
                k[j - 1] = oldval
                oldval = newval
        for i in range(order):
            oldval = -k[0]
            for j in range(1, ksize + 1):
                newval = k[j - 1] - k[j]
                k[j - 1] = oldval
                oldval = newval
        k = k[:-1]
    return k

grlee77 avatar Jul 27 '22 14:07 grlee77