在没有 nfilter 函数的情况下进行滑动 window(大小 MxN)以进行局部和自适应操作,如局部阈值?

Make sliding window (size MxN) without nfilter function to do local and adaptive operation like local thresholding?

我需要一个 matlab 代码来使 MxN 滑动 window 没有 nfilter() 功能来进行自适应和局部操作,如自适应阈值。

例如,我想在每个矩形(MxN window中实现OTSU的阈值方法 graythresh() ) 不是 pixelpixel.

我写了这段代码,但它有一些问题:

im=imread('cameraman.tif');
imshow(im);figure,title('original image')
M=64; %lenght of window
N=64; %width of widow
[row,col]=size(im);
out=zeros(M,N);
out1=zeros(row,N);

for i=1:N:row
     for j=1:M:col
         mask=im(i:i+N-1,j:j+M-1);
         bw=im2bw(mask,graythresh(mask));
         out=[out,bw];imshow(out),title('output')
     end
%      out1=[out1;out];
%      out=zeros(M,N);
end
% figure,imshow(out1)     

输入图像: http://i.stack.imgur.com/L0EZo.png

输出图像: http://i.stack.imgur.com/dmP9j.png

这是对我原来 post 的完全重写,因为我现在知道你想要做什么。您的代码确实有效,因为您想要提取 M x N distinct 邻域,对每个邻域执行 Otsu 算法,然后将这些邻域设置为输出图像。

但是,您没有正确构建最终图像。您正在按列堆叠邻域,但是您需要做的是,一旦到达图像的末尾列,就需要向下移动到下一行。要使您的代码正常工作,最简单的方法是在遍历列的循环中创建另一个矩阵,当您到达末尾时,将该矩阵逐行连接到输出图像。我已经从您的代码中删除了一些绒毛,以便快速进入我的观点:

im=imread('cameraman.tif');
M=64; %//height of window
N=64; %//width of widow
[row,col]=size(im);
out = []; %// Create output image

for i=1:N:row
     out1 = []; %// Inner matrix
     for j=1:M:col
         mask=im(i:i+N-1,j:j+M-1);
         bw=im2bw(mask,graythresh(mask));
         out1 = [out1 bw]; %// Concatenate column-wise
     end
     out = [out; out1]; %// Take inner matrix and concatenate row-wise
end
figure; subplot(1,2,1); imshow(im); title('Original Image');
subplot(1,2,2); imshow(out); title('Thresholded Image');

我将原始图像和阈值图像放在同一张图中,我们得到:


但是,因为在您上面的评论中提到您有 blockproc 可用,我建议您使用它来尽量减少您编写的代码量。 blockproc 允许您处理图像中不同的像素邻域。对于每个像素邻域,您可以对它们做任何您想做的事。在我们的例子中,我们想将 Otsu 的算法应用于每个块并对其进行阈值处理。您完全可以在一行中实现上述结果代码:

out = blockproc(im, [64 64], @(x) im2bw(x.data, graythresh(x.data)));

im 是输入图像,out 是输出图像。第二个参数告诉您每个块有多大,第三个函数是您编写的应用于每个块的自定义函数。此函数的输入是一个结构,其中 data 是一个结构元素,它为您提供图像中的块。因此,您可以像上面一样在相同的方法中使用 im2bwgraythresh,但是您将使用 data 字段来执行此操作。


更进一步,您说您还有 colfilt 可用,它与 blockproc 做同样的事情,但它会重塑图像,以便将邻域块放入列中,将函数应用于每一列,然后将图像重建回其原始尺寸。

因此:

out = colfilt(im, [64 64], 'distinct', @(x) im2bw(x, graythresh(x)));

你可以看到上面的语法和blockproc几乎一样,但是这里我们必须指定'distinct'标志来告诉colfilt我们想要不同的邻域,而不是重叠的。此外,众所周知 colfiltblockproc 快(请参阅上面关于 colfilt - link 的文档)。