我正在研究标记检测算法并阅读本文,他们正在使用高斯核的一维导数来获得梯度。他们将屏幕分成一条相隔 5 像素的小扫描线,然后他们在水平和垂直方向上操作内核以计算梯度,我想知道它是如何做到的,即:
他们的操作是:
[ -3 -5 0 5 3] * A
我认为它是水平导数?
那么垂直的呢,只是像这样乘以转置的问题吗?
A * ([ -3 -5 0 5 3]^T)
对于另一侧来计算梯度方向,他们使用 3x3 Sobel 内核,但扫描线是 5x5,有人知道它是怎么做到的吗?
卷积
[-3 -5 0 5 3] * A
是实际导数的近似值。因为A
是采样的,所以我们无法知道真正的导数。我们需要一个离散近似。一种常见的方法是有限差分法,其中只需取后续元素之间的差:A[x+1,y]-A[x,y]
。这就是您在离散情况下填写导数极限方程时得到的结果。Lim h->0
变成h=1
,没有更小的间距。这种差异可以使用卷积来计算:
[1 -1] * A
此操作在两个像素之间的位置生成导数。为了克服这一点,可以使用中心区别:(A[x+1,y]-A[x-1,y])/2
,或卷积形式:
[1/2 0 -1/2] * A
通过与高斯的导数进行卷积可以获得进一步的改进。在平滑(正则化(滤波器方面,高斯是某种最佳的。此外,卷积具有以下属性:d/dx (A * G) = A * d/dx G
。也就是说,将图像与高斯的导数卷积与由高斯平滑的图像的真实导数相同。你可以写这样的一维卷积:
[0.013 0.108 0.242 0.0 -0.242 -0.108 -0.013] * A
请注意,最好也用高斯卷积列,以保持各向同性。但是,让我们暂时忽略这一点。
出于某种原因,计算机视觉社区的人们似乎对浮点值过敏(最近这种情况正在改善很多,但总会有人认为用整数值计算卷积更便宜(。因此,似乎您链接的页面,他们用近似它的整数值内核替换了高斯核的实际导数。这导致[3 5 0 -5 -3]
.他们还设法反转了这些值,导致了一个近似-d/dx
的操作。
他们后来使用Gabor来确定方向进一步表明他们并不真正知道自己在做什么,因为Gabor对真实梯度的近似比高斯导数更差。
简而言之,如果要计算导数,请执行以下操作:
A * d/dx G(x) * G(y)
(G(x)
一维高斯作为x
的函数,即水平向量,并G(y)
其转置;直接d/dx G(x)
采样,而不是G(x)
采样并计算其有限差分导数(。
要沿y
轴计算导数,请执行相同的操作,但使用G(y)
内核的导数。
实用的实施建议取决于您的语言。以下是使用 MATLAB 时的一些建议。它可能也可以很好地翻译成其他语言。
关于5x5扫描线:我不知道这意味着什么。我认为他们以某种方式对图像进行子采样以提高性能。更少的像素 = 更快的计算速度。