Units
您正在获取函数的一些近似导数。如果函数是,比如说,f(x)
,然后记住你正在看的是change in f
超过change in x
。假设该函数是基于时间的位置r(t)
,那么导数的单位是位置(距离)差除以时间(时间)差。那么图像的单位是什么?嗯,它们是某些位置的亮度值。光度值的变化只是光度值,位置的变化是距离。所以导数的单位是光度/距离。
梯度幅值
由于我们正在处理图像,最小距离是一个像素,最大可能的变化是从白色到黑色(反之亦然),因此这些将与最大梯度相对应。但 Sobel 可以处理任意矩阵,其最小值和最大值可能远远超出 0 到 1 或 0 到 255 范围。
请注意,您可能会得到负的斜率值:以像素为单位的距离始终为正,但从白色到黑色以及从黑色到白色的变化具有相反的符号。索贝尔计算出这些导数后,您将计算震级分别从angle。您可以根据权重计算角度x
and y
方向由每个方向上的梯度强度决定,并且需要符号来返回 0 到 360 之间的任何角度。
如果您希望所有边缘的大小为正值,并且非边缘为 0,您可以采用L1-norm,即abs(x) + abs(y)
,或取欧几里得 or L2-norm with the magnitude功能这是sqrt(G(x)^2 + G(y)^2)
,就像计算三角形的斜边一样。直接添加意味着一些梯度为正,一些梯度为负,留下显示黑白边缘的灰色图像。
Sobel 算子的值
Sobel 运算符只是计算像素邻域的导数,不只是比较两个像素,而是比较六个像素,并对它们进行加权,将它们全部相加,因此它可能比图像中的值稍高一些。而且,浮点图像不会在 0 或 1 处被截断,因此您可以发送具有更大值的图像并获取更大的值。除了数据类型可以容纳的最大值之外,运算符没有虚拟最大值。 Sobel 算子还在梯度计算之前进行一些平滑处理以去除小边缘,但平滑算子不会缩放值。
OpenCV索贝尔的文档显示运算符与图像相乘的值。具体来说,对于x
方向,每个 3x3 像素邻域按元素乘以
-1 0 1
-2 0 2
-1 0 1
并总结。如果您的图像类型的最大可能值为M
最小值是m
那么梯度中最大的正值是
(1+2+1)*M - (1+2+1)*m = 4*M - 4*m
类似地,最大负值是
-(1+2+1)*M + (1+2+1)*m = -4*M + 4*m
这对于每个方向的梯度都是相同的。所以,每个方向上的梯度范围Sobel
将[-4M+4m, 4M-4m]
.
规范化操作员
您将使用 L1 范数或 L2 范数以某种方式将其中两个量值相加。假设您坚持使用 L2 范数,则组合幅度的最大值将简单地遵循 L2 范数定义,
MAX = sqrt((4*M - 4*m)**2 + (4*M - 4*m)**2)
= sqrt(2 * (4*M - 4*m)**2)
= sqrt(2 * 16 * (M - m)**2)
= sqrt(32) * (M - m)
由于 L1 或 L2 范数将正值和负值视为相等(重要的是它们与 0 的距离),因此 Sobel 算子中的最小值在组合幅度中给出与最大值相同的响应。当然,您的响应的某些点可能为 0,这会给出 Sobel 响应,因此总和幅度也为 0,因此 0 将是最小值。
编辑:如中所述另一个答案对于这个问题,我们实际上无法同时在 X 和 Y 方向上达到最大值,如果你计算出实际的最大值是多少,它最终会更小一些:
sqrt(20) * (M - n)
因此,您可以将梯度标准化为介于 0 和 1 之间。除以最大值即可确定图像类型。这将允许您比较多个图像的边缘强度。
或者你可以只使用normalize
函数,但最终值将取决于您的图像,因此您无法比较图像之间的相等值。