C 语言的 Canny 边缘检测器

发布于 2024-08-04 01:11:52 字数 383 浏览 6 评论 0原文

我正在寻找有关 Canny 边缘检测中算法如何实现的一些说明 - 维基百科条目 - 工作。使用 2D 高斯滤波器执行降噪似乎非常简单,但我听说使用两个 1D 滤波器 - 这是如何实现的?计算梯度和边缘方向也很简单。然而,在执行非极大值抑制时,是否有一个巧妙的技巧来获得圆角?我目前正在做的是将边缘方向 (theta) 值除以 pi/4,将其转换为整数并使用 switch 语句。但是,如何处理负 theta 值 - 即 -pi/4 应该以与 3*pi/4 相同的方式处理还是与 pi/4 相同的方式处理?

非常感谢任何建议/链接!

谢谢, 本

I am looking for a bit of clarification on how the algorithms implemented in Canny edge detection - Wikipedia entry - work. It seems pretty straightforward to perform noise reduction using a 2D Gaussian filter, but I have heard that using two 1D filters - how is this accomplished? It's also simple to calculate the gradient and edge direction. However, when performing non-maximum suppression is there a neat trick to getting the rounded angle? What I'm currently doing is dividing the edge direction (theta) value by pi/4, casting it to an integer and using a switch statement. But, how does one handle the negative theta values - ie should -pi/4 be handled the same way as 3*pi/4 or the same as pi/4?

Any advice/links are much appreciated!

Thanks,
Ben

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一江春梦 2024-08-11 01:11:52

高斯分布

[为简单起见,省略了常数]

g2d(x,y)=exp(-xxyy)=exp(-x^2) * exp(- y^2)=g1d(x) * g1d(y)

因此可以分解为一维分布的乘法。因此,可以首先在 x 方向(每行独立)然后在 y 方向(每列独立)进行过滤

圆角

如果角度超出 [0..pi)在这种情况下,根据需要多次加/减 pi(或使用函数 fmod)是正确的,对于 [0..pi) 一切都很清楚。

另外,根据平台的不同,最好完全避免使用反正切:您可以画一个圆,将其分为 4 个区域,并为仅使用算术运算的梯度分量生成一组条件,并给出区域方向的答案。

Gauss distribution:

[constants are omitted for simplicity]

g2d(x,y)=exp(-xx-yy)=exp(-x^2) * exp(-y^2)=g1d(x) * g1d(y)

Thus is can be separated into multiplication of 1d-distributions. And thus filtration can be done first in x-direction (independently on each row) and then in y-direction (independently on each column)

rounded angle:

If angle is outside of [0..pi) it's correct in this case to add/subtract pi as many times as needed (or use function fmod), and for [0..pi) all is clear.

Also depending on platform it may be better to avoid arctan usage at all: you can draw a circle, divide it in 4 areas and produce a set of conditions for gradient components which use only arithmetic operations and give you answer in which area direction is.

踏月而来 2024-08-11 01:11:52

您必须自己实现还是可以使用库? OpenCv 是一个巨大的计算机视觉 C 算法库,包括边缘检测:http ://opencv.willowgarage.com/documentation/image_processing.html?highlight=canny#cvCanny

如果您出于教育目的而这样做,我建议考虑购买有关计算机视觉的优秀书籍。几乎所有介绍性文本都会讨论高斯滤波(以及有据可查的一维技巧)以及精明的边缘检测和非极大值抑制。

Do you have to implement it yourself or can you use a library? OpenCv is a huge C library of algorithms in computer vision including edge detection: http://opencv.willowgarage.com/documentation/image_processing.html?highlight=canny#cvCanny .

If you are doing it for educational purposes, I suggest considering the purchase of a good text on computer vision. Almost any introductory text will discuss filtering with the Gaussian (and the well documented 1d trick) as well as canny edge detection and non-maximum suppression.

血之狂魔 2024-08-11 01:11:52

我认为 -pi/4 应该以与 3*pi/4 相同的方式处理,因为两者都定义相同的对角线。

如果您可以标准化渐变的角度,使其位于 [0, pi) 范围内,那么您可以使用如下所示的简单函数来量化角度:

enum Angle
{
    HORIZONTAL,
    DIAG_UP,
    VERTICAL,
    DIAG_DOWN
};

Angle quantizeAngle(double theta)
{
    if (0 <= theta && theta < PI/8.0) || (7.0*PI/8.0 <= theta && theta < PI))
        return HORIZONTAL;
    else if (PI/8.0 <= theta && theta < 3.0*PI/8.0)
        return DIAG_UP;
    else if (3.0*PI/8.0 <= theta && theta < 5.0*PI/8.0)
        return VERTICAL;
    else 
        return DIAG_DOWN;
}

I think that -pi/4 should be handled the same way as 3*pi/4, because both define the same diagonal.

If you can normalize the angle of the gradient so that it lies in [0, pi), then you could use a simple function like the following to quantize the angle:

enum Angle
{
    HORIZONTAL,
    DIAG_UP,
    VERTICAL,
    DIAG_DOWN
};

Angle quantizeAngle(double theta)
{
    if (0 <= theta && theta < PI/8.0) || (7.0*PI/8.0 <= theta && theta < PI))
        return HORIZONTAL;
    else if (PI/8.0 <= theta && theta < 3.0*PI/8.0)
        return DIAG_UP;
    else if (3.0*PI/8.0 <= theta && theta < 5.0*PI/8.0)
        return VERTICAL;
    else 
        return DIAG_DOWN;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文