opencv-学习笔记(6)图像梯度Sobel以及canny边缘检测
opencv-学习笔记(6)图像梯度Sobel以及canny边缘检测
这章讲了
- sobel算子
- scharr算子
- Laplacion拉普拉斯算子
- 图像深度问题
- Canny检测
图像梯度
- sobel算子和scharr算子
sobel算子是高斯平滑与微分操作的结合体,所以它的抗噪声能力很强
我们可以设定求导的方向xorder或者yorder。也可以设置卷积核的大学
Ps当我们设置卷积核的大小为ksize=-1时候,这个函数会用
3*3的scharr算子如下
官方推荐在使用3*3滤波器时候要用scharr滤波器
Laplacion算子
拉普拉斯算子可以使用二阶导数的形式定义,可假设其离散实现类型于二阶Sobel导数实际上,
Opencv在计算拉普拉斯算子时直接调用Sobel算子。
计算公式如下
拉普拉斯滤波器使用的卷积核
Opencv在计算拉普拉斯算子时候是直接调用sobel算子的
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('1.jpg',0)
#cv2.CV_64F 输出图像的深度(数据类型),可以使用-1与源图像保持一致 np.uint8
laplacian=cv2.Laplacian(img,cv2.CV_64F)
#参数1,0为只在x方向求一阶导数,最大可以求2阶导数,卷积核5*5
#对x滤波就显示y波形
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
#参数0,1为只在y方向求一阶导数,最大可以求2阶导数,卷积核5*5
#对y滤波就显示x波形
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)
cv2.imshow('one',img)
cv2.imshow('lap',laplacian)
cv2.imshow('sx',sobelx)
cv2.imshow('sy',sobely)
cv2.waitKey(0)
图像深度问题
看下面2个例子,
都是用5*5的卷积核,只是输出图像的深度不同,第四张是原图深度
水平的导数都消失了
从第三章可以看出来,导数小于0的地方没有消失,但是图24消失了导数小于0的地方
Canny边缘检测
- 首先我们要去除噪声5*5的高斯滤波器
- 我们计算图像的梯度计算图像x和y方向的一阶导数,根据两幅梯度体系找到边界的梯度大小和方向,(梯度一般总是和边界垂直,梯度方向被归为四类,垂直水平和对角线)
- 这是计算梯度大小和方向的函数
- 非极大值抑制,去除非边界的点,对每一个像素检查,看这个点梯度是不是周围具有相同梯度方向的点中最大的。
- 滞后阀值----设置两个阀值minVal和maxVal当图像的灰度梯度高于maxVal时候被认为是真的边界,低于minVal就被抛弃,如果在两者之间的话就看这个点时候和某个被确认为真正边界的点相连,如果是就认为他也是边界,,否则抛弃。
- 如下图
-
-
图中A高于maxVal被认为是真正的边界带你,C虽然低于maxVal但是高于minVAl且和A相连,所以C也是边界点。B被抛弃
这一步中一些小的噪声点被去除,因为我们假设边界都是一些长的线段
在opencv里面我们用一个函数来完成上面所有步骤
cv2.Canny()
Cv2.canny(图像对象,minVal,maxVal,用来计算梯度的Sobel卷积核大小Size=3,L2gradient)
如果L2gradient是True就会用到上面的步骤
如果L2gradient是false就会edge_graddient=|Gx^2|+|Gy^2|来代替
代码如下,这里使用的是size=3的默认卷积核以及,L2gradient=True
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('new.jpg',1)
minval=100
maxval=200
edges=cv2.Canny(img,minval,maxval,False)
edges2=cv2.Canny(img,minval,maxval,True)
cv2.imshow('dsd',img)
cv2.imshow('s',edges)
cv2.imshow('s2',edges2)
k=cv2.waitKey(0)
cv2.destroyAllWindows()