Применение фильтра Sobel с использованием scipy

Я пытаюсь применить фильтр Sobel на изображении для обнаружения краев с помощью scipy. Я использую Python 3.2 (64 бит) и scipy 0.9.0 для Windows 7 Ultimate (64 бит). В настоящее время мой код выглядит следующим образом:

import scipy
from scipy import ndimage

im = scipy.misc.imread('bike.jpg')
processed = ndimage.sobel(im, 0)
scipy.misc.imsave('sobel.jpg', processed)

Я не знаю, что я делаю неправильно, но обработанное изображение не похоже на то, что нужно. Изображение "bike.jpg" - это оттенок серого (режим "L" не "RGB" ), поэтому каждый пиксель имеет только одно значение, связанное с ним.

К сожалению, я не могу размещать изображения здесь (не хватает репутации), но я привел ссылки ниже:

Оригинальное изображение (bike.jpg): http://s2.postimage.org/64q8w613j/bike.jpg

Scipy Filtered (sobel.jpg): http://s2.postimage.org/64qajpdlb/sobel.jpg

Ожидаемый результат: http://s1.postimage.org/5vexz7kdr/normal_sobel.jpg

Я, очевидно, ошибаюсь где-то! Может кто-нибудь, пожалуйста, скажите мне, где. Спасибо.

Ответ 1

1) Используйте более высокую точность. 2) Вы вычисляете только аппроксимацию производной вдоль нулевой оси. Оператор 2D Sobel объясняется на Wikipedia. Попробуйте этот код:

import numpy
import scipy
from scipy import ndimage

im = scipy.misc.imread('bike.jpg')
im = im.astype('int32')
dx = ndimage.sobel(im, 0)  # horizontal derivative
dy = ndimage.sobel(im, 1)  # vertical derivative
mag = numpy.hypot(dx, dy)  # magnitude
mag *= 255.0 / numpy.max(mag)  # normalize (Q&D)
scipy.misc.imsave('sobel.jpg', mag)

Ответ 2

Я не мог комментировать ответ cgohlke, поэтому я повторил его ответ с помощью corrction. Параметр 0 используется для вертикальной производной и 1 для горизонтальной производной (первая ось массива изображений равна y/вертикальное направление - ряды, а вторая ось - х/горизонтальное направление - столбцы). Просто хотелось предупредить других пользователей, потому что я потерял 1 час, чтобы найти ошибку в неправильных местах.

import numpy
import scipy
from scipy import ndimage

im = scipy.misc.imread('bike.jpg')
im = im.astype('int32')
dx = ndimage.sobel(im, 1)  # horizontal derivative
dy = ndimage.sobel(im, 0)  # vertical derivative
mag = numpy.hypot(dx, dy)  # magnitude
mag *= 255.0 / numpy.max(mag)  # normalize (Q&D)
scipy.misc.imsave('sobel.jpg', mag)

Ответ 3

или вы можете использовать:

def sobel_filter(im, k_size):

    im = im.astype(np.float)
    width, height, c = im.shape
    if c > 1:
        img = 0.2126 * im[:,:,0] + 0.7152 * im[:,:,1] + 0.0722 * im[:,:,2]
    else:
        img = im

    assert(k_size == 3 or k_size == 5);

    if k_size == 3:
        kh = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype = np.float)
        kv = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]], dtype = np.float)
    else:
        kh = np.array([[-1, -2, 0, 2, 1], 
                   [-4, -8, 0, 8, 4], 
                   [-6, -12, 0, 12, 6],
                   [-4, -8, 0, 8, 4],
                   [-1, -2, 0, 2, 1]], dtype = np.float)
        kv = np.array([[1, 4, 6, 4, 1], 
                   [2, 8, 12, 8, 2],
                   [0, 0, 0, 0, 0], 
                   [-2, -8, -12, -8, -2],
                   [-1, -4, -6, -4, -1]], dtype = np.float)

    gx = signal.convolve2d(img, kh, mode='same', boundary = 'symm', fillvalue=0)
    gy = signal.convolve2d(img, kv, mode='same', boundary = 'symm', fillvalue=0)

    g = np.sqrt(gx * gx + gy * gy)
    g *= 255.0 / np.max(g)

    #plt.figure()
    #plt.imshow(g, cmap=plt.cm.gray)      

    return g

Подробнее см. здесь