【问题标题】:What is the Sobel operator?什么是 Sobel 算子?
【发布时间】:2021-08-31 08:53:05
【问题描述】:

我在 Python 中尝试了 5 种不同的 Sobel 运算符实现,其中一种是我自己实现的,结果根本不同。

我的问题类似于this one,但与其他实现仍有一些我不明白的区别。

Sobel算子的定义是否有一致的定义,它是否总是“图像梯度”的同义词?

即使 Sobel 内核的定义因源而异,根据 Wikipedia 是 [[1, 0, -1],[2, 0, -2],[1, 0, -1]],但根据其他来源是 [[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]]

这是我尝试不同技术的代码:

from scipy import ndimage
import numpy as np
import cv2 as cv
from scipy import ndimage
from PIL import Image, ImageFilter

img = np.random.randint(0, 255, [10, 10]).astype(np.uint8)

def sobel_x(img) :
    return ndimage.convolve(img, np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]]))

my_sobel = sobel_x(img)
_, numpy_sobel = np.gradient(img)
opencv_sobel = cv.Sobel(img, cv.CV_8UC1, 1, 0)
ndimage_sobel = ndimage.sobel(img, axis=0, mode="constant")
pil_sobel = np.array(Image.fromarray(img).filter(ImageFilter.Kernel((3, 3), (-1, 0, 1, -2, 0, 2, -1, 0, 1), 1, 0)))

print(my_sobel)
print(numpy_sobel)
print(opencv_sobel)
print(ndimage_sobel)
print(pil_sobel)

【问题讨论】:

  • 你可以看看this 了解sobel是如何在opencv中实现的

标签: python opencv image-processing filtering derivative


【解决方案1】:

Sobel 算子估计导数。

Sobel算子估计水平导数的正确定义是:

  | 1  0 -1 |
  | 2  0 -2 | / 8
  | 1  0 -1 |

除以 8 对获得正确的幅度很重要。人们经常忽略它,因为他们不关心实际的导数,他们关心的是比较同一图像不同位置的梯度。将所有内容乘以 8 没有任何区别,因此省略 /8 可以让事情变得简单。

您会在某些地方看到用反号定义的内核。这些是通过相关而不是卷积来应用内核的情况(通过内核的镜像而不同),例如 OpenCV 的情况。这些也可能是人们在不理解的情况下复制内容,从而导致带有错误符号的渐变。

但话又说回来,Sobel算子主要用于获得梯度幅度(水平和垂直导数的平方和的平方根)。在这种情况下,反转符号就不再重要了。


请注意,np.gradient(img) 相当于与 [1,0,-1]/2 进行卷积。这是估计导数的另一种方法。 Sobel 在垂直方向添加了正则化(==平滑)。


如果您使用更有意义的测试图像,您将更好地理解每个实现。例如,尝试一个黑色图像,中间有一个白色方块。您将能够比较估计梯度的强度、方向(我假设某些库使用不同的 x 和 y 轴定义),并且您将能够看到正则化的效果。

【讨论】:

    【解决方案2】:

    根据维基百科它是 [[1, 0, -1],[2, 0, -2],[1, 0, 1]] 但根据其他来源它是 [[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]]

    两者都用于检测垂直边缘。这里的区别在于这些内核如何标记“左”和“右”边缘。

    为简单起见,让我们考虑一维示例,并让数组为

    [0, 0, 255, 255, 255]

    那么如果我们使用填充计算那么

    • 内核[2, 0, -2] 提供[0, -510, -510, 0, 0]
    • 内核[-2, 0, 2] 提供[0, 510, 510, 0, 0]

    如您所见,值的突然增加被第一个内核标记为 negative 值,第二个内核标记为 positive 值。请注意,仅当您需要区分左右边缘时才相关,当您只想找到垂直边缘时,您可以使用上述两种方法中的任何一种,然后获取绝对值。

    【讨论】:

      猜你喜欢
      • 2019-12-04
      • 2013-06-09
      • 2023-04-03
      • 2018-01-31
      • 2017-06-21
      • 2022-01-23
      • 2012-09-14
      • 2018-01-16
      • 2014-04-18
      相关资源
      最近更新 更多