图像边缘检测非极大值抑制求解释

m104130232 2011-06-09 12:00:05
请看这段代码
// 如果当前象素的梯度幅度为 0,则不是边界点
if(pnMag[nPos] == 0 )
{
pUncheckRst[nPos] = 0 ;
}
else
{
dTmp = pnMag[nPos] ;
gx = pnGradX[nPos] ; // 水平方向偏导数
gy = pnGradY[nPos] ; // 垂直方向偏导数
if (abs(gy) > abs(gx))
{
weight = fabs(gx)/fabs(gy); // 计算插值的比例
g2 = pnMag[nPos-imageWidth] ;
g4 = pnMag[nPos+imageWidth] ;
// 如果两个方向的偏导数的符号相同
// C 是当前象素,与 g1-g4 的位置关系为:
// g1 g2
// C
// g4 g3
if (gx*gy > 0)
{
g1 = pnMag[nPos-imageWidth-1] ;
g3 = pnMag[nPos+imageWidth+1] ;
}
// 如果两个方向的偏导数的符号相反
// C 是当前象素,与 g1-g4 的位置关系为:
// g2 g1
// C
// g3 g4
else
{
g1 = pnMag[nPos-imageWidth+1] ;
g3 = pnMag[nPos+imageWidth-1] ;
}
}
else
{
weight = fabs(gy)/fabs(gx);
g2 = pnMag[nPos+1] ;
g4 = pnMag[nPos-1] ;
// 如果两个方向的偏导数的符号相同
// C 是当前象素,与 g1-g4 的位置关系为:
// g3
// g4 C g2
// g1
if (gx*gy > 0)
{
g1 = pnMag[nPos+imageWidth+1] ;
g3 = pnMag[nPos-imageWidth-1] ;
}
// 如果两个方向的偏导数的符号相反
// C 是当前象素,与 g1-g4 的位置关系为:
// g1
// g4 C g2
// g3
else
{
g1 = pnMag[nPos-imageWidth+1] ;
g3 = pnMag[nPos+imageWidth-1] ;
}
}
// 下面利用 g1-g4 对梯度进行插值
{
dTmp1 = weight*g1 + (1-weight)*g2 ;
dTmp2 = weight*g3 + (1-weight)*g4 ;
// 当前象素的梯度是局部的最大值
// 该点可能是个边界点
if(dTmp>=dTmp1 && dTmp>=dTmp2)
{
pUncheckRst[nPos] = 128 ;
}
else
{
// 不可能是边界点
pUncheckRst[nPos] = 0 ;
}
}
}
}
}
}
小弟有以下几个问题:(1) 插值是何意?为啥取g1,g2为一组,g3,g4为一组计算插值?
(2) 原理上是比较3*3矩阵内相邻像素点是不是最大值,他为何比较g1,g2,g3,g4就完事了
(3) 为何要分X,Y方向导数谁大两种情况比较
...全文
3780 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
snoopy4243 2013-04-02
  • 打赏
  • 举报
