深度学习让模型本身选择会用什么的算子,而深度学习之前,我们的都是靠自己来提取这些算子
— 总体概括:
边缘检测的基本方法有很多,一阶的有Roberts Cross算子,Prewitt算子,Sobel算子,Canny算子,Krisch算子,罗盘算子;而二阶的还有Marr-Hildreth,在梯度方向的二阶导数过零点。各种算子的存在就是对这种导数分割原理进行的实例化计算,是为了在计算过程中直接使用的一种计算单位。在对图像的操作,我们采用模板对原图像进行卷积运算,从而达到我们想要的效果。而获取一幅图像的梯度就转化为:模板(Roberts、Prewitt、Sobel、Lapacian算子)对原图像进行卷积。
— 微分算子
---- sobel算子
边缘检测,离散型差分算子,梯度的近似值,一阶导数的边缘检测算子,对噪声有平滑作用, Sobel算子对于象素的位置的影响做了加权,与Prewitt算子、Roberts算子相比因此效果更好。
缺点是Sobel算子并没有将图像的主题与背景严格地区分开来,换言之就是Sobel算子并没有基于图像灰度进行处理,由于Sobel算子并没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。
用到了opencv的 https://www.e-learn.cn/content/python/1393046
image = cv2.copyMakeBorder(image, 1, 1, 1, 1, cv2.BORDER_DEFAULT) 填充的效果
def Sobeloperator(roi, operator_type):
if operator_type == 'H':
sobel = np.array([[-1,-2,-1],[0,0,0],[1,2,1]])
if operator_type == 'W':
sobel = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])
result = np.abs(np.sum(roi * sobel))
return result
def SobelALo(image, operator_type):
new_image = np.zeros(image.shape)
image = cv2.copyMakeBorder(image, 1, 1, 1, 1, cv2.BORDER_DEFAULT)
for i in range(1,image.shape[0]-1):
for j in range(1,image.shape[1]-1):
new_image[i-1,j-1] = Sobeloperator(image[i - 1:i + 2, j - 1:j + 2], operator_type)
new_image = new_image * (255/np.max(image))
return new_image.astype(np.uint8)
saber = cv2.imread("Yolov3-tiny.jpg")
gray_saber = cv2.cvtColor(saber,cv2.COLOR_RGB2GRAY)
gray_saber = cv2.resize(gray_saber,(200,200))
---- Prewitt 算子
据经验得知Sobel要比Prewitt更能准确检测图像边缘。
Prewitt算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用 。其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。
则 P(i,j)=max[G(i),G(j)]或 P(i,j)=G(i)+G(j)
经典Prewitt算子认为:凡灰度新值大于或等于阈值的像素点都是边缘点。即选择适当的阈值T,若P(i,j)≥T,则(i,j)为边缘点,P(i,j)为边缘图像。这种判定是欠合理的,会造成边缘点的误判,因为许多噪声点的灰度值也很大,而且对于幅值较小的边缘点,其边缘反而丢失了。
Prewitt算子对噪声有抑制作用,抑制噪声的原理是通过像素平均,但是像素平均相当于对图像的低通滤波,所以Prewitt算子对边缘的定位不如Roberts算子。
该算子与Sobel算子类似,只是权值有所变化,但两者实现起来功能还是有差距的。
def Sobeloperator(roi, operator_type):
if operator_type == 'H':
sobel = np.array([[-1,-1,-1],[0,0,0],[1,1,1]])
if operator_type == 'W':
sobel = np.array(