挑战图像处理100问(15)——Sobel滤波器

Welcome ·
更新时间:2024-09-21
· 538 次阅读

在这里插入图片描述
Author:Tian YJ

Sobel滤波器

Sobel算子是一种典型的用于边缘检测的线性滤波器,它基于两个简单的3*3内核,滤波器按下式定义:

纵向:
K=[121000−1−2−1] K=\left[ \begin{matrix} 1&2&1\\ 0&0&0\\ -1&-2&-1 \end{matrix} \right] K=⎣⎡​10−1​20−2​10−1​⎦⎤​
横向:
K=[10−120−210−1] K=\left[ \begin{matrix} 1&0&-1\\ 2&0&-2\\ 1&0&-1 \end{matrix} \right] K=⎣⎡​121​000​−1−2−1​⎦⎤​
如果把图像看做二维函数,那么sobel算子就是图像在水平和垂直方向变化的速度。在数学属于中,这种速度称为梯度。它是一个二维向量,向量的元素是横竖两个方向的函数的一阶导数:
grad(I)=[∂I∂x∂I∂y]T grad(I)=\left[ \begin{matrix} \frac{\partial I}{\partial x}&\frac{\partial I}{\partial y}\\ \end{matrix} \right] ^T grad(I)=[∂x∂I​​∂y∂I​​]T
sobel算子在水平和垂直方向计算像素值的差分,得到图像梯度的近似值。它在像素周围的一定范围内进行运算,以减少噪声带来的影响。

代码实现 import cv2 # 我只用它来做图像读写和绘图,没调用它的其它函数哦 import numpy as np # 进行数值计算 # padding 函数 def padding(img, K_size=3): # img 为需要处理图像 # K_size 为滤波器也就是卷积核的尺寸,这里我默认设为3*3,基本上都是奇数 # 获取图片尺寸 H, W, C = img.shape pad = K_size // 2 # 需要在图像边缘填充的0行列数, # 之所以我要这样设置,是为了处理图像边缘时,滤波器中心与边缘对齐 # 先填充行 rows = np.zeros((pad, W, C), dtype=np.uint8) # 再填充列 cols = np.zeros((H+2*pad, pad, C), dtype=np.uint8) # 进行拼接 img = np.vstack((rows, img, rows)) # 上下拼接 img = np.hstack((cols, img, cols)) # 左右拼接 return img # Sobel 滤波器函数 def sobel_filter(img, K_size=3): # 获取图像尺寸 H, W, C = img.shape # 进行padding pad = K_size // 2 out = padding(img, K_size=3) # 纵向滤波器系数 K_v = np.array([[1., 2., 1.],[0., 0., 0.], [-1., -2., -1.]]) # 横向滤波器系数 K_h = np.array([[1., 0., -1.],[2., 0., -2.],[1., 0., -1.]]) # 进行滤波 tem = out.copy() out_v = out.copy() out_h = out.copy() for h in range(H): for w in range(W): for c in range(C): out_v[pad+h, pad+w, c] = np.sum(K_v * tem[h:h+K_size, w:w+K_size, c], dtype=np.float) out_h[pad+h, pad+w, c] = np.sum(K_h * tem[h:h+K_size, w:w+K_size, c], dtype=np.float) out_v = np.clip(out_v, 0, 255) out_h = np.clip(out_h, 0, 255) out_v = out_v[pad:pad+H, pad:pad+W].astype(np.uint8) out_h = out_h[pad:pad+H, pad:pad+W].astype(np.uint8) return out_v, out_h # 这里需要把图像先灰度化 # 直接用之前的灰度化代码 # 灰度化函数 def BGR2GRAY(img): # 获取图片尺寸 H, W, C = img.shape # 灰度化 out = np.ones((H,W,3)) for i in range(H): for j in range(W): out[i,j,:] = 0.299*img[i,j,0] + 0.578*img[i,j,1] + 0.114*img[i,j,2] out = out.astype(np.uint8) return out # 读取图片 path = 'C:/Users/86187/Desktop/image/' file_in = path + 'cake.jpg' file_out_1 = path + 'cake_sobel_filter_v.jpg' file_out_2 = path + 'cake_sobel_filter_h.jpg' img = cv2.imread(file_in) # 调用函数进行灰度化 img = BGR2GRAY(img) # 调用函数进行sobel滤波 out = sobel_filter(img) # 保存图片 # 纵向 cv2.imwrite(file_out_1, out[0]) cv2.imshow("result", out[0]) # 横向 cv2.imwrite(file_out_2, out[1]) cv2.imshow("result", out[1]) cv2.waitKey(0) cv2.destroyAllWindows() 结果展示
原图 纵向 横向
在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

作者:田纳尔多



图像处理 sobel

需要 登录 后方可回复, 如果你还没有账号请 注册新账号