使用blockproc或im2col在图像上重叠滑动窗口?

时间:2015-03-13 19:42:12

标签: image matlab image-processing image-segmentation dct

我必须将dct2应用于我的图片的小窗口,最好是使用重叠窗口。

我发现Matlab中有两个函数可以使blockprocim2col成为可能。我也很难理解,并希望得到一些澄清。

blockproc可用于使用BorderSizeTrimBorder参数在滑动窗口上实现我的函数。

B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false');

我意识到这会创建一个[64 + 2*5, 64 + 2*5]块并在每个块上应用函数@fun。但是因为我无法在调试中进入我的函数@fun以验证正确的操作,所以我不能确定这是我需要的。 我的上述代码是否符合我的要求?我知道我在B得到一个连续的结果,但它应该在一个重叠的滑块上。这会实现我的需求吗?

第二个是im2colim2col(A,[m n],block_type)将块分成m个n块,并将它们排列成列,因此每列是一个块?如果是这样,重叠如何控制?如果每个块都是一列,我可以在每列上成功应用dct2函数吗?因为我怀疑它会将向量作为输入吗?

非常感谢一些澄清。

1 个答案:

答案 0 :(得分:9)

好的,这是一个非常复杂的问题。我将尝试将其分解为单独的部分,并将分别回答每个问题。

问题#1

  

blockproc可用于使用BorderSizeTrimBorder参数在滑动窗口上实现我的函数。

     

B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false');

     

我意识到这会创建一个[64 + 2*5, 64 + 2*5]块并在每个块上应用函数@fun。但是因为我无法在调试中进入我的函数@fun以验证正确的操作,所以我不能确定这是我需要的。我的上述代码是否符合我的要求?我知道我在B得到一个连续的结果,但它应该在一个重叠的滑块上。这会实现我的需求吗?

在试验blockproc后,这确实是正确的,您可以使用它来进行滑动邻域处理。但是,您需要一个额外的标记PadPartialBlocks。此标志的目的是,如果您要提取一个块,您在图像的外边缘处,并且您无法创建指定大小的块,这将填充此部分块这样它就符合相同的尺寸。这是一个小例子,可以使用滑动窗口。假设我们有一个矩阵,以便:

>> A = reshape(1:25,5,5)

A =

     1     6    11    16    21
     2     7    12    17    22
     3     8    13    18    23
     4     9    14    19    24
     5    10    15    20    25

我们想说我们想要获取上面矩阵中每个3 x 3重叠邻域的平均值,并将那些超出矩阵边界的元素填零。您可以使用blockproc执行此操作:

B = blockproc(A, [1 1], @(x) mean(x.data(:)), 'BorderSize', [1 1], 'TrimBorder', false, 'PadPartialBlocks', true);

需要注意的重要一点是,块大小(在这种情况下为1 x 1,BorderSize为1 x 1,其设置与您预期的不同3 x 3块。为了解决这种情况的原因,我们需要进一步了解BorderSize的工作原理。对于块的给定中心,BorderSize允许您捕获超出原始大小的块的维度的值/像素。对于那些超出矩阵边界的位置,我们默认将这些位置填充为零。 BorderSize允许我们更多地捕获2M + 2N像素,其中MN是您想要的水平和垂直边框大小。这样,我们就可以在原始块的上方和下方捕获M个像素,并在原始块的左侧和右侧捕获更多像素{.1}}。

因此,对于N中的值1,如果块大小为1 x 1,则表示该元素仅包含1,并且如果我们的A为1 x 1。意味着我们的最后一块将是:

BorderSize

因为我们的块大小是1,所以下一个块将以6为中心,我们将获得3 x 3像素网格,依此类推。将0 0 0 0 1 6 0 2 7 设置为TrimBorder也很重要,这样我们就可以保留在扩展块时最初捕获的像素。默认设置为false。最后,truePadPartialBlocks以确保所有块的大小相同。运行上面的代码时,我们得到的结果是:

true

您可以使用nlfilter验证我们是否可以获得相同的结果,我们可以将均值应用于3 x 3滑动邻域:

B =

    1.7778    4.3333    7.6667   11.0000    8.4444
    3.0000    7.0000   12.0000   17.0000   13.0000
    3.6667    8.0000   13.0000   18.0000   13.6667
    4.3333    9.0000   14.0000   19.0000   14.3333
    3.1111    6.3333    9.6667   13.0000    9.7778

因此,如果要正确使用C = nlfilter(A, [3 3], @(x) mean(x(:))) C = 1.7778 4.3333 7.6667 11.0000 8.4444 3.0000 7.0000 12.0000 17.0000 13.0000 3.6667 8.0000 13.0000 18.0000 13.6667 4.3333 9.0000 14.0000 19.0000 14.3333 3.1111 6.3333 9.6667 13.0000 9.7778 进行滑动操作,则需要分别设置块大小和边框大小。在这种情况下,一般规则是始终将块大小设置为1 x 1,并允许blockproc指定所需的每个块的大小。具体而言,对于大小为BorderSize的块,您可以将K x K分别设置为BorderSize。如果floor(K/2) x floor(K/2)很奇怪,这会让事情变得简单。

例如,如果您希望在滑动窗口的基础上进行K均值过滤操作,则应将5 x 5设置为BorderSize[2 2]和{{1} }。因此,你会这样做:

K = 5

使用大小为5 x 5的floor(K/2) = 2进行复制也会产生:

B = blockproc(A, [1 1], @(x) mean(x.data(:)), 'BorderSize', [2 2], 'TrimBorder', false, 'PadPartialBlocks', true)

B =

    2.5200    4.5600    7.2000    6.9600    6.1200
    3.6000    6.4000   10.0000    9.6000    8.4000
    4.8000    8.4000   13.0000   12.4000   10.8000
    4.0800    7.0400   10.8000   10.2400    8.8800
    3.2400    5.5200    8.4000    7.9200    6.8400

我正在进行一些时序测试,似乎在此上下文中使用的nlfilterC = nlfilter(A, [5 5], @(x) mean(x(:))) C = 2.5200 4.5600 7.2000 6.9600 6.1200 3.6000 6.4000 10.0000 9.6000 8.4000 4.8000 8.4000 13.0000 12.4000 10.8000 4.0800 7.0400 10.8000 10.2400 8.8800 3.2400 5.5200 8.4000 7.9200 6.8400 更快。

问题#2

  

第二个是blockprocnlfilter将块分成m个n块,并将它们排列成列,因此每列是一个块?如果是这样,重叠如何控制?如果每个块都是一列,我可以在每列上成功应用im2col函数吗?因为我怀疑它会将向量作为输入吗?

你是正确的im2col(A,[m n],block_type)将每个像素邻域或块转换为单个列,这些列的串联形成输出矩阵。您可以通过dct2参数控制块是重叠还是不同。指定im2colblock_type(默认值)以控制此操作。您还可以使用distinctsliding控制每个社区的大小。

但是,如果您的目标是将mn的输出结合使用,那么您将无法获得所需内容。具体而言,dct2将2D数据中每个数据点的空间位置考虑在内,并用作转换的一部分。通过将每个像素邻域变换为单个列,最初存在于每个块的2D空间关系现在消失了。 im2col期望2D空间数据,但您将指定1D数据。因此,dct2可能不是您正在寻找的。如果我理解你想要什么,你会想要使用dct2


希望这有帮助!