OpenCV Chapter3 图像梯度与Canny边缘检测
OpenCV
图像梯度
Sobel算子
主要目的:找出图像中有梯度的地方
主要思路 $\rightarrow$ 计算左右/上下数据
最终落实在卷积核上面(注意此时权重仍然与位置有关,类似高斯滤波)(对应位置相加后求和) $$ Kernel_x=\begin{bmatrix} &-1\ 0\ +1\newline &-2\ 0\ +2\newline &-1\ 0\ +1\newline \end{bmatrix}\newline G_x = \sum_{1 \leq i \leq size, 1 \leq j \leq size} Kernel_x[i][j] \times image[i][j]\newline $$
$$ Kernel_y=\begin{bmatrix} &-1\ -2\ -1\newline &0\ 0\ 0\newline &+1\ +2\ +1\newline \end{bmatrix}\newline G_y = \sum_{1 \leq i \leq size, 1 \leq j \leq size} Kernel_y[i][j] \times image[i][j]\newline $$
|
|
-
ddepth:图像的深度,通常为-1
-
dx和dy分别表示水平和竖直方向
-
ksize是Sobel算子的大小(一般为3x3或者5x5)
计算出来的数值如果越界会截断,只取范围内的最小或最大值
|
|
将负数转换为绝对值(否则在显示的时候会按照截断处理),防止因为计算方向带来的误差
|
|
效果
原二值图

原图
)第一次使用Sobel算子

第一次使用Sobel算子
)取绝对值

取绝对值
)使用不同的方式求和
分别给0.5的权重
|
|
为什么不同时设置$dx=1,dy=1$一起直接计算呢 $\rightarrow$ 直接计算效果不好(主要是融合效果不好),而且融合的时不如分开计算的自由度高
Scharr算子
权重与距离中心点的距离相关性更大,相比于Sobel
算子来说更加准确敏感,可以看成是Sobel
的改进
$$
Kernel_x=\begin{bmatrix}
&-3\ 0\ +3\newline
&-10\ 0\ +10\newline
&-3\ 0\ +3\newline
\end{bmatrix}\newline
G_x = \sum_{1 \leq i \leq size, 1 \leq j \leq size} Kernel_x[i][j] \times image[i][j]\newline
$$
$$ Kernel_y=\begin{bmatrix} &-3\ -10\ -3\newline &0\ 0\ 0\newline &+3\ +10\ +3\newline \end{bmatrix}\newline G_y = \sum_{1 \leq i \leq size, 1 \leq j \leq size} Kernel_y[i][j] \times image[i][j]\newline $$ 使用
|
|
Laplace算子
原理:二阶导数,对噪音点比较敏感,一般需要和其他方法配合使用 $$ Kernel=\begin{bmatrix} &0\ 1\ 0\newline &1\ -4\ 1\newline &0\ 1\ 0\newline \end{bmatrix}\newline G=\sum_{1 \leq i \leq size, 1 \leq j \leq size}Kernel_{i, j} \times image_{i, j}\newline $$
|
|
Canny边缘检测
流程
- 使用高斯滤波器,以平滑图像,滤除噪声
- 计算图像中每个像素点的梯度强度和方向
- 应用非极大值(
Non-Maximum Suppression
)抑制,以消除边缘检测带来的杂散响应 - 应用双阈值(
Double-Threshold
)检测来确定真实的和潜在的边缘 - 通过抑制孤立的弱边缘最终完成检测
高斯滤波器
$$ G(x, y)=\frac{1}{2\pi \sigma^2}e^{-\frac {x^2+y^2}{2\sigma^2}}\newline $$
$$ H=\begin{bmatrix} &0.0924\ 0.1192\ 0.0924\newline &0.1192\ 0.1538\ 0.1192\newline &0.0924\ 0.1192\ 0.0924\newline \end{bmatrix}\newline $$
$$ e=H * A = \begin{bmatrix} &h_{11}\ h_{12}\ h_{13}\newline &h_{21}\ h_{22}\ h_{23}\newline &h_{31}\ h_{32}\ h_{33}\newline \end{bmatrix} * \begin{bmatrix} &a\ b\ c\newline &d\ e\ f\newline &g\ h\ i\newline \end{bmatrix}=\sum_{1 \leq i \leq size, 1 \leq j \leq size}^{i, j} \begin{bmatrix} &a\times h_{11}\ b\times h_{12}\ c\times h_{13}\newline &d\times h_{21}\ e\times h_{22}\ f\times h_{23}\newline &g\times h_{31}\ h\times h_{32}\ i\times h_{33}\newline \end{bmatrix} $$
梯度和方向
使用Sobel
算子
$$ Kernel_x=\begin{bmatrix} &-1\ 0\ +1\newline &-2\ 0\ +2\newline &-1\ 0\ +1\newline \end{bmatrix}\newline G_x = \sum_{1 \leq i \leq size, 1 \leq j \leq size} Kernel_x[i][j] \times image[i][j]\newline $$
$$ Kernel_y=\begin{bmatrix} &-1\ -2\ -1\newline &0\ 0\ 0\newline &+1\ +2\ +1\newline \end{bmatrix}\newline G_y = \sum_{1 \leq i \leq size, 1 \leq j \leq size} Kernel_y[i][j] \times image[i][j]\newline $$
$$ \begin{align} &G=\sqrt{G_x^2+G_y^2}\newline &\theta=arctan(\frac {G_y}{G_x})\newline \end{align}\newline $$
非极大值抑制
在所有框里面选出相关性最大的,同时还会比较该框和周围框的相关性
算法:遍历图像中的所有像素点,判断当前像素点是否是周围像素点中具有相同方向(此时会给$\theta$ 划分区间,同区间视为相同就行)梯度的最大值。如果是梯度最大的像素点,就保留,否则就抑制
这一步可以将模糊的边界变得清晰
双阈值检测
$$ \begin{align} \begin{cases} 梯度值>maxVal:处理为边界\newline minVal<梯度值<maxVal:如果该点可以通过线连到边界点(即大于阈值的点)则保留,否则舍弃\newline 梯度值<minVal:舍弃\newline \end{cases} \end{align} $$
minVal
越小,条件越松,越多的边界会被检测到,反之则要求变高,检测的到边缘越少
maxVal
越大,条件越高,反之越松
代码
|
|
原图|(80, 150)|(50, 100)对比

不同阈值下的效果(第一张是原图,第二张为(80, 150),第三张为(50, 100)
)