Сбой при реализации фильтра маски Собеля

#jupyter-notebook #scikit-image #noise #sobel

#jupyter-notebook #scikit-изображение #шум #собель

Вопрос:

Я пытаюсь создать маску Собеля на гауссовом зашумленном изображении в оттенках серого с использованием Python, но, похоже, она не обнаруживает края, как должно быть, и я не понимаю, что я делаю не так. Это мой код, в который я добавил все объявления переменных:

  # Import numpy, skimage and matplotlib
    import numpy as np
    from skimage import io,color
    import matplotlib.pyplot as plt
    
    # Image loading
    img = io.imread('lena.png')
    plt.figure(),plt.imshow(img),plt.title("Initial image")
    # Grayscale conversion
    img = color.rgb2gray(img)
    # Displaying the grayscale image
    # The grayscale image has values between 0 (black) and 1 (white). 
    plt.figure(),plt.imshow(img,cmap='gray', vmin = 0, vmax = 1),plt.title("Greyscale image")
    
    # convert the image to values between 0 (black) and 255 (white)
    img = img*255
    
    # generate the gaussian noise with mean = 0 and a given standard deviation 
    N = np.random.normal(0,30,img.shape)
    
    # add the noise to the image
    img_n = img   N
    
    # Show image with the Gaussian Noise
    plt.figure(),plt.imshow(img_n,cmap='gray', vmin = 0, vmax = 255),plt.title("Image with Gaussian Noise")
    size = img.shape
# define the 4 masks for the 4 differences between the pixels
mask_x = np.array([[0, 0, 0], [-1, 0, 1], [0, 0, 0] ])
mask_y = np.array([[0, -1, 0], [0, 0, 0], [0, 1, 0] ])
mask_45 = np.array([[-1, 0, 0], [0, 0, 0], [0, 0, 1] ])
mask_135 = np.array([[0, 0, -1], [0, 0, 0], [1, 0, 0] ])
    # for each pixel in the image
    for i in range(size[0]-2):
        for j in range(size[1]-2):
            # compute the result of the 4 differences (with the 4 linear filters)
            V = img[i:i 3,j:j 3]
            Vx = V * mask_x
            img_fx[i 1,j 1] = np.sum(Vx)
            Vy = V * mask_y
            img_fy[i 1,j 1] = np.sum(Vy)
            V45 = V * mask_45
            img_f45[i 1,j 1] = np.sum(V45)
            V135 = V * mask_135
            img_f135[i 1,j 1] = np.sum(V135)
            # take the one that gives the maximum absolute difference
            compass[i 1,j 1] = max([abs(img_fx[i 1,j 1]), abs(img_fy[i 1,j 1]), abs(img_f45[i 1,j 1]), abs(img_f135[i 1,j 1])  ])
    
    # visualize all of them        
    plt.figure(),plt.imshow(img,cmap='gray')
    plt.figure(),plt.imshow(img_fx,cmap='gray', vmin = -255, vmax = 255)
    plt.figure(),plt.imshow(img_fy,cmap='gray', vmin = -255, vmax = 255)
    plt.figure(),plt.imshow(img_f45,cmap='gray', vmin = -255, vmax = 255)
    plt.figure(),plt.imshow(img_f135,cmap='gray', vmin = -255, vmax = 255)
    plt.figure(),plt.imshow(compass,cmap='gray', vmin = 0, vmax = 255)
 

Ответ №1:

Я имею в виду, я не знаю точно, где ваш код идет не так, и это не фильтр Собеля, но вы делаете его намного сложнее, чем нужно. Вы должны использовать scipy.ndimage.correlate :

 import numpy as np
from scipy import ndimage as ndi


kernels = [
        np.array([[-1, 0, 1]]),
        np.array([[-1], [0], [1]]),
        np.array([[-1, 0, 0], [0, 0, 0], [0, 0, 1]]),
        np.array([[0, 0, -1], [0, 0, 0], [1, 0, 0]]),
]

filtered = [
        ndi.correlate(img, kernel)
        for kernel in kernels
]

compass = np.max(np.abs(filtered), axis=0)