【问题标题】:Median filter binary image with 3x3 mask in MatlabMatlab中具有3x3掩码的中值滤波二值图像
【发布时间】:2015-02-11 03:49:07
【问题描述】:

我正在尝试在具有给定 3x3 掩码的 2D 二值图像上使用 medfilt2 function

很遗憾,medfilt2 没有将掩码作为参数。

否则如何median filter 带有 3x3 蒙版的图像?

例如:

binary_image = [0 0 0 0 0 0 0 0;
                0 1 0 1 0 1 1 0;
                0 1 1 1 1 1 1 0;
                0 1 0 1 1 1 0 0;
                0 0 0 1 1 0 1 0;
                0 1 1 1 0 1 1 0;
                0 1 0 1 1 1 1 0;
                0 0 0 0 0 0 0 0];

mask = [1 0 1;
        0 1 1 ;
        1 1 1];

【问题讨论】:

  • 你能自己实现一个中值过滤器并添加掩码功能吗?应该不会太难。
  • 那么您是否只想计算mask 中有效值的中位数?
  • 是的 rayryeng。 eigenchris,我正在寻找 matlab 中的内置方法
  • @James - 您可以使用nlfilter 并指定在邻域上运行的自定义函数。我会写一个答案。

标签: matlab image-processing


【解决方案1】:

简短的回答是您可以使用nlfilter,您可以在其中指定对图像中的像素邻域执行的操作。具体来说,您可以像这样调用nlfilter

B = nlfilter(A, [m n], fun);

A 将是一个图像,[m n] 将指定您正在考虑的像素邻域的大小 (m x n),fun 是一个应用于每个邻域的函数。输入是m x n 补丁,输出应该是单个值。假设masklogical,而你的图片存储在im,那么你要做的就是:

out = nlfilter(im, size(mask), @(x) median(x(mask)));

x(mask) 访问那些在邻域内有效的位置,然后您将median 应用于这些值以检索每个邻域在有效位置上的中值。

但是,众所周知,nlfilter 很慢。我建议您在这里查看我的帖子:Matlab Median Filter Code

这会非常快速地根据第一原理计算median 过滤器。我会把它留给你通读这篇文章并理解我做了什么。但是,为了您的目的,您必须做的修改是删除im2col 的输出中与掩码中的无效值相对应的那些行。因此,请执行以下操作:

N = size(mask,1); %// Size of mask - Assume that # of rows = # of columns
im_pad = padarray(im, [floor(N/2) floor(N/2)]);
im_col = im2col(im_pad, [N N], 'sliding');

%// Get locations in mask that don't count towards getting median
invalid_rows = ~(mask(:));

%// Remove from column neighbourhood matrix
im_col(invalid_rows,:) = [];

%// Determine new median index
val = floor((N*N - sum(invalid_rows))/2) + 1;

%// apply algorithm as normal
sorted_cols = sort(im_col, 1, 'ascend');
med_vector = sorted_cols(val, :);
out = col2im(med_vector, [N N], size(im_pad), 'sliding');

invalid_rows 将掩码展开为单列,就像im2col 对每个像素邻域所做的那样,然后我们反转掩码以确定那些不应计入最终中位数的位置。此外,val 确定了 索引,即我们开始移除未分析的邻域中的像素后需要从中获取中值的位置。


如果输入是二进制图像,那么 eigenchris 给你的答案应该会非常快,而且比我写的要快得多。但是,如果将其应用于灰度图像,那么我所写的将起作用。这适用于二值和灰度图像。

【讨论】:

  • 不错的快速中值滤波器实现。 :)
【解决方案2】:

如果您只处理二进制图像,您可以通过使用conv2() 函数执行卷积来解决此问题。

逻辑是,由于掩码中有 7 个有效像素,如果卷积结果中的某个像素的值大于或等于 4,我们就知道中位数为 1。否则中位数必须是0

一般来说,如果你的掩码中有n 有效像素,我们可以通过将卷积矩阵除以n 的结果四舍五入得到掩码中位数。

n = sum(sum(mask));                 % number of valid pixels in the mask
maskFlipped = fliplr(flipud(mask)); % flip mask so it faces the right way
convResult = conv2(binary_image,maskFlipped,'same');
maskedMedianFilterResult = round(convResult/n);

【讨论】:

  • 很好的答案。您也可以使用maskFlipped = mask(end:-1:1, end:-1:1); 实现翻转。这样,我们可以避免使用两个嵌套的函数调用。 +1 顺便说一句。
猜你喜欢
  • 2013-09-20
  • 1970-01-01
  • 2015-02-16
  • 2011-07-07
  • 2011-10-02
  • 2021-04-17
  • 1970-01-01
  • 2023-03-24
  • 2018-07-21
相关资源
最近更新 更多