使用Scipy应用Sobel滤波器

11

我正在尝试使用scipy对图像应用Sobel滤波器以便检测边缘。我正在使用Python 3.2(64位)和Windows 7 Ultimate(64位)中的scipy 0.9.0。目前我的代码如下:

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过滤后(sobel.jpg): http://s2.postimage.org/64qajpdlb/sobel.jpg

期望输出: http://s1.postimage.org/5vexz7kdr/normal_sobel.jpg

我显然做错了什么! 有人能告诉我哪里出了问题吗?谢谢。


链接已失效 :( - jtlz2
3个回答

32

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)

1
是的,我需要沿着0轴(dx)的导数。实际上,我正在尝试实现Canny边缘检测器,并且在使用Sobel算子计算梯度时遇到了问题。非常感谢!我需要更改精度。 - Feanor
1
当我在使用skimage过滤器时,将数据类型从uint8更改为float对我很有帮助。 - wronk

9

我无法对cgohlke的回答进行评论,因此我重复了他的回答并进行了更正。参数0用于垂直导数,而参数1用于水平导数(图像数组的第一个轴是y/垂直方向-行,第二个轴是x/水平方向-列)。只是想提醒其他用户,因为我花了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
简而言之,梯度垂直于边缘,水平导数检测垂直边缘。 - dtk

1
或者你可以使用:

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

更多信息请查看这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接