Prewitt滤波器
Author: Tian YJ
Prewitt是一种常用的检测图像边缘的滤波器,它分为横向和纵向算子,分别用于检测纵向和横向的边缘(注意:横向形式的滤波器检测图像的纵向边缘,纵向形式的滤波器检测图像的横向边缘)。
纵向:
横向:
注意比较记忆 Prewitt 滤波器和 Sobel 滤波器,它们在形式和功能上十分相近,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
# Prewitt 滤波函数
def prewitt(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., -1., -1.],[0., 0., 0.], [1., 1., 1.]])
# 横向滤波器系数
K_h = np.array([[-1., 0., 1.],[-1., 0., 1.],[-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_prewitt_filter_v.jpg'
file_out_2 = path + 'cake_prewitt_filter_h.jpg'
img = cv2.imread(file_in)
# 调用函数进行灰度化
img = BGR2GRAY(img)
# 调用函数进行sobel滤波
out = prewitt(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()
结果展示
Prewitt滤波器和Sobel滤波器比较
原图 | 纵向prewitt | 横向prewitt |
---|---|---|
原图 | 纵向sobel | 横向sobel |
从实验结果,我们可以观察到,对比使用 Sobel算子 和 Prewitt算子 进行图像边缘检测 ,Sobel滤波器能够获得更加清晰明亮的边缘。