在Matlab中使用3x3掩码的中值滤波器二进制图像

时间:2015-02-10 18:52:36

标签: matlab image-processing

我试图在具有给定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];

2 个答案:

答案 0 :(得分:2)

简短的回答是,您可以使用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对你的回答应该非常快,并且比我写的要快得多。但是,如果将其应用于灰度图像,那么我所写的内容将起作用。这适用于二进制和灰度图像。

答案 1 :(得分:1)

如果您只处理二进制图像,则可以通过使用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);