使用MATLAB中的imgradient时,如何解释梯度的方向?

7
我正在寻找一张图像的梯度。目前,我只是使用一个5 x 5的图像。我更感兴趣的是找到梯度的方向,但手动计算结果与使用MATLAB函数imgradient得到的结果不同。请参考以下图片了解更多关于输入图片和用于查找图像梯度的Sobel滤波器的信息。这里使用的3 x 3 Sobel运算符之一是我使用该函数得到的运算符。
f1 = fspecial('sobel');

另一个是通过转置f1得到的。

请注意,我在这里只试图找到由红色圆形包围的一个像素的方向。在前两种情况下,我的结果与使用imgradient函数获得的结果匹配,但在第三种情况下,imgradient给出了-135度,而我得到的是-45度。请帮助我找到错误。

Case one and case two

Case three (Mismatch in results)

同时请解释如何将以下梯度方向解释为下图所示。

enter image description here

1个回答

6
你的计算是正确的,但强烈建议你不要使用atan(y/x)的定义,因为这种计算不知道梯度角所在的象限。对于你的分量进行atan(y/x)会错误地报告角度为-45度,而这并不正确。相反,你应该使用atan2。
现在,imgradient的内部非常直接。我想指出的是,imgradient报告的角度假定y坐标从下到上递增。此外,imgradient应该报告指向最大变化率的方向的方向角。在图像的情况下,这指向我们从暗像素到亮像素的进展方向。
首先调用imgradientxy,如果你给imgradient提供sobel标志,则调用fspecial('sobel')。事实上,记住imgradientxy的这部分内容很重要(从第75行开始:MATLAB R2015a)。
case 'sobel'
    h = -fspecial('sobel'); %// Align mask correctly along the x- and y- axes
    Gx = imfilter(I,h','replicate'); %'
    if nargout > 1
        Gy = imfilter(I,h,'replicate');
    end

请注意,fspecial输出的负数会被执行,同时还提供了该行的注释。这是为了确保检测水平边缘的掩模(即Gy)是向下的(在计算机图形学中通常如此)。具体来说,图像的原点位于左上角而不是左下角。
以下是坐标系在y-down中的图示表示: 来源:维基百科 - 旋转矩阵 因此,在查找方向时,还有一个额外的要求,即梯度方向的角度是相对于我们习惯的y-up坐标系的。因此,在计算角度之前,需要对y坐标进行取反,以便角度符合标准约定。
寻找您所需的梯度定义是y坐标从底部到顶部增加的常规系统。需要进行取反操作,实际上,如果您检查imgradient的源代码,则会在代码的第127行(版本R2015a)执行此操作。
Gdir = atan2(-Gy,Gx)*180/pi; %// Radians to degrees

你可能会问为什么需要在找到方向后否定掩码并再次否定y坐标。原因是,修改后的掩码需要正确捕获梯度的大小,所以我们将掩码取反一次并找到梯度大小,然后否定y坐标,以便我们可以根据传统坐标系找到角度。
在你的情况下,假设Gx = 765Gy = -765,将这些值代入上述方程式得到:
>> Gy = 765;
>> Gx = -765;
>> Gdir = atan2(-Gy,Gx)*180/pi

Gdir =

  -135

这是有道理的,因为梯度方向对应着变化率最大的方向。-135度意味着我们指向西南方向,这很合理,因为我们正在从暗像素向亮像素前进。
现在,如果您查看第三个示例图像,imgradient 报告的角度确实是正确的。只需从暗区域到光区域绘制一条线,并查看它与 x 轴所成的角度,其中该轴与列向右增加对齐。第一个+90度的角度是合理的,因为我们正在从底部向上跟随暗区域和光区域。这类似于图像翻转的情况。第三种情况是我们之前见过的,第四种情况只是将第三种情况旋转了180度,因此从暗到光的方向角现在是+45度,而不是先前的-135度。

@NavdeepSony 没问题 :) 很高兴能帮到你。祝你好运! - rayryeng
我对Gdir感到困惑。我认为Gdir是最大强度变化的方向,而边缘始终垂直于它。我是正确的吗?当我使用gx=[-1 0 1; -2 0 2; -1 0 1]gy=[-1 -2 -1;0 0 0;1 2 1]时,所有答案都与imgradient匹配,但我无法解释结果。例如,对于情况1:我得到了Gdir = 90,这是一条位于y轴上(向下)的线,我认为这显示了强度变化。同样地,对于情况2:Gdir = -90,显示向上的强度变化,但在情况3中:Gdir = -135,这是边缘存在的角度。问题出在哪里? - Navdeep Sony
@NavdeepSony 我对 imgradient 进行了更深入的调查。我现在知道发生了什么。通过执行 atan2(-Gy,Gx),可以确保角度相对于 y 向上。我将不得不更改我的帖子,因为在 imgradient 中,他们确实使用了你指定的那些掩模,而这些掩模本身是 y 向下的。因此,-135 度的角度现在是有意义的,这使得梯度指向西南方向,并且这个方向指向最大变化率(即从黑色到白色)。我将更新我的帖子以反映这一点。 - rayryeng
非常感谢!这正是我想的!但我仍然无法理解为什么要这样做 h = -fspecial('sobel'); %// Align mask correctly along the x- and y- axes。你怎么知道它是“向下的”?如果我们使用 h = fspecial('sobel');,那么只使用 Gdir = atan2(Gy,Gx)*180/pi 而不是 Gdir = atan2(-Gy,Gx)*180/pi 是否可以? - Navdeep Sony
我只是检查了掩码,这就是我找出方向的方法。而且,你说的话很有道理。祝你好运! - rayryeng
你的意思是说因为我们从负值到正值移动(从第一行到第三行),所以我们可以说这是向下为 y 吗?还是其他什么原因。 - Navdeep Sony

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