最近一直研究基于灰度的边缘检测,搜索了好多博客文章,发现没有对Sobel算子解释的非常清晰明了的,对于我这种数学控,细节控,实在是无法忍受,所以索性自己查阅数学资料,研究一番,花了一周时间终于搞清楚了所有的困惑,分享给大家。这篇文章非常长,分成3个部分:实现原理,代码部分,数学部分,大家可以根据需要查看,如果能从头到尾啃完,相信一定有巨大收获!由于我不想把所有数学公式再打一遍了,所以直接上图了,请谅解
目录
1-5. 曼哈顿距离(Manhattan Distance )
1.实现原理
1-1.边缘检测的原理
图像由像素点组成的,在像素点的灰度变化剧烈的地方就可以被当作是边缘.
a.比较灰度
像素点一般来说可以有三种颜色表示,RGB,单独比较任何以中颜色,都不能表达图像某区域的变化.所以要比较灰度.
b.单像素点的最大变化值
每个像素点的灰度变化,是和周围像素点比较的结果,而且这个比较是有方向的. 某个方向也许变化不大,另一个方向变化或许很大. 必须选取变化最大的一个方向的数值,这个数值才有资格代表这个像素点的变化率. 从数学角度来说,灰度在某个方向的变化率,其实就是灰度在某个方向上的方向导数. 那么哪个方向的方向导数最大呢,是梯度的方向(注意,梯度是个向量),并且这个最大方向导数的绝对值,也就是最大的变化率的绝对值,等于梯度的模.
c.选出边缘
每个像素点的最大变化率都求出后,我们可以根据自己设定的阈值,进行筛选,得到最终的边缘.或者是按照这个变化率绝对值的大小,按照比例绘制粗细不同,颜色深浅不同的边缘轮廓.
1-2.像素的梯度
具体的梯度公式和方向导数的推导证明请参考最后的“数学部分”,此处我们直接开始讨论像素的梯度计算.
也就是要求出像素的梯度,并且还要求出梯度的模,也就是该像素灰度的最大变化率.
梯度:
梯度的模:
之所以要约等于x,y两个分量绝对值的和,是因为计算平方和,再计算开方是个不小的成本.
最后问题归结为计算x,y方向的偏导数.
1-3.思路总结
1-4.像素的梯度
如果是连续的函数,那么通过x,y的偏导数计算得到的梯度向量就是个准确的数值.但是现实情况是,在图像中灰度的变化并不是连续的函数,而是离散的. 为了让得到的灰度变化梯度更加准确,不仅要计算x,y方向的偏导数(方向导数)得到梯度,同时可以再选择两个正交的方向计算方向导数(参考数学部分g),得到梯度,这两个梯度求平均值,进而得到更准确的梯度.
图中每个格子代表一个像素点,上面的字母表示该像素点的灰度数值. 以e像素为中心,可粗略分成8个方向. 如果要更细致的划分方向,需要扩展邻近像素数量,计算成本将会大大提高. 更值得关注的是梯度的相对大小,而不是绝对大小,所以我们这里也没有严格使用单位向量.
参考“数学部分”公式f-4,