本期主要介绍常用于进行图像边缘检测的滤波器(算子):Sobel算子、Scharr算子、Laplacian算子;通过实验比较不同的算子的处理效果以及使用场景。
完成本期内容,你可以:
-
了解图像梯度的原理和应用
-
掌握使用Sobel算子、Scharr算子、Laplacian算子进行边缘检测
若要运行案例代码,你需要有:
-
操作系统:Ubuntu 16 以上 或者 Windows10
-
工具软件:VScode 或者其他源码编辑器
-
硬件环境:无特殊要求
-
核心库:python 3.6.13, opencv-contrib-python 3.4.11.39,opencv-python 3.4.2.16
点击下载源码
Sobel算子
OpenCV将Sobel算子封装成了cv2.Sobel()
方法。
函数原型: dst = cv2.Sobel( src, ddepth, dx, dy[,ksize[, scale[, delta[, borderType]]]] )
dst为输出图像。
参数描述如下:
-
dst
:目标图像 -
src
:原始图像 -
ddepth
:输出图像的深度 -
dx
:x方向上的求导阶数。 -
dy
:y方向上的求导阶数。 -
ksize
:Sobel核的大小。该值为-1时,则会使用Scharr算子进行运算。 -
scale
:计算导数值时所采用的缩放因子,默认情况下该值是1,是没有缩放的。 -
delta
:加在目标图像dst上的值,该值是可选的,默认为0。 -
borderType
:边界样式
Scharr算子
OpenCV将Scharr算子封装成了cv2.Scharr()
方法。
函数原型: dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )
dst为输出图像。
参数描述如下:
dst
:目标图像src
:原始图像ddepth
:输出图像的深度dx
:x方向上的求导阶数。dy
:y方向上的求导阶数。scale
:计算导数值时所采用的缩放因子,默认情况下该值是1,是没有缩放的。delta
:加在目标图像dst上的值,该值是可选的,默认为0。borderType
:边界样式
Laplacian算子
OpenCV将Laplacian算子封装成了cv2.Laplacian()
方法。
函数原型:dst = cv2.Laplacian( src, ddepth[ , ksize[ , scale[ , delta[ , borderType]]]])
参数描述如下:
ddepth
:输出图像深度。ksize
:核的大小scale
:计算导数值时的缩放因子(可选)。delta
:加到目标图像上的亮度值(可选)。borderType
:边界样式。
具体步骤
1. 创建项目结构
创建项目名为对花朵图像进行边缘检测
,项目根目录下新建code
文件夹储存代码,新建dataset
文件夹储存数据,项目结构如下:
对花朵图像进行边缘检测 # 项目名称
├── code # 储存代码文件
├── dataset # 储存数据文件
注:如项目结构已存在,无需再创建。
2. 使用不同的算子进行边缘检测
- 在
code
文件夹下创建edge.py
文件; - 导入所需的库,OpenCV;
- 读取
dataset
文件夹下的flower.png
图片,并进行展示,标题为flower ; - 分别使用Sobel算子、Scharr算子、Laplacian算子进行图像处理,并展示结果;
步骤一:创建文件并读取图像
代码实现
# 导入OpenCV
import cv2
# 读取图片
o = cv2.imread('../dataset/flower.png')
cv2.imshow('flower',o)
步骤二:使用Sobel算子进行边缘检测
代码实现
# 使用Sobel算子进行边缘检测
# 计算图像x方向的边缘,输出图像深度为64F
Sobelx = cv2.Sobel(o,cv2.CV_64F,1,0)
Sobelx = cv2.convertScaleAbs(Sobelx)
# 计算图像y方向的边缘,输出图像深度为64F
Sobely = cv2.Sobel(o,cv2.CV_64F,0,1)
Sobely = cv2.convertScaleAbs(Sobely)
# 将x和y方向的梯度图加权相加
Sobelxy = cv2.addWeighted(Sobelx,0.5,Sobely,0.5,0)
cv2.imshow('Sobel',Sobelxy)
步骤三:使用Scharrx算子进行边缘检测
代码实现
# 使用Scharrx算子进行边缘检测
# 计算图像x方向的边缘,输出图像深度为64F
Scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
Scharrx = cv2.convertScaleAbs(Scharrx)
# 计算图像y方向的边缘,输出图像深度为64F
Scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
Scharry = cv2.convertScaleAbs(Scharry)
# 将x和y方向的梯度图加权相加
Scharrxy = cv2.addWeighted(Scharrx,0.5,Scharry,0.5,0)
cv2.imshow('Scharr',Scharrxy)
步骤四:使用Laplacian算子进行边缘检测
代码实现
# 使用Laplacian算子进行边缘检测
# 计算图像图像边缘信息,滤波核的大小为3,输出图像深度为64F
Laplacian = cv2.Laplacian(o,cv2.CV_64F,ksize = 3)
Laplacian = cv2.convertScaleAbs(Laplacian)
cv2.imshow("Laplacian",Laplacian)
步骤五:关闭窗口
代码实现
cv2.waitKey()
cv2.destroyAllWindows()
3. 结果比较
通过比较三种算子进行边缘检测以后的效果,会发现:三种算子均可以满足图像边缘检测的需求,scharr算子较sobel算子提取的细节边缘更多,Laplacian算子提取边缘后的图像亮度更高。
点击下载源码