回复
引用 4 楼 laodizhi8757 的回复:
代码部分有个错误 if(dTmp>=dTmp1 && dTmp>=dTmp2) { pUncheckRst[nPos] = 128 ; } 一直想不通为什么会是128,完全没有道理,而且出来的结果也不正确,有一堆无关的边缘,比没抑制前还严重,只要是有幅值>0的基本上都成为了无关边缘。 这里应该改为: if(dTmp>=dTmp1 &&……
应该是当前点的灰度值而不是幅值 改为 pUncheckRst->imageData[nPos] = 128;
kaixindouble 2012-10-12
  • 打赏
  • 举报
回复
好~~~~看论文一直没有理解non maximal supression是为嘛,在哪里体现的~~~
qq850609901 2012-04-10
  • 打赏
  • 举报
回复
相信自己,代码也是人写的,他也会犯错误
laodizhi8757 2012-02-22
  • 打赏
  • 举报
回复
代码部分有个错误
if(dTmp>=dTmp1 && dTmp>=dTmp2)
{
pUncheckRst[nPos] = 128 ;
}
一直想不通为什么会是128,完全没有道理,而且出来的结果也不正确,有一堆无关的边缘,比没抑制前还严重,只要是有幅值>0的基本上都成为了无关边缘。
这里应该改为:
if(dTmp>=dTmp1 && dTmp>=dTmp2)
{
pUncheckRst[nPos] = dTmp;
}
laodizhi8757 2012-02-22
  • 打赏
  • 举报
回复
if(dTmp>=dTmp1 && dTmp>=dTmp2)
{
pUncheckRst[nPos] = 128 ;
}

为什么会等于128呢?源图像经过非极大值抑制之后的结果会是怎么样的呢?
visionfans 2011-06-10
  • 打赏
  • 举报
回复
由于行文仓促,上面发帖的时候有些笔误,凡是说到"最大值抑制"的,请楼主自行改正为"非最大值抑制".

canny算子中抑制的是不是局部最大值的梯度像素点.
visionfans 2011-06-10
  • 打赏
  • 举报
回复
给你画个图就明白了.



下面分几点给你解释:

首先要明白的是:

(a.) canny算子中非最大抑制(Non-maximum suppression)是回答这样一个问题: "当前的梯度值在梯度方向上是一个局部最大值吗?" 所以,要把当前位置的梯度值与梯度方向上两侧的梯度值进行比较.
(b.) 梯度方向垂直于边缘方向, 这一点不要误解.

针对你的几个问题:
Q1: 插值是何意?为啥取g1,g2为一组,g3,g4为一组计算插值?
A: 首先, 虽然插值是有必要的,但是没有说必须要插值. 例如, Wikipedia里[1]的canny算子一文中的所讲的非最大值抑制就只是在0\90\45\135度梯度方向上进行的. 每个像素点梯度方向按照相近程度用这四个方向来代替,这种情况下,非最大值抑制所比较的相邻两个像素就是:
0 : 左边 和 右边
90 : 上边 和 下边
45 : 右上 和 左下
135: 左上 和 右下

这样做的好处是简单, 但是, 这种简化的方法无法达到最好的效果, 因为, 自然图像中的边缘梯度方向不一定是沿着这四个方向的. 因此, 就有很大的必要进行插值, 目的是*找出在一个像素点上最能吻合其所在梯度方向的两侧的像素值*.

然而, 通过argtan(gx/gy)得到的方向可以是-90~90度内的任何值, 但是, 因为实际数字图像中的像素点是离散的二维矩阵, 所以, 处在真正中心位置C处的梯度方向两侧的点是不一定存在的, 或者说是一个亚像素(sub pixel)点, 而这个不存在的点, 以及这个点的梯度值就必须通过对其两侧的点进行插值来得到.

至此, 插值的目的我讲述了一遍.

举个直观的例子,就是上面贴的那张图.
这个图给出的情况是, gy > gx 且 gx*gy > 0(注意: gx*gy>0是因为图像坐标系中y轴是朝下的.)

蓝色的直线代表梯度方向. g1, g2, g3, g4四个点以及插值点dTemp1, dTemp2 的位置如图所示.
对应的代码是:
g1 = pnMag[nPos-imageWidth-1] ;
g3 = pnMag[nPos+imageWidth+1] ;

g2 = pnMag[nPos-imageWidth] ;
g4 = pnMag[nPos+imageWidth] ;

下面解释, 插值公式为什么是:
dTmp1 = weight*g1 + (1-weight)*g2 ;
dTmp2 = weight*g3 + (1-weight)*g4 ;

这里: weight = fabs(gx)/fabs(gy) = ctan(theta), theta为梯度方向.
上面那个公式变一下就可以变换成:
weight = |dTemp1-g2|/|g1-g2| = |dTemp1-g2|/|C-g2| = ctan(theta);
而从我画的图中可以直观的看出, 在由<C, g2, dTemp1>组成的三角形中, 正好符合这个公式.(这里我没有太care正负号,只是为了给你一个直观解释)

讲到这里,应该你的后两个问题都不成问题了吧.

Q2: 原理上是比较3*3矩阵内相邻像素点是不是最大值,他为何比较g1,g2,g3,g4就完事了
A: 最大值抑制中的比较最大值不是看是不是3*3矩阵内的最大值, 而是看是不是梯度方向上的局部最大值. 否则就成了一个3*3的最大值滤波了. 为什么比较g1~g4, Q1的回答中已经讲清楚了.

Q3: 为何要分X,Y方向导数谁大两种情况比较
A: 把X, Y方向导数谁大两种情况分开只是为了编程上的方便. 你也可以分四种情况分别进行最大值抑制.

[1] http://en.wikipedia.org/wiki/Canny_edge_detector#Non-maximum_suppression

4,445

社区成员

发帖
与我相关
我的任务
社区描述
图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