1 实验目的
了解Sobel边缘检测的用途及原理。
2 实验设备
安装了python和pychrm的电脑一台。
3 实验内容
包含图片的导入和显示、Sobel边缘检测。
4 实验原理
Sobel算子是一种常用的边缘检测算子,是一阶的梯度算法;对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高;当对精度要求不是很高时,是一种较为常用的边缘检测方法。它是一阶微分算子(离散差分算子),利用临近(上下、左右)的像素值(灰度值)来计算当前像素值(灰度值),因为图像中边缘处的灰度变化比较快,呈现阶跃现象,sobel算法边缘检测利用这一特点对图像中每个像素计算其余周围相邻像素的差分值来判断该像素点是否属于边缘,这可根据阈值来取舍。通过横向和纵向的计算得到和,,但是为了提高计算效率,因此用来代替。
思想:
算子使用两个3*3的矩阵算子分别和原始图片作卷积,分别得到横向Gx和纵向Gy的梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点;上述的处理可以同时进行两个方向的处理,当需要突出图像某一个方向的边缘信息时,也可以只进行其中一个方向的处理。
Sobel卷积因子:
该算子包含两组3*3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下
让两个方向模板分别沿着x轴、y轴与图像做卷积,方向是从上到下和从左到右。将模板的中 心和图像上的某个像素重合,并将该像素周围的点 与模板上对应的系数相乘, 最后选取合适的阈值,将像素点的灰度值与阈 值进行比较,若大于阈值,则该点则为图像边缘点。
具体计算如下:
Gx = (-1)*f(x-1, y-1) + 0*f(x,y-1) + 1*f(x+1,y-1)
+(-2)*f(x-1,y) + 0*f(x,y)+2*f(x+1,y)
+(-1)*f(x-1,y+1) + 0*f(x,y+1) + 1*f(x+1,y+1)
= [f(x+1,y-1)+2*f(x+1,y)+f(x+1,y+1)]-[f(x-1,y-1)+2*f(x-1,y)+f(x-1,y+1)]
Gy =1* f(x-1, y-1) + 2*f(x,y-1)+ 1*f(x+1,y-1)
+0*f(x-1,y) 0*f(x,y) + 0*f(x+1,y)
+(-1)*f(x-1,y+1) + (-2)*f(x,y+1) + (-1)*f(x+1, y+1)
= [f(x-1,y-1) + 2f(x,y-1) + f(x+1,y-1)]-[f(x-1, y+1) + 2*f(x,y+1)+f(x+1,y+1)]
其中f(a,b),表示图像(a,b)点的灰度值。
图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
如果梯度G大于某一阀值 则认为该点(x,y)为边缘点。
然后可用以下公式计算梯度方向:
Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。
Opencv通过cv2.Sobel()函数实现Sobel算子。
函数原型:
sobelx = cv2.Sobel(img,cv2.CV_64F, 1, 0, ksize=3)
参数:
img表示源图像,即进行边缘检测的图像
cv2.CV_64F表示64位浮点数即64float。这里不使用numpy.float64,因为可能会发生溢出现象。用cv的数据则会自动。
第三和第四个参数分别是对X和Y方向的导数(即dx,dy),对于图像来说就是差分,这里1表示对X求偏导(差分),0表示不对Y求导(差分)。其中,X还可以求2次导。
注意:对X求导就是检测X方向上是否有边缘。
第五个参数ksize是指核的大小。
4.5 实验步骤
打开pycharm
我们右击相应的文件目录,选择new--->点击Python File,然后输入新建的文件名,点击确定,相应的.py文件就建好了,可以进行编写代码了。
导入需要的图片。
ipoert cv2
将图片以灰度图像读取。
img = cv2.imread("..\images\statue.jpg", 0)
调用opencv的Sobel函数对X方向求梯度。
edges2 = cv2.Sobel(img,cv2.CV_16S,1,0, ksize=3)
sobel_x = cv2.convertScaleAbs(edges2)
求y放向的梯度。
edges3 = cv2.Sobel(img,cv2.CV_16S,0,1, ksize=3)
sobel_y = cv2.convertScaleAbs(edges3)
对两个方向同时进行检测,则会过滤掉仅仅只是x或者y方向上的边缘。
sobel_XY = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3)
显示结果。
plt.subplot(2, 2, 1)
plt.imshow(img, 'gray')
plt.title('src')
plt.subplot(2, 2, 2)
plt.imshow(sobel_x, 'gray')
plt.title('sobelX')
plt.subplot(2, 2, 3)
plt.imshow(sobel_y, 'gray')
plt.title('sobelY')
plt.subplot(2, 2, 4)
plt.imshow(sobel_XY, 'gray')
plt.title('sobelXY')
plt.show()
下面是分别对x方向和y方向,还有x和y方向时进行边缘检测的结果
运行结果