空间域图像增强:OpenCV实现更多一阶导数图像边缘检测算子

0.综述

图像的一阶导数算子除了Sobel边缘检测算子以外,常见的还有Roberts边缘检测算子与Prewitt边缘检测算子。尽管OpenCV中没有这两个算子直接调用的API,我们可以通过自定义滤波器来自行创建Robert算子和Prewitt算子来实现图像的梯度边缘检测。

关于Sobel算子和图像梯度的内容可以参见下面这篇博客:

OpenCV自定义滤波器则可以参见下面这篇博客:

1.Roberts边缘检测算子原理分析

任意一对相互垂直方向上的差分可以看成是梯度的近似求解,Roberts边缘检测算子就是基于该原理,用对角线上相邻像素之差来代替梯度,从而寻找图像中边缘。所以Roberts边缘检测算子是一个交叉算子,其在点 ( i , j ) (i,j) (i,j)处的梯度幅值表达式为:
G ( i , j ) = ∣ f ( i , j ) − f ( i + 1 , j + 1 ) ∣ + ∣ f ( i + 1 , j ) − f ( i , j + 1 ) ∣ (1) G(i,j)=|f(i,j)-f(i+1,j+1)|+|f(i+1,j)-f(i,j+1)|\tag{1} G(i,j)=f(i,j)f(i+1,j+1)+f(i+1,j)f(i,j+1)(1)
其中:
G x = f ( i , j ) − f ( i + 1 , j + 1 ) G_x=f(i,j)-f(i+1,j+1) Gx=f(i,j)f(i+1,j+1)
G y = f ( i + 1 , j ) − f ( i , j + 1 ) G_y=f(i+1,j)-f(i,j+1) Gy=f(i+1,j)f(i,j+1)
所以等式 ( 1 ) (1) (1)可以简化为:
G ( i , j ) = ∣ G x ∣ + ∣ G y ∣ G(i,j)=|G_x|+|G_y| G(i,j)=Gx+Gy
G x , G y G_x,G_y Gx,Gy的对于2x2大小卷积核分别为:
H x = [ 1 0 0 − 1 ] H_x= \left[ \begin{matrix} 1 &0 \\ 0& -1 \end{matrix} \right] Hx=[1001]
H y = [ 0 − 1 1 0 ] H_y= \left[ \begin{matrix} 0 &-1 \\ 1& 0 \end{matrix} \right] Hy=[0110]

由于Roberts边缘检测算子是利用图像的两个对角线方向的相邻像素之差进行梯度幅值的检测,所以求得的是在差分点 ( i + 1 / 2 , j + 1 / 2 ) (i+1/2,j+ 1/2) (i+1/2,j+1/2)处梯度幅值的近似值,而不是所预期的点 ( i , j ) (i,j) (ij)处的近似值,为了避免引起混淆,通常采用3X3邻域计算梯度值。

利用Roberts边缘检测算子进行边缘检测的方法是:分别利用上述两个模板对图像进行逐像素卷积,将2个卷积结果值相加,然后判别该相加结果是否大于或等于某个阈值,如果满足条件,则将其作为结果图像中对应于模板 ( i , j ) (i,j) (i,j)位置的像素值;如果不满足条件,则给结果图像中对应于模板 ( i , j ) (i,j) (i,j)位置的像素赋0值。

由于Roberts算子模板窗口较小,平滑噪声的作用小,且对噪声较为敏感。该算法仅采用了对角线上相邻像素之差进行梯度幅度检测,并未考虑水平相邻像素和垂直相邻像素的情况,无法消除局部噪声干扰,也会丢失灰度值变化缓慢的局部边缘,从而导致目标的边缘轮廓不连续。

2.Prewitt边缘检测算子原理分析

Prewitt边缘检测算子在x方向和y方向的梯度幅值形式与Sobel算子的形式完全相同,只是它的系数均为1。该算子对应的两个方向的3x3卷积核分别为:
H x = [ − 1 0 1 − 1 0 1 − 1 0 1 ] H_x= \left[ \begin{matrix} -1 &0&1 \\ -1 &0&1 \\ -1 &0&1 \\ \end{matrix} \right] Hx=111000111
H y = [ 1 1 1 0 0 0 − 1 − 1 − 1 ] H_y= \left[ \begin{matrix} 1&1&1\\ 0&0&0\\ -1&-1&-1\\ \end{matrix} \right] Hy=101101101

Prewitt边缘检测算子的计算比Sobel算子更为简单,但是在噪声方面Sobel算子更胜一筹。从总体上来说,梯度算子对噪声都有一定的敏感性,所以比较适用于图像边缘灰度值比较尖锐,并且图像噪声比较小的情况下应用。

3.OpenCV自定义滤波器实现Roberts算子与Prewitt算子

首先定义两个算子的卷积核:

	Mat roberts_x = (Mat_<int>(2, 2) << 1, 0, 0, -1);
	Mat roberts_y = (Mat_<int>(2, 2) << 0, -1, 1, 0);

	Mat pre_kx = (Mat_<char>(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);
	Mat pre_ky = (Mat_<char>(3, 3) << 1, 1, 1, 0, 0, 0, -1, -1, -1);

然后使用filter2D函数进行卷积计算:

Mat rob_x, rob_y, pre_x, pre_y;

filter2D(input, rob_x, CV_16S, roberts_x);
filter2D(input, rob_y, CV_16S, roberts_y);
convertScaleAbs(rob_x, rob_x);
convertScaleAbs(rob_y, rob_y);

filter2D(input, pre_x, CV_32F, pre_kx);
filter2D(input, pre_y, CV_32F, pre_ky);
convertScaleAbs(pre_x, pre_x);
convertScaleAbs(pre_y, pre_y);

最后显示出结果:

imshow("rob_x", rob_x);
imshow("rob_y", rob_y);
imshow("pre_x", pre_x);
imshow("pre_y", pre_y);

最终结果如下:
在这里插入图片描述

通过上面的结果可以看出,垂直算子对垂直方向的边缘梯度具有较强的响应,而水平算子对水平方向上的边缘梯度具有较强的响应。在这三种边缘检测算法中,Roberts算子的检测结果最精细,Prewitt算子比Sobel算子稍精细一些。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值