什么是滤波
图像滤波:
- 图像滤波是图像处理中的一种基本操作,通过卷积操作对图像进行处理,以改变或增强图像的特征。
- 滤波的目的通常包括去除噪声、平滑图像、增强边缘等。
卷积核:
- 卷积核是滤波过程中使用的一个小矩阵,它在图像上滑动并与图像进行卷积操作,从而产生新的图像。
- 卷积核的不同形状和数值可以实现不同的滤波效果。
滤波目的:
- 高通滤波:用于强调图像中的高频信息,例如边缘和细节。
- 低通滤波:用于去除图像中的高频信息,主要用于平滑图像和去噪。
- 中通滤波:用于获取特定频率范围内的信号。
- 阻带滤波:用于去除特定频率范围内的信号。
滤波分析:
- 时域分析:直接对信号在时间域上的变化进行分析。
- 频域分析:通过对信号进行傅里叶变换等操作,将信号转换到频率域,以便更好地理解信号的频率特性。
卷积操作
卷积是通过卷积核与图像之间逐点相乘求和的操作。卷积核是一个小矩阵,通过滑动在图像上与图像每个局部区域进行卷积。
卷积可用于包括平滑锐化,边缘检测等图像处理任务。
# 定义卷积核
kernel = np.ones((3,3),np.float32) /9
# 卷积操作
kernel_img = cv2.filter2D(img,-1,kernel)
kernel
: 卷积核,这里是一个3x3的平均滤波器。它是一个二维的数值矩阵,用于在卷积操作中与图像的局部区域进行逐点相乘并求和。在这里,每个元素的值为1/9,是为了对图像进行平均化处理
image
: 输入图像。-1
: 输出图像的深度,设置为-1表示输出图像与输入图像有相同的深度。kernel
: 卷积核。
平滑操作
平滑操作是通过卷积核的权重对图像进行平均化,来降低图像的高频噪声,实现图像平滑化。
平滑滤波器:
均值滤波器:
- 作用:均值滤波器是一种平滑滤波器,用于降低图像中的噪声并平滑图像。它是一种简单的线性滤波器,通过对图像的局部区域取平均值来替代中心像素的值。
- 操作过程: 对于每个像素,取其周围邻域的像素值的平均值,然后将该平均值赋给中心像素。
高斯滤波器:
- 作用: 高斯滤波器也是一种平滑滤波器,主要用于去除图像中的噪声和平滑图像。与均值滤波器不同,高斯滤波器对邻域内的像素进行加权平均,权重由高斯分布决定。
- 操作过程: 对于每个像素,取其周围邻域的像素值进行加权平均,权重由高斯分布确定。中心像素的权重最大,周围像素的权重逐渐减小。
smoothed_img = cv2.GaussianBlur(img,(5,5),0)
image
: 输入图像。(5, 5)
: 卷积核的大小,这里是一个5x5的高斯核。0
: 高斯核的标准差,设为0表示使用默认值,由卷积核的大小自动计算。
锐化操作
锐化操作指突出图像中的细节和边缘
锐化滤波器通常包括一些正负值,以增强边缘对比度
sharpened_kernel = np.array([[-1,0,-1],[-1,5,-1],[-1,0,-1]])
sharpened_img = cv2.filter2D(img,-1,sharpened_kernel)
image
: 输入图像。-1
: 输出图像的深度,设置为-1表示输出图像与输入图像有相同的深度。- sharpened_kernel: 锐化核,这里是一个锐化滤波器。通过这个核,图像的边缘和细节会更加突出。
梯度操作
梯度操作用于检测图像中的边缘,通过计算图像中每个像素梯度值。
常见使用Sobel滤波器,通过在水平和垂直方向上进行卷积计算梯度。
gra_x = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
gra_y = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
gra_mag = np.sqrt(gra_x**2 + gra_y**2)
image
: 输入图像。cv2.CV_64F
: 输出图像的深度,64位浮点数。1, 0
: Sobel核的水平方向导数。0, 1
: Sobel核的垂直方向导数。ksize=3
: Sobel核的大小,这里是3x3。
import cv2
import numpy as np
# 读取图像
image = cv2.imread('example_image.jpg', cv2.IMREAD_GRAYSCALE)
# 定义卷积核
kernel = np.ones((3, 3), np.float32) / 9 # 3x3平均滤波器
# 卷积操作
convolved_image = cv2.filter2D(image, -1, kernel)
# 平滑操作 - 高斯滤波
smoothed_image = cv2.GaussianBlur(image, (5, 5), 0)
# 锐化操作
sharpened_image = cv2.filter2D(image, -1, np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]))
# 梯度操作 - Sobel滤波器
gradient_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
gradient_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
gradient_magnitude = np.sqrt(gradient_x**2 + gradient_y**2)
中值滤波和双边滤波
中值滤波(Median Filtering):
- 任务: 主要用于去除图像中的椒盐噪声或脉冲噪声,这些噪声可能导致图像中出现明显的黑白点。
- 操作过程: 对图像的每个像素,用它周围邻域中所有像素的中值替代原始像素值。
- 优点: 对于椒盐噪声效果较好,能够在保留图像边缘信息的同时有效地去除噪声。
双边滤波(Bilateral Filtering):
- 任务: 主要用于平滑图像,同时保留图像的边缘信息。
- 操作过程: 双边滤波不仅考虑空间上的邻域关系,还考虑像素值之间的相似性。它在滤波时对邻域内像素的权重进行加权,以保留边缘。
- 优点: 在去噪的同时,能够有效地保留图像的细节。
# 双边滤波,参数分别为图像,邻域直径,颜色空间标准差,灰度空间标准差
double_img = cv2.bilateralFilter(img,9,75,75)
邻域直径(Diameter of Neighborhood):
- 作用: 它定义了在滤波过程中考虑的像素邻域的大小。
- 含义: 邻域直径决定了在空间上对每个像素考虑的周围像素的数量。邻域直径越大,考虑的邻域范围就越广。
颜色空间标准差(Standard Deviation in Color Space):
- 作用: 它定义了在颜色空间上考虑像素相似性的程度。
- 含义: 颜色空间标准差控制了在颜色相似性方面的权重。较大的标准差意味着更广泛的颜色范围被考虑,从而使得颜色相差较大的像素在滤波过程中得到较小的权重。
灰度值空间标准差(Standard Deviation in Greyscale Space):
- 作用: 它定义了在灰度值空间上考虑像素相似性的程度。
- 含义: 灰度值空间标准差控制了在灰度值相似性方面的权重。较大的标准差意味着更广泛的灰度值范围被考虑,使得灰度相差较大的像素在滤波过程中得到较小的权重。
import cv2
img = cv2.imread("example.jpg")
# 中值滤波,核大小为5*5
median_img = cv2.medianBlur(img,5)
# 双边滤波,参数分别为图像,邻域直径,颜色空间标准差,灰度空间标准差
double_img = cv2.bilateralFilter(img,9,75,75)
锐化算子
Laplacian锐化
拉普拉斯锐化简单来说,就是依据周围像素灰度带动中心点像素改变。当邻域灰度像素低于其所在领域内其他灰度像素平均值,其中心点灰度像素也会进一步降低;当邻域灰度像素高于其所在领域内其他灰度像素平均值,其中心点灰度像素也会进一步提高。
cv.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
参数说明:
- src:输入图像,可以是灰度图像,也可以是多通道的彩色图像
- ddepth:输出图片的数据深度:
- dst:输出图像,大小和类型与 src 相同
- ksize:计算二阶导数滤波器的孔径大小,必须为正奇数,可选项
- scale:缩放比例因子,可选项,默认值为 1
- delta:输出图像的偏移量,可选项,默认值为 0
- borderType:边界扩充的类型,注意不支持对侧填充(BORDER_WRAP)
同样,拉普拉斯锐化还有种方法,就是依据自定义卷积核。
kernel = np.array([[0,-1,0],[-1,4,-1],[0,-1,0]],np.float32)
lap_img = cv2.filter2D(img,kernel,cv2.CV_64F)
USM锐化
USM(非锐化掩膜),就是先通过低通滤波筛选出低频分量,再用原图减去低频分量得到高频分量,最后将原图加上高频分量叠加就得到了非锐化掩模。
- 首先使用低通滤波器平滑原图像得到低频分量图像:s = 低通滤波;
- 原图像减去低频分量图像,产生的差值,高频分量图像称为模板:m = f - s;
- 将模板图像乘以一个系数,加到原图像中,得到锐化后的图像:g = f + k × m
- f为原图,k为锐化系数,m为剩下的高频分量。
import cv2
import numpy as np
def unsharp_masking(image, weight=1.5):
# Step 1: Apply Gaussian blur
blurred = cv2.GaussianBlur(image, (0, 0), 3)
# Step 2: Calculate the unsharp mask
mask = image - blurred
# Step 3: Enhance edges by adding the mask back to the original image
sharpened = image + weight * mask
# Clip pixel values to be in the valid range [0, 255]
sharpened = np.clip(sharpened, 0, 255).astype(np.uint8)
return sharpened
# Load an example image
image = cv2.imread('example_image.jpg')
# Convert the image to grayscale (optional, depending on your input)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply the unsharp masking
sharpened_image = unsharp_masking(gray_image)
# Display the results
cv2.imshow('Original Image', gray_image)
cv2.imshow('Sharpened Image', sharpened_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
src = cv2.imread(r"1.jpg")
dst = cv2.GaussianBlur(src, (5, 5), 0)
dst = cv2.addWeighted(src, 2, dst, -1, 0)
cv2.imshow("src show", src)
cv2.imshow("dst show", dst)
cv2.waitKey(0)
改进点:
mask阈值设定abs(mask)->threshold?1:0
梯度算子
以下卷积核的大小是固定的。
Sobel算子和Scharr算子
度时)的优化。Laplacian 是求二阶导数。
import cv2
import numpy as np
# 读取图像
image = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)
# 使用Sobel算子进行边缘检测
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 计算合并后的梯度幅值和方向
gradient_magnitude = np.sqrt(sobel_x**2 + sobel_y**2)
gradient_direction = np.arctan2(sobel_y, sobel_x) * (180 / np.pi)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Sobel X', sobel_x)
cv2.imshow('Sobel Y', sobel_y)
cv2.imshow('Gradient Magnitude', gradient_magnitude.astype(np.uint8))
cv2.imshow('Gradient Direction', gradient_direction.astype(np.uint8))
cv2.waitKey(0)
cv2.destroyAllWindows()
Scharr算子是Sobel算子的一种改进版本,用于更精确地估计图像梯度。Scharr算子对噪声的敏感性较低,相对于Sobel算子,它具有更强的边缘响应,相较于sobel算子,scharr算子也有着自适应的卷积核大小。
import cv2
# 使用Scharr算子进行边缘检测
scharr_x = cv2.Scharr(image, cv2.CV_64F, 1, 0)
scharr_y = cv2.Scharr(image, cv2.CV_64F, 0, 1)
# 计算合并后的梯度幅值和方向
gradient_magnitude_scharr = np.sqrt(scharr_x**2 + scharr_y**2)
gradient_direction_scharr = np.arctan2(scharr_y, scharr_x) * (180 / np.pi)
# 显示结果
cv2.imshow('Scharr X', scharr_x)
cv2.imshow('Scharr Y', scharr_y)
cv2.imshow('Gradient Magnitude (Scharr)', gradient_magnitude_scharr.astype(np.uint8))
cv2.imshow('Gradient Direction (Scharr)', gradient_direction_scharr.astype(np.uint8))
cv2.waitKey(0)
cv2.destroyAllWindows()
Laplacian算子
上面锐化部分已经讲过了。
Prewitt算子
Prewitt算子和Roberts算子没有单独函数,他们同时都是自定义卷积核进行计算,Prewitt算子类似于Sobel算子,分为水平和垂直两个方向。Roberts算子采用2*2的卷积核。
import cv2
import numpy as np
# 读取图像
image = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)
# 使用Prewitt算子进行边缘检测
prewitt_x = cv2.filter2D(image, cv2.CV_64F, np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]]))
prewitt_y = cv2.filter2D(image, cv2.CV_64F, np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]]))
# 计算合并后的梯度幅值和方向
gradient_magnitude_prewitt = np.sqrt(prewitt_x**2 + prewitt_y**2)
gradient_direction_prewitt = np.arctan2(prewitt_y, prewitt_x) * (180 / np.pi)
# 显示结果
cv2.imshow('Prewitt X', prewitt_x)
cv2.imshow('Prewitt Y', prewitt_y)
cv2.imshow('Gradient Magnitude (Prewitt)', gradient_magnitude_prewitt.astype(np.uint8))
cv2.imshow('Gradient Direction (Prewitt)', gradient_direction_prewitt.astype(np.uint8))
cv2.waitKey(0)
cv2.destroyAllWindows()
Roberts算子
import cv2
import numpy as np
# 读取图像
image = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)
# 使用Roberts算子进行边缘检测
roberts_x = cv2.filter2D(image, cv2.CV_64F, np.array([[1, 0], [0, -1]]))
roberts_y = cv2.filter2D(image, cv2.CV_64F, np.array([[0, 1], [-1, 0]]))
# 计算合并后的梯度幅值和方向
gradient_magnitude_roberts = np.sqrt(roberts_x**2 + roberts_y**2)
gradient_direction_roberts = np.arctan2(roberts_y, roberts_x) * (180 / np.pi)
# 显示结果
cv2.imshow('Roberts X', roberts_x)
cv2.imshow('Roberts Y', roberts_y)
cv2.imshow('Gradient Magnitude (Roberts)', gradient_magnitude_roberts.astype(np.uint8))
cv2.imshow('Gradient Direction (Roberts)', gradient_direction_roberts.astype(np.uint8))
cv2.waitKey(0)
cv2.destroyAllWindows()