写一个canny算子,网上有很多canny算子的博客,但是有些地方描述的没有很清楚或者说比较讲的比较难懂,本文主要对某些细节进行更通俗的解释,由于时间有限,没有长篇大论的进行详细的描述,适合对canny算子已经有一定了解的同学。
canny算子是一种边缘提取算法,是sobel,prewitt算子的升级版本。
sobel边缘算子的缺陷:
1.只有垂直和水平两个方向,没有充分地利用梯度的方向。
2.只采用单阈值进行最后边缘的判断,梯度幅值小于阈值的认为不是边缘,大于的则认为是边缘。
canny算子的改进:
1.基于边缘梯度方向进行非极大值抑制,将粘合的多个像素边缘,选取最强的单个像素代替。
2.最后采用两个阈值进行判断。
canny进行这两个改进 的目的:
1.取梯度幅值的局部最大值作为真正的边缘,用于细化边缘。
2.对于弱边缘,判断是否与真正的边缘相连,如果不相连不作为边缘,避免将单个的噪声判断为边缘。
canny共分为四个步骤:
1.高斯平滑,降低边缘的错误率,去除一些噪声影响。
2.sobel计算边缘方向和幅值,将方向量化为4个方向,注意梯度方向的计算应该在-180到180度之间,应该采用arctan2,而不是直接arctan(dy/dx)。
梯度的方向其实就是水平和垂直方向的幅值相对大小决定的,哪个方向的幅值大,梯度方向就往哪边靠,比如相等时,则梯度方向在中间,arctan(1)=45度
3.选择一个3x3大小的(或者其他大小)模版,延此像素的梯度方向,判断模版内此像素是不是梯度幅值最大的,如果是保留,如果不是置为0。将模版在图像内移动,遍历所有位置。
4.经过步骤三之后,得到了一个新的梯度幅值图,选择最高的梯度幅值,乘于0.3和0.1分别作为高低阈值,低于低阈值的判断不是边缘,高于高阈值的判断为边缘,处于中间的如果它八邻域内有真正的边缘,将其判断为边缘。
以上为简单通俗的对canny的理解,其中还有更多的细节未能阐述。
参考文章: