前言
记录Sobel算子的学习过程。该算法相对其他的边界检测算法而言是比较的容易。但是对于噪声的鲁棒性要低于其他的边界检测技术。比如canny。
索伯算子是一种多用于边缘检测的离散性差分算子。索伯算子有两组不同的卷积因子,可以为一张图片做横向以及纵向的平面卷积。详细的讲就是,假设要对一张图中的(x,y)这个像素使用索伯算子。首先用两个卷积因子分别对该点做卷积,从而可得出该点在这两个方向上的亮度差分近似值。将xy两个方向的亮度近似值进行结合之后,即可得到该点亮度。 得到的是一个数,如果这个值大于了阈值,那么这个点就可以被考虑成边缘点。
一、算子
具体算子的模板如下图所示,
二、编程实现
1.卷积函数
代码如下(示例):
import numpy as np
def my_filter2D(img,kernel):
"""
卷积函数
:param image: 原图像,是灰度图
:param kernel: 卷积核
:return: 卷积后的图像
"""
k_rows,k_cols = kernel.shape[:2]
i_rows,i_cols = img.shape[:2]
new_img = np.zeros((img.shape[0],img.shape[1]),dtype=np.float32)
#进行遍历操作
for row in range(i_rows-k_rows+1):
for col in range(i_cols-k_cols+1):
#创建一个视图window,大小与kernel一致
windows=img[row:row+k_rows,col:col+k_cols]
#完成卷积操作
out=abs(np.sum(windows * np.flip(kernel), axis=(0, 1)))
#赋值 3*3的kernel是row+1,但是2*2 此时的位置是左上,那就等于row,col,将下面修改一下。
#new_img[row+1,col+1] = out
new_img[row+k_rows//2,col+k_cols//2] = out
new_img = np.clip(new_img, 0, 255).astype(np.uint8)
return new_img
2.sobel算子函数
代码如下(示例):
import numpy as np
import img_filter2D #将前面的卷积函数写成一个模块并引入
def my_roberts(img):
h,w = img.shape[:2]
G = np.zeros((img.shape[0],img.shape[1]),dtype=np.float32)
dx = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])
dy = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
Gx = abs(img_filter2D.my_filter2D(img,dx))
Gy = abs(img_filter2D.my_filter2D(img,dy))
G = Gx+Gy
new_img = np.clip(G, 0, 255).astype(np.uint8)
Gx = np.clip(Gx, 0, 255).astype(np.uint8)
Gy = np.clip(Gy, 0, 255).astype(np.uint8)
return Gx,Gy,new_img
3进行测试
import cv2
import matplotlib.pyplot as plt
import Sobel
img = cv2.imread("lena.bmp",0)
i,j,k = Sobel.my_roberts(img)
figure_ = plt.figure()
ax1 = figure_.add_subplot(141)
ax1.set_title('original img')
plt.imshow(img,cmap='gray')#不要忘记这一步
ax2= figure_.add_subplot(142)
ax2.set_title('x_convolution')
plt.imshow(i,cmap='gray')
ax3 = figure_.add_subplot(143)
ax3.set_title('y_convolution')
plt.imshow(j,cmap='gray')
ax4 = figure_.add_subplot(144)
ax4.set_title('magnitude')
plt.imshow(k,cmap='gray')
plt.show()
结果如图所示:
Q:有没有发现第一张图是绿色的?
A:因为我一开始plt.imshow(img,cmap=‘gray’)代码里面忘记写cmap=‘gray’,他可能默认是彩色映射,改过来效果就应该没问题了。