Matlab 中具有 3x3 掩码的中值滤波器二值图像
Median filter binary image with 3x3 mask in Matlab
我正在尝试在具有给定 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];
如果您只处理二进制图像,则可以通过使用 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);
简短的回答是您可以使用 nlfilter
,您可以在其中指定对图像中的像素邻域执行的操作。具体来说,您可以这样调用 nlfilter
:
B = nlfilter(A, [m n], fun);
A
将是一个图像,[m n]
将指定您正在考虑的像素邻域的大小 (m x n
),而 fun
是一个函数适用于每个街区。输入是 m x n
补丁,输出应该是单个值。假设mask
为logical
,而你的图片存储在im
,你只需要:
out = nlfilter(im, size(mask), @(x) median(x(mask)));
x(mask)
访问那些在邻域内有效的位置,然后您可以将 median
应用于这些值以检索有效位置上每个邻域的中值。
但是,众所周知,nlfilter
速度很慢。我建议您在此处查看我的 post:Matlab Median Filter Code .
这根据第一原理非常快速地计算 median
过滤器。我将留给您通读 post 并理解我所做的事情。但是,为了您的目的,您需要做的是在 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
确定了 new 索引,一旦我们开始删除未分析的邻域中的像素,我们就需要从中获取中位数。
如果输入是二值图像,那么eigenchris给你的回答应该很快,比我写的快多了。但是,如果将其应用于灰度图像,那么我所写的内容将起作用。这适用于二进制和灰度图像。
我正在尝试在具有给定 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];
如果您只处理二进制图像,则可以通过使用 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);
简短的回答是您可以使用 nlfilter
,您可以在其中指定对图像中的像素邻域执行的操作。具体来说,您可以这样调用 nlfilter
:
B = nlfilter(A, [m n], fun);
A
将是一个图像,[m n]
将指定您正在考虑的像素邻域的大小 (m x n
),而 fun
是一个函数适用于每个街区。输入是 m x n
补丁,输出应该是单个值。假设mask
为logical
,而你的图片存储在im
,你只需要:
out = nlfilter(im, size(mask), @(x) median(x(mask)));
x(mask)
访问那些在邻域内有效的位置,然后您可以将 median
应用于这些值以检索有效位置上每个邻域的中值。
但是,众所周知,nlfilter
速度很慢。我建议您在此处查看我的 post:Matlab Median Filter Code .
这根据第一原理非常快速地计算 median
过滤器。我将留给您通读 post 并理解我所做的事情。但是,为了您的目的,您需要做的是在 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
确定了 new 索引,一旦我们开始删除未分析的邻域中的像素,我们就需要从中获取中位数。
如果输入是二值图像,那么eigenchris给你的回答应该很快,比我写的快多了。但是,如果将其应用于灰度图像,那么我所写的内容将起作用。这适用于二进制和灰度图像。