边缘检测的实质是采用某种算法来提取出图像中对象与背景间的交界线。边缘为图像中灰度发生急剧变化的区域边界。图像灰度的变化情况可以用图像灰度分布的梯度来反映,因此可以用局部图像微分技术来获得边缘检测算子。经典的边缘检测方法,是通过对原始图像中像素的某小邻域构造边缘检测算子来达到检测边缘的目的。
一旦计算出导数之后,下一步要做的就是给出一个阈值来确定哪里是边缘位置。阈值越低,能够检测出的边线越多,结果也就越容易受到图片噪声的影响,并且越容易从图像中挑出不相关的特性。与此相反,一个高的阈值将会遗失细的或者短的线段。一个常用的这种方法是带有滞后作用的阈值选择。这个方法使用不同的阈值去寻找边缘。首先使用一个阈值上限去寻找边线开始的地方。一旦找到了一个开始点,我们在图像上逐点跟踪边缘路径,当大于门槛下限时一直纪录边缘位置,直到数值小于下限之后才停止纪录。这种方法假设边缘是连续的界线,并且我们能够跟踪前面所看到的边缘的模糊部分,而不会将图像中的噪声点标记为边缘。
一阶检测算子
Roberts Cross算子,Prewitt算子,Sobel算子, Kirsch算子,Canny算子,罗盘算子
1.Roberts算子
Roberts算子是对图像的对角方向的边缘感兴趣的梯度算子,是一种最简单的算子,利用局部差分算子寻找边缘。它采用对角线方向相邻两像素之差近似梯度幅值检测边缘。
下面分别用python自带的函数和自己按照Roberts算法编的代码,采用的方法是在原图像的第一行和第一列填充0,然后对其进行卷积计算,采用的公式为:
代码:
from skimage import data,color,filters
import matplotlib.pyplot as plt
import numpy as np
original_img=data.chelsea()
gray_img=color.rgb2gray(original_img)
'''
#using system function
edge_img=filters.roberts(gray_img)
figure=plt.figure()
plt.subplot(131).set_title('original_img')
plt.imshow(original_img)
plt.subplot(132).set_title('gray_img')
plt.imshow(gray_img)
plt.subplot(133).set_title('roberts_img')
plt.imshow(edge_img)
plt.show()
'''
#self code
x_roberts=np.array([[1,0],
[0,-1]])
y_roberts=np.array([[0,1],
[-1,0]])
h,w=gray_img.shape
img=np.zeros([h+1,w+1])
img[1:h+1,1:w+1]=gray_img[0:h,0:w]
def robert_cal(img,filter):
h,w=img.shape
img_filter=np.zeros([h,w])
for i in range(h-1):
for j in range(w-1):
img_filter[i][j]=img[i][j]*filter[0][0]+img[i][j+1]*filter[0][1]+img[i+1][j]*filter[1][0]+img[i+1][j+1]*filter[1][1]
return img_filter
x_edge_img=robert_cal(img,x_roberts)
y_edge_img=robert_cal(img,y_roberts)
edge_img=np.zeros([h,w])
for i in range(h):
for j in range(w):
edge_img[i][j]=np.sqrt(x_edge_img[i][j]**2+y_edge_img[i][j]**2)/(np.sqrt(2))
plt.figure('imgs')
plt.subplot(321).set_title('original_img')
plt.imshow(original_img)
plt.subplot(322).set_title('gray_img')
plt.imshow(gray_img)
plt.subplot(323).set_title('x_edge_img')
plt.imshow(x_edge_img