【问题标题】:What are the units and limits of gradient magnitude?梯度大小的单位和界限是什么?
【发布时间】:2017-10-20 06:46:00
【问题描述】:

图像梯度幅度的单位和限制是什么?例如,我知道如何获得图像的梯度幅度(见下文)。生成的Mat 将包含我的源图像中每个边缘的边缘强度(大小)。

但是“边缘强度/大小”的单位是什么?梯度方向以度/弧度为单位,幅度的单位是什么? OpenCV 中 Magnitude 的限制是什么?它是 0 到 1,即边缘的强度/大小介于 0 和 1 之间,其中 1 是完全垂直的?

因此,如果我要在直方图中绘制幅度; x 轴表示边缘强度/陡峭度,y naxis 表示具有该强度/陡峭度的像素数?我说的对吗?

Mat sX, sY, mag;
Sobel(src, sX, CV_32F, 1, 0, 1);
Sobel(src, sY, CV_32F, 0, 1, 1);

magnitude(sX, sY, mag);

// So mag now contains the image gradient magnitude 
// of the all the edges I pulled out by sobel.
// What are the units and limits of 'edge strength'/magnitude?
// For example are the limits 0 to 1?

【问题讨论】:

    标签: c++ opencv computer-vision


    【解决方案1】:

    单位

    您正在对函数进行一些近似导数。如果函数是f(x),那么请记住,您正在查看f 中的change,而不是x 中的change。假设函数是基于时间的位置r(t),那么导数的单位是位置差(距离)与时间差(时间)。那么图像的单位是什么?嗯,它们是某些位置的光度值。光度值的变化只是光度值,位置的变化是距离。所以导数的单位是光度/距离。

    梯度幅度

    由于我们处理的是图像,因此最小距离是一个像素,而最大的变化可能是从白色到黑色(反之亦然),因此它们对应于最大的渐变。但 Sobel 可以处理最小值和最大值可能远远超出 0 到 1 或 0 到 255 的任意矩阵。

    请注意,您可能会得到斜率的负值:以像素为单位的距离始终为正,但从白色到黑色以及从黑色到白色的变化具有相反的符号。在 Sobel 计算出这些导数之后,您将分别计算 magnitudeangle。您可以根据每个方向的梯度强度对xy方向进行加权来计算角度,并且它需要符号返回0到360之间的任意角度。

    如果您想要所有边的大小为正值,而非边的大小为 0,您可以采用 L1-norm,即abs(x) + abs(y),或采用 EuclideanL2-normthe magnitude functionsqrt(G(x)^2 + G(y)^2),就像您要计算三角形的斜边一样。直接添加意味着一些渐变是正的,一些是负的,给你留下一个显示黑白边缘的灰色图像。

    Sobel 算子的值

    Sobel 算子只是计算像素邻域中的导数,不仅比较两个像素,而是比较六个像素,然后对它们进行加权,将它们全部相加——因此它可能比图像中的值高一点。而且,浮点图像不会在 0 或 1 处被截断,因此您可以发送具有更大值的图像并获得更大的值。除了数据类型可以容纳的最大值之外,运算符没有虚拟最大值。 Sobel 算子在梯度计算之前也会做一些平滑以去除小边缘,但平滑算子不会缩放值。

    OpenCV docs for Sobel 显示操作员将图像乘以的值。具体来说,对于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 将是最小值。

    编辑:正如another answer 中提到的这个问题,我们实际上不能同时在 X 和 Y 方向上达到最大值,如果你计算出最大值实际上可以是多少,它最终会更小一些:

    sqrt(20) * (M - n)
    

    因此,您可以将梯度标准化为具体介于 0 和 1 w.r.t 之间。您的图像类型除以最大值。这将允许您比较多个图像的边缘强度。

    或者您可以只使用normalize 函数,但最终值将取决于您的图像,因此您无法比较图像之间的相等值。

    【讨论】:

    • 关于限制:您是否处理过大小为 sqrt(gx^2+gy^2) 的问题?
    • 本教程只计算一个近似值,函数 cv::magnitude 应该总是计算欧几里得范数。
    • @Micka 不知何故我忘记了Sobel() 不返回幅度而只计算梯度的事实;我最初在想Canny(),它将返回幅度。哎呀。谢谢你。
    • 那么最小值将是一个复数?
    • @JoãoPaulo 我不知道我怎么错过了这么久,但你是完全正确的——我(终于)修复了这个错误。
    【解决方案2】:

    最大梯度幅度
    我很难同意上面的答案。请注意,对于中心像素 X 及其 3✕3 个相邻像素,它不能同时获取最大水平和垂直梯度,因此对于 8 位系统,Sobel 滤波器可以实现的最大梯度应该是sqrt(20)*(M-m) ,其中Mm 与接受的答案中定义的相同。邻里结构为[m M M; m X M; m m M]

    【讨论】:

      猜你喜欢
      • 2013-11-17
      • 2020-02-10
      • 2016-06-23
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      相关资源
      最近更新 更多