【问题标题】:How do I create and apply a Gaussian filter in MATLAB without using fspecial, imfilter or conv2?如何在不使用 fspecial、imfilter 或 conv2 的情况下在 MATLAB 中创建和应用高斯滤波器?
【发布时间】:2018-05-02 08:21:36
【问题描述】:

我在 MATLAB 中有以下代码:

I=imread(image);
h=fspecial('gaussian',si,sigma);
I=im2double(I);
I=imfilter(I,h,'conv');
figure,imagesc(I),impixelinfo,title('Original Image after Convolving with gaussian'),colormap('gray');

如何在没有imfilterfspecialconv2 的情况下定义高斯滤波器并将其应用于图像?

【问题讨论】:

  • 如果有人能够使用我的变量输入解决方案,那就太棒了。我现在很困惑
  • 非常感谢,我不能使用 fspecial、imfilter 或 conv2

标签: matlab image-processing


【解决方案1】:

很遗憾,您不能使用图像处理工具箱中的一些内置方法来帮助您完成这项任务。但是,我们仍然可以按照您的要求进行操作,尽管会有些困难。我仍将使用 IPT 中的一些功能来帮助我们完成您的要求。另外,我将假设您的图像是灰度。如果您想为彩色图像执行此操作,我将留给您。


创建高斯蒙版

您可以使用meshgrid 创建一个二维空间坐标网格,该网格与您正在创建的高斯滤镜蒙版大小相同。我将假设N 很奇怪,可以让我的生活更轻松。这将允许空间坐标在蒙版周围对称。

如果你记得,二维高斯可以定义为:

指数前面的比例因子主要与确保高斯下方的面积为 1 相关。我们将以另一种方式处理这种归一化,我们生成高斯系数没有缩放因子,然后简单地将掩码中的所有系数相加,然后将每个元素除以该和以确保单位面积。

假设您要创建一个N x N 过滤器,并使用给定的标准偏差sigma,代码将如下所示,h 代表您的高斯过滤器。

%// Generate horizontal and vertical co-ordinates, where
%// the origin is in the middle
ind = -floor(N/2) : floor(N/2);
[X Y] = meshgrid(ind, ind);

%// Create Gaussian Mask
h = exp(-(X.^2 + Y.^2) / (2*sigma*sigma));

%// Normalize so that total area (sum of all weights) is 1
h = h / sum(h(:));

如果您使用fspecial 进行检查,对于N 的奇数值,您会看到掩码匹配。


过滤图片

过滤图像的基本原理是针对输入图像中的每个像素,获取一个围绕该像素的像素邻域,该像素邻域与您的高斯蒙版大小相同。您使用高斯掩码对这个像素邻域执行逐个元素的乘法,并将所有元素相加。结果总和是输出像素在输出图像中相应空间位置的值。我将使用im2col 将像素邻域转换为列。 im2col 将获取这些列中的每一列并创建一个矩阵,其中每一列代表一个像素邻域。

接下来我们可以做的是获取我们的高斯掩码并将其转换为列向量。接下来,我们将采用此列向量,并将其复制到我们从im2col 的结果中获得的尽可能多的列,以创建...我们将其称为高斯矩阵,因为缺少更好的术语。使用这个高斯矩阵,我们将对该矩阵和im2col 的输出进行逐个元素的乘法。一旦我们这样做了,我们就可以对每一列的所有行求和。进行这种逐个元素相乘的最佳方法是通过bsxfun,稍后我将向您展示如何使用它。

此结果将是您过滤后的图像,但它将是一个向量。您需要使用col2im 将此向量重新整形为矩阵形式,以获取我们过滤后的图像。但是,这种方法的一个小问题是它不会过滤空间掩码超出图像尺寸的像素。因此,您实际上需要用零填充图像的边框,以便我们可以正确地进行过滤。我们可以通过padarray 做到这一点。

因此,我们的代码将如下所示,与您在上面定义的变量一起使用:

N = 5; %// Define size of Gaussian mask
sigma = 2; %// Define sigma here

%// Generate Gaussian mask
ind = -floor(N/2) : floor(N/2);
[X Y] = meshgrid(ind, ind);
h = exp(-(X.^2 + Y.^2) / (2*sigma*sigma));
h = h / sum(h(:));

%// Convert filter into a column vector
h = h(:);

%// Filter our image
I = imread(image);
I = im2double(I);
I_pad = padarray(I, [floor(N/2) floor(N/2)]);
C = im2col(I_pad, [N N], 'sliding');
C_filter = sum(bsxfun(@times, C, h), 1);
out = col2im(C_filter, [N N], size(I_pad), 'sliding');

out 包含在对输入图像I 应用高斯过滤蒙版后过滤后的图像。例如,假设N = 9, sigma = 4。让我们也使用cameraman.tif,这是一个图像,它是 MATLAB 系统路径的一部分。通过使用上述参数,以及图像,这是我们得到的输入和输出图像:

【讨论】:

  • 非常感谢您的帮助!
  • 使用比例因子与事后对内核进行归一化有区别吗?
  • @MathuSumMut 如果我理解你,你想知道是否使用未标准化的内核执行过滤并通过总和进行标准化是否与首先标准化内核相同。如果这是您的问题,那么没有没有区别。你可以做或者你会得到相同的结果。如果您考虑过滤操作,您将每个值乘以(1 / scale)。由于操作的偏好,对元素乘积求和并缩放结果与缩放每个系数和求和完全相同。做你最舒服的事。
  • @MathuSumMut 在数学上,正如 rayryeng 的评论指出的那样,没有区别。但是过滤器 h 通常比要过滤的图像小得多(几百个条目与一百万个条目 [=pixels]),因此归一化 h 在计算上更有效。此外,如果您将相同的过滤器应用于多个图像,您不会忘记标准化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-29
  • 2011-02-15
  • 2021-05-22
  • 1970-01-01
  • 2014-09-18
相关资源
最近更新 更多