python - 在频域中应用低通和拉普拉斯滤波器
问题描述
我正在尝试在频域中应用这两个滤波器。首先是低通滤波器,其次是拉普拉斯高斯滤波器。虽然我的图像被正确过滤,但输出是环绕的。此外,输出图像被移动(看起来好像图像已被复制)。
这是输入和输出: 过滤器之前和之后
这是我的代码:
# Padding the image
image = Pad(image)
# The mask for low-pass filter
rows, cols = image.shape
center = (rows, cols)
crow, ccol = rows/2, cols/2
Low_mask = np.zeros((rows, cols), dtype=np.float32)
Low_mask[crow-cutoff:crow+cutoff, ccol-cutoff:ccol+cutoff] = 1
# Shifting the mask (low-pass)
Low_mask_dft = np.fft.fft2(Low_mask)
Low_mask_dft_shift = np.fft.fftshift(Low_mask_dft)
# Shifting the image
image_dft = np.fft.fft2(image)
image_dft_shift = np.fft.fftshift(image_dft)
# Performing the convolution
image_fdomain = np.multiply(image_dft_shift, Low_mask_dft_shift)
# Shifting the mask (LOG)
LOGmask = GaussKernel(center)
LOGmask_dft = np.fft.fft2(LOGmask)
LOGmask_dft_shift = np.fft.fftshift(LOGmask_dft)
# Performing the convolution
frequency_image = np.multiply(image_fdomain, LOGmask_dft_shift)
# Now, return the image back to it's original form
result = np.fft.ifftshift(frequency_image)
result = np.fft.ifft2(result)
result = np.absolute(result)
return result
解决方案
您需要做的是确定您正在使用的边界条件。
频域(对于离散数据)的自然一个是循环/循环卷积,这意味着循环边界条件。
一旦您设置并相应地准备数据,一切都会按要求进行。
我创建了小型 MATLAB 脚本(您将能够轻松地在 Python 中复制它)来展示它应该如何完成。
主要的是:
numRows = size(mI, 1);
numCols = size(mI, 2);
% Convolution in Spatial Domain
% Padding for Cyclic Convolution
mOGaussianRef = conv2(PadArrayCircular(mI, kernelRadius), mGaussianKernel, 'valid');
mOLogRef = conv2(PadArrayCircular(mI, kernelRadius), mLog, 'valid');
% Convolution in Frequency Domain
% Padding and centering of the Kernel
mGaussianKernel(numRows, numCols) = 0;
mGaussianKernel = circshift(mGaussianKernel, [-kernelRadius, -kernelRadius]);
mLog(numRows, numCols) = 0;
mLog = circshift(mLog, [-kernelRadius, -kernelRadius]);
mOGaussian = ifft2(fft2(mI) .* fft2(mGaussianKernel), 'symmetric');
mOLog = ifft2(fft2(mI) .* fft2(mLog), 'symmetric');
convErr = norm(mOGaussianRef(:) - mOGaussian(:), 'inf');
disp(['Gaussian Kernel - Cyclic Convolution Error (Infinity Norm) - ', num2str(convErr)]);
convErr = norm(mOLogRef(:) - mOLog(:), 'inf');
disp(['LoG Kernel - Convolution Error (Infinity Norm) - ', num2str(convErr)]);
结果是:
Gaussian Kernel - Cyclic Convolution Error (Infinity Norm) - 3.4571e-06
LoG Kernel - Convolution Error (Infinity Norm) - 5.2154e-08
即它做了它应该做的事情。
我的Stack Overflow Q50614085 Github Repository中的完整代码。
如果您想了解如何处理其他边界条件(或线性卷积),请查看FreqDomainConv.m
.
推荐阅读
- sqlalchemy - 有没有办法使用 SQLAlchemy 在 Teradata 表上创建主索引?
- c++ - 向量指针奇怪的结果
- python-3.x - python 正则表达式函数用特殊字符分割字符串
- regex - 是否可以匹配字符串中所有出现的模式,具有给定的开始和结束?
- java - 在 linux 上使用 ant 编译时出错:错误的版本 52.0,应该是 50.0
- scala - spark数据框中orderBy的列列表
- postgresql - PostgreSQL 使用 COALESCE 或其他条件表达式来设置字段
- spring - Spring Data MongoDB 与原生 MongoDB
- sql - 需要对查找多个外键值的 SQL 查询使用“VLOOKUP”类型的操作 - SOS
- python - 无法使用 Python 请求将所有数据存储到 Django 数据库中