图像带通滤波在频域中保留中频成分(如纹理、边缘等细节),抑制低频(平滑区域)和高频(噪声、微小细节)。以下通过python代码分别实现常规和gpu加速图像带通滤波。
1. 图像带通滤波算法
代码说明
ideal_bandpass_mask:理想环形,边界陡峭,可能导致振铃效应。gaussian_bandpass_mask:高斯平滑过渡,更符合自然图像的频域特性,推荐使用。
radius_low:抑制低频(例如平滑区域),值越小去除越多低频。radius_high:抑制高频(例如噪声、微小细节),值越小保留的纹理越粗糙。- 根据图像尺寸调整,通常
radius_low 取 20~50,radius_high 取 80~150(对 512×512 图像)。
- 使用
cv2.imshow 展示每个步骤的结果,所有窗口可调整大小(WINDOW_NORMAL)。
pip install numpy opencv-python
import numpy as npimport cv2defideal_bandpass_mask(shape, radius_low, radius_high):"""生成理想带通掩膜(环形)""" rows, cols = shape crow, ccol = rows // 2, cols // 2 mask = np.zeros((rows, cols), dtype=np.float32)for i in range(rows):for j in range(cols): r = np.sqrt((i - crow) ** 2 + (j - ccol) ** 2)if radius_low <= r <= radius_high: mask[i, j] = 1.0return maskdefgaussian_bandpass_mask(shape, radius_low, radius_high):"""生成高斯带通掩膜(平滑过渡,减少振铃)""" rows, cols = shape crow, ccol = rows // 2, cols // 2 mask = np.zeros((rows, cols), dtype=np.float32)for i in range(rows):for j in range(cols): r = np.sqrt((i - crow) ** 2 + (j - ccol) ** 2)# 带通 = 高斯低通(外半径) - 高斯低通(内半径) low_pass_outer = np.exp(-(r ** 2) / (2 * (radius_high ** 2))) low_pass_inner = np.exp(-(r ** 2) / (2 * (radius_low ** 2))) mask[i, j] = low_pass_outer - low_pass_innerreturn maskdefnormalize_display(img):"""将任意浮点数图像归一化到 0-255 并转为 uint8,用于 OpenCV 显示""" img_min, img_max = img.min(), img.max()if img_max - img_min > 1e-8: normalized = (img - img_min) / (img_max - img_min) * 255else: normalized = np.zeros_like(img)return np.uint8(normalized)# ------------------- 1. 读取图像 -------------------image_path = "lena.jpg"# 请换成你自己的图片路径,若无则用生成的测试图img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)# 转为 float32 以便进行傅里叶变换image_float = img.astype(np.float32)# ------------------- 2. 频域变换 -------------------f = np.fft.fft2(image_float)fshift = np.fft.fftshift(f)magnitude_spectrum = np.log(np.abs(fshift) + 1) # 对数压缩便于显示# ------------------- 3. 设计带通滤波器 -------------------rows, cols = img.shaperadius_low, radius_high = 30, 80# 根据图像尺寸调整# mask = ideal_bandpass_mask((rows, cols), radius_low, radius_high)mask = gaussian_bandpass_mask((rows, cols), radius_low, radius_high) # 推荐高斯掩膜# ------------------- 4. 应用滤波器 -------------------fshift_filtered = fshift * maskf_ishift = np.fft.ifftshift(fshift_filtered)image_filtered = np.fft.ifft2(f_ishift)image_filtered = np.real(image_filtered) # 取实部# 超出 0-255 的像素进行裁剪(由于浮点误差可能轻微超出)image_filtered = np.clip(image_filtered, 0, 255).astype(np.uint8)# ------------------- 5. 计算被移除的频率成分(可选) -------------------fshift_removed = fshift * (1 - mask)f_ishift_removed = np.fft.ifftshift(fshift_removed)image_removed = np.real(np.fft.ifft2(f_ishift_removed))image_removed = np.clip(image_removed, 0, 255).astype(np.uint8)# ------------------- 6. 用 OpenCV 显示结果 -------------------# 准备可显示的幅度谱magnitude_disp = normalize_display(magnitude_spectrum)magnitude_filtered_disp = normalize_display(np.log(np.abs(fshift_filtered) + 1))mask_disp = normalize_display(mask)cv2.namedWindow("Original", cv2.WINDOW_NORMAL)cv2.imshow("Original", img)cv2.namedWindow("Original Spectrum", cv2.WINDOW_NORMAL)cv2.imshow("Original Spectrum", magnitude_disp)cv2.namedWindow("Bandpass Mask", cv2.WINDOW_NORMAL)cv2.imshow("Bandpass Mask", mask_disp)cv2.namedWindow("Filtered Spectrum", cv2.WINDOW_NORMAL)cv2.imshow("Filtered Spectrum", magnitude_filtered_disp)cv2.namedWindow("Bandpass Filtered Image", cv2.WINDOW_NORMAL)cv2.imshow("Bandpass Filtered Image", image_filtered)cv2.namedWindow("Removed (Low+High Freq)", cv2.WINDOW_NORMAL)cv2.imshow("Removed (Low+High Freq)", image_removed)print("按任意键关闭所有窗口...")cv2.waitKey(0)cv2.destroyAllWindows()
Original:
Removed (Low+High Freq):
Original Spectrum:
Bandpass Mask:
Filtered Spectrum:
Bandpass Filtered Image:
2. GPU加速的高性能图像带通滤波算法
以下是使用GPU加速的高性能图像带通滤波算法实现,利用PyTorch调用CUDA/cuFFT库,对RGB或灰度图像进行快速滤波。
代码说明
在频域设计一个高斯带通滤波器:
该滤波器保留频率范围介于 low_cutoff 和 high_cutoff 之间的信息,抑制低频(大尺度亮度变化)和高频(微小噪声/纹理)。
- 使用
torch.fft 调用 cuFFT 库,在 GPU 上执行二维复数 FFT,复杂度 对 4K 图像可在毫秒级完成。 - 滤波器在频域直接点乘,避免空域大卷积核的计算开销。
low_cutoff 设置高通截止:值越小,抑制的低频范围越大(如去除雾霾/光照不均)。high_cutoff 设置低通截止:值越小,图像越模糊;值越大保留更多纹理。- 典型范围:
low_cutoff = 5~20,high_cutoff = 30~150。需根据图像分辨率调整(频率单位为像素/周期,最大有效值为图像尺寸的一半)。
import torchimport numpy as npfrom PIL import Imageimport matplotlib.pyplot as pltdefcreate_gaussian_bandpass_filter(shape, low_cutoff, high_cutoff, device): rows, cols = shape crow, ccol = rows // 2, cols // 2# 构建频率网格(原点移至中心) u = torch.arange(rows, device=device) - crow v = torch.arange(cols, device=device) - ccol U, V = torch.meshgrid(u, v, indexing='ij') D = torch.sqrt(U**2 + V**2).float()# 两个高斯低通滤波器 low_pass_high = torch.exp(- (D**2) / (2 * (high_cutoff**2))) # 截止频率高,保留更多低频 low_pass_low = torch.exp(- (D**2) / (2 * (low_cutoff**2))) # 截止频率低,保留更少低频 bandpass = low_pass_high - low_pass_low # 带通 = 低通1 - 低通2return bandpassdefbandpass_filter_gpu(image, low_cutoff, high_cutoff, device='cuda'):# 转换为GPU张量,归一化至[0,1]if image.ndim == 2: img_tensor = torch.from_numpy(image).float().to(device) / 255.0 img_tensor = img_tensor.unsqueeze(0) # (1, H, W)else: # RGB img_tensor = torch.from_numpy(image).float().to(device) / 255.0 img_tensor = img_tensor.permute(2, 0, 1) # (C, H, W)# 快速傅里叶变换 (cuFFT) fft = torch.fft.fft2(img_tensor, norm='backward') fft_shift = torch.fft.fftshift(fft)# 生成带通滤波器 H, W = img_tensor.shape[-2], img_tensor.shape[-1] filter_2d = create_gaussian_bandpass_filter((H, W), low_cutoff, high_cutoff, device) filter_ = filter_2d.unsqueeze(0) # (1, H, W) 适配多通道广播# 频域相乘 filtered_fft = fft_shift * filter_# 逆傅里叶变换 fft_ishift = torch.fft.ifftshift(filtered_fft) result = torch.fft.ifft2(fft_ishift, norm='backward').real# 裁剪到[0,1]并转换回[0,255] uint8 result = torch.clamp(result, 0, 1)if result.shape[0] == 3: # RGB result = result.permute(1, 2, 0)else: result = result.squeeze(0) result_np = (result.cpu().numpy() * 255).astype(np.uint8)return result_npif __name__ == "__main__":# 检查GPU可用性 device = 'cuda'if torch.cuda.is_available() else'cpu' print(f"使用设备: {device}")# 读取图像(请替换为实际路径) img_path = "input.jpg" img = np.array(Image.open(img_path).convert('RGB'))# 执行带通滤波# 低截止频率10:抑制频率低于10的纹理(大尺度结构)# 高截止频率80:抑制频率高于80的噪声/细节 filtered_img = bandpass_filter_gpu(img, low_cutoff=10, high_cutoff=80, device=device)# 显示原图与滤波结果 plt.figure(figsize=(10, 5)) plt.subplot(121), plt.imshow(img), plt.title('Original') plt.subplot(122), plt.imshow(filtered_img), plt.title('Bandpass Filtered') plt.show()# 保存结果 Image.fromarray(filtered_img).save("bandpass_output.jpg")

扩展优化建议
- 混合精度:在创建滤波器和 FFT 前使用
torch.half 可进一步提速,但需注意精度损失。 - 批处理:多张图像可将 batch 维度合并,一次性执行 FFT 提升吞吐量。
- 预计算滤波器:若多张图像尺寸相同且滤波参数不变,滤波器可复用。