使用 Hamming/Hanning 过滤器平滑二进制蒙版
Smoothing binary mask with Hamming/Hanning filter
我已经使用 MATLAB 的内置 "imfreehand" 定义了二进制掩码。边界内的每个像素都设置为 1,否则设置为 0:
h = imfreehand(handles.fig);
wait(h);
mask = h.creatMask();
然后,我想把mask扩大4个像素,最后加一段代码让边缘更平滑,即mask的边缘从1平滑到0;类似于 Hamming 或 Hanning window。我该怎么做?
所以如果我正确理解你的问题,你有一个二进制掩码,从 h.createMask();
输出,你想扩展边界,然后,本质上,'feather' 掩码边界。
我完成此操作的一种方法是,或多或少像您建议的那样,使用 imdilate()
通过具有适当半径(比如 4)的圆盘来扩大掩模。虽然我不确定它会产生 4 个像素的膨胀。然后我会用一个小内核执行 conv2()
。正如您提到的,它可以由 Hann window 构建。在代码中:
首先,让我们制作您要问的面具:
% test image
I = imread('cameraman.tif'); % Read a sample grayscale image
% From the OP's Question (suggested edit anyway)
fig = figure;
hAx = axes(fig);
hImg = imshow(I, 'Parent', hAx);
h = imfreehand(hAx);
wait(h);
mask = h.createMask();
然后,我们可以通过 strel()
创建一个更大的磁盘来用 imdilate()
扩大掩码
%dilate radius of mask by 4
maskExpanded = imdilate(mask, strel('disk', 4));
最后,我们可以从 hann()
window 制作一个 2D 内核并对我们的扩张掩码进行卷积。您用于 hann()
window 的点数控制羽化量。也就是说,您可以使用 20 而不是 10 来增加羽化。
%hann kernal
hannWindow = hann(10); %10px
% Convert window into 2 dimensions by outer product.
hannKernel = hannWindow * hannWindow';
% Make the kernel sum to 1
hannKernel = hannKernel ./ sum(hannKernel(:));
% Now Apply Smoothing to the enlarged mask
maskSmoothed = conv2(maskExpanded,hannKernel,'same');
为了完整起见,您可以通过以下方式查看效果:
%View
f2 = figure;
f2.Position(3) = 2*f2.Position(3); %twice as wide
f2.Position(1) = f2.Position(1) - f2.Position(3)/2;
f2.Position(4) = 2.1*f2.Position(4); %twice as wide
f2.Position(2) = f2.Position(2) - f2.Position(4)/2;
%axes
ax1 = subplot(2,2,1);
ax2 = subplot(2,2,2);
ax3 = subplot(2,2,3);
ax4 = subplot(2,2,4);
%plots
surf(hannKernel, 'parent', ax1);
imshow(maskExpanded,'parent', ax2);
imshow(maskSmoothed,'parent', ax3);
imshow(maskSmoothed-mask,'parent', ax4);
%titles
title(ax1,'Hann kernel 3d representation');
title(ax2,'Expanded Mask');
title(ax3,'Expanded Mask with convolution');
title(ax4,{'Effect of expansion & convolution';'(difference from original)'});
对我来说,这会产生以下数字:
我想有很多方法可以做到这一点,但我希望我的解决方案有所帮助。
我已经使用 MATLAB 的内置 "imfreehand" 定义了二进制掩码。边界内的每个像素都设置为 1,否则设置为 0:
h = imfreehand(handles.fig);
wait(h);
mask = h.creatMask();
然后,我想把mask扩大4个像素,最后加一段代码让边缘更平滑,即mask的边缘从1平滑到0;类似于 Hamming 或 Hanning window。我该怎么做?
所以如果我正确理解你的问题,你有一个二进制掩码,从 h.createMask();
输出,你想扩展边界,然后,本质上,'feather' 掩码边界。
我完成此操作的一种方法是,或多或少像您建议的那样,使用 imdilate()
通过具有适当半径(比如 4)的圆盘来扩大掩模。虽然我不确定它会产生 4 个像素的膨胀。然后我会用一个小内核执行 conv2()
。正如您提到的,它可以由 Hann window 构建。在代码中:
首先,让我们制作您要问的面具:
% test image
I = imread('cameraman.tif'); % Read a sample grayscale image
% From the OP's Question (suggested edit anyway)
fig = figure;
hAx = axes(fig);
hImg = imshow(I, 'Parent', hAx);
h = imfreehand(hAx);
wait(h);
mask = h.createMask();
然后,我们可以通过 strel()
创建一个更大的磁盘来用 imdilate()
扩大掩码
%dilate radius of mask by 4
maskExpanded = imdilate(mask, strel('disk', 4));
最后,我们可以从 hann()
window 制作一个 2D 内核并对我们的扩张掩码进行卷积。您用于 hann()
window 的点数控制羽化量。也就是说,您可以使用 20 而不是 10 来增加羽化。
%hann kernal
hannWindow = hann(10); %10px
% Convert window into 2 dimensions by outer product.
hannKernel = hannWindow * hannWindow';
% Make the kernel sum to 1
hannKernel = hannKernel ./ sum(hannKernel(:));
% Now Apply Smoothing to the enlarged mask
maskSmoothed = conv2(maskExpanded,hannKernel,'same');
为了完整起见,您可以通过以下方式查看效果:
%View
f2 = figure;
f2.Position(3) = 2*f2.Position(3); %twice as wide
f2.Position(1) = f2.Position(1) - f2.Position(3)/2;
f2.Position(4) = 2.1*f2.Position(4); %twice as wide
f2.Position(2) = f2.Position(2) - f2.Position(4)/2;
%axes
ax1 = subplot(2,2,1);
ax2 = subplot(2,2,2);
ax3 = subplot(2,2,3);
ax4 = subplot(2,2,4);
%plots
surf(hannKernel, 'parent', ax1);
imshow(maskExpanded,'parent', ax2);
imshow(maskSmoothed,'parent', ax3);
imshow(maskSmoothed-mask,'parent', ax4);
%titles
title(ax1,'Hann kernel 3d representation');
title(ax2,'Expanded Mask');
title(ax3,'Expanded Mask with convolution');
title(ax4,{'Effect of expansion & convolution';'(difference from original)'});
对我来说,这会产生以下数字:
我想有很多方法可以做到这一点,但我希望我的解决方案有所帮助。