使用 blockproc 或 im2col 在图像上重叠滑动 window?
Overlapping sliding window over an image using blockproc or im2col?
我必须将 dct2
应用到图像的小 windows,最好使用重叠的 window。
我发现 Matlab 中有两个函数可以使这成为可能 blockproc
和 im2col
。我也无法理解,希望得到一些说明。
blockproc
可用于使用 BorderSize
和 TrimBorder
参数在滑动 window 上实现我的功能。
B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false');
我意识到这会创建一个 [64 + 2*5, 64 + 2*5]
块并在每个块上应用函数 @fun
。但是由于我无法在调试中进入我的函数 @fun
以验证正确的操作,所以我不能确定这就是我需要的。
我上面的代码是否符合我的需要?我知道我在 B
中得到了一个串联结果,但它应该在重叠的滑块上。这会达到我需要的吗?
第二个是im2col
。 im2col(A,[m n],block_type)
会把块分成m×n块,然后按列排列,那么每一列就是一个块?如果是这样,如何控制重叠?如果每个块都是一列,我能否在每一列上成功应用 dct2
函数?因为我怀疑它会将向量作为输入?
如能提供一些说明,我们将不胜感激。
好的,这是一个相当复杂的问题。我会尝试将其分解成不同的部分,并分别回答每个问题。
问题 #1
blockproc
can be used to implement my function on a sliding window using the BorderSize
and TrimBorder
arguments.
B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false');
I realize that this creates a block of [64 + 2*5, 64 + 2*5]
and applies the function @fun
on each block. But since I cannot go into my function @fun
in debugging to verify proper operation I cannot be sure this is what I need. Is my above code correct for what I need? I know that I get a concatenated result in B
but it should be on a overlapping sliding block. Will this achieve what I need?
在使用 blockproc
进行试验后,这确实是正确的,您可以使用它来进行滑动邻域处理。但是,您将需要一个额外的标志,即 PadPartialBlocks
。此标志的目的是,如果您要提取位于图像外边缘的块并且无法制作指定大小的块,这将对该部分块进行零填充以使其符合到相同的大小。这是一个使用滑动 windows 的小例子。假设我们有一个矩阵:
>> 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
像素,其中 M
和 N
是您想要的水平和垂直边框大小。这将使我们能够在原始块的上方和下方捕获 M
个像素,在原始块的左侧和右侧捕获 N
个像素。
因此,对于A
中1的值,如果块大小是1 x 1,这意味着元素只包含1,如果我们的BorderSize
是1 x 1 . 这意味着我们的最终块将是:
0 0 0
0 1 6
0 2 7
因为我们的块大小是 1,下一个块将以 6 为中心,我们将得到一个 3 x 3 的像素网格等等。将 TrimBorder
设置为 false
也很重要,这样我们就可以保留那些在扩展块时最初捕获的像素。默认设置为 true
。最后,PadPartialBlocks
就是true
,保证所有块的大小都一样。当你运行以上代码时,我们得到的结果是:
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
您可以使用 nlfilter
验证我们得到相同的结果,我们可以将平均值应用于 3 x 3 滑动邻域:
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
因此,如果您想正确使用blockproc
进行滑动操作,您需要注意如何分别设置块大小和边框大小。在这种情况下,一般规则是始终将您的块大小设置为 1 x 1,并允许 BorderSize
指定您想要的每个块的大小。具体来说,对于大小为 K x K
的块,您可以将 BorderSize
分别设置为 floor(K/2) x floor(K/2)
。如果 K
是奇数,事情就会变得简单。
例如,如果您想要在滑动 window 基础上进行 5 x 5
均值过滤操作,您可以将 BorderSize
设置为 [2 2]
,如 K = 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
用大小为 5 x 5 的 nlfilter
复制它也得到:
C = 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
我在做一些计时测试,似乎在这种情况下使用 blockproc
比 nlfilter
快。
问题 #2
The second is im2col
. im2col(A,[m n],block_type)
will divide the block into m by n blocks and arrange them in columns, so each column is a block? If so, how is the overlapping controlled? And if each block is a column can I successfully apply the dct2
function on each column? Because I doubt it will take vectors as input?
你是正确的,im2col
将每个像素邻域或块转换为单个列,这些列的串联形成输出矩阵。您可以通过 block_type
参数控制块是重叠还是不同。指定 distinct
或 sliding
(默认)来控制它。您还可以使用 m
和 n
.
控制每个邻域的大小
但是,如果您的目标是应用 dct2
和 im2col
的输出,那么您将得不到想要的结果。具体来说,dct2
将二维数据中每个数据点的空间位置考虑在内,并用作转换的一部分。通过将每个像素邻域转换为单个列,每个块最初存在的 2D 空间关系现在消失了。 dct2
需要 2D 空间数据,但您会指定 1D 数据。因此,im2col
可能不是您要查找的内容。如果我理解你想要的是正确的,你会想使用 blockproc
来代替。
希望对您有所帮助!
我必须将 dct2
应用到图像的小 windows,最好使用重叠的 window。
我发现 Matlab 中有两个函数可以使这成为可能 blockproc
和 im2col
。我也无法理解,希望得到一些说明。
blockproc
可用于使用 BorderSize
和 TrimBorder
参数在滑动 window 上实现我的功能。
B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false');
我意识到这会创建一个 [64 + 2*5, 64 + 2*5]
块并在每个块上应用函数 @fun
。但是由于我无法在调试中进入我的函数 @fun
以验证正确的操作,所以我不能确定这就是我需要的。
我上面的代码是否符合我的需要?我知道我在 B
中得到了一个串联结果,但它应该在重叠的滑块上。这会达到我需要的吗?
第二个是im2col
。 im2col(A,[m n],block_type)
会把块分成m×n块,然后按列排列,那么每一列就是一个块?如果是这样,如何控制重叠?如果每个块都是一列,我能否在每一列上成功应用 dct2
函数?因为我怀疑它会将向量作为输入?
如能提供一些说明,我们将不胜感激。
好的,这是一个相当复杂的问题。我会尝试将其分解成不同的部分,并分别回答每个问题。
问题 #1
blockproc
can be used to implement my function on a sliding window using theBorderSize
andTrimBorder
arguments.
B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false');
I realize that this creates a block of
[64 + 2*5, 64 + 2*5]
and applies the function@fun
on each block. But since I cannot go into my function@fun
in debugging to verify proper operation I cannot be sure this is what I need. Is my above code correct for what I need? I know that I get a concatenated result inB
but it should be on a overlapping sliding block. Will this achieve what I need?
在使用 blockproc
进行试验后,这确实是正确的,您可以使用它来进行滑动邻域处理。但是,您将需要一个额外的标志,即 PadPartialBlocks
。此标志的目的是,如果您要提取位于图像外边缘的块并且无法制作指定大小的块,这将对该部分块进行零填充以使其符合到相同的大小。这是一个使用滑动 windows 的小例子。假设我们有一个矩阵:
>> 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
像素,其中 M
和 N
是您想要的水平和垂直边框大小。这将使我们能够在原始块的上方和下方捕获 M
个像素,在原始块的左侧和右侧捕获 N
个像素。
因此,对于A
中1的值,如果块大小是1 x 1,这意味着元素只包含1,如果我们的BorderSize
是1 x 1 . 这意味着我们的最终块将是:
0 0 0
0 1 6
0 2 7
因为我们的块大小是 1,下一个块将以 6 为中心,我们将得到一个 3 x 3 的像素网格等等。将 TrimBorder
设置为 false
也很重要,这样我们就可以保留那些在扩展块时最初捕获的像素。默认设置为 true
。最后,PadPartialBlocks
就是true
,保证所有块的大小都一样。当你运行以上代码时,我们得到的结果是:
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
您可以使用 nlfilter
验证我们得到相同的结果,我们可以将平均值应用于 3 x 3 滑动邻域:
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
因此,如果您想正确使用blockproc
进行滑动操作,您需要注意如何分别设置块大小和边框大小。在这种情况下,一般规则是始终将您的块大小设置为 1 x 1,并允许 BorderSize
指定您想要的每个块的大小。具体来说,对于大小为 K x K
的块,您可以将 BorderSize
分别设置为 floor(K/2) x floor(K/2)
。如果 K
是奇数,事情就会变得简单。
例如,如果您想要在滑动 window 基础上进行 5 x 5
均值过滤操作,您可以将 BorderSize
设置为 [2 2]
,如 K = 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
用大小为 5 x 5 的 nlfilter
复制它也得到:
C = 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
我在做一些计时测试,似乎在这种情况下使用 blockproc
比 nlfilter
快。
问题 #2
The second is
im2col
.im2col(A,[m n],block_type)
will divide the block into m by n blocks and arrange them in columns, so each column is a block? If so, how is the overlapping controlled? And if each block is a column can I successfully apply thedct2
function on each column? Because I doubt it will take vectors as input?
你是正确的,im2col
将每个像素邻域或块转换为单个列,这些列的串联形成输出矩阵。您可以通过 block_type
参数控制块是重叠还是不同。指定 distinct
或 sliding
(默认)来控制它。您还可以使用 m
和 n
.
但是,如果您的目标是应用 dct2
和 im2col
的输出,那么您将得不到想要的结果。具体来说,dct2
将二维数据中每个数据点的空间位置考虑在内,并用作转换的一部分。通过将每个像素邻域转换为单个列,每个块最初存在的 2D 空间关系现在消失了。 dct2
需要 2D 空间数据,但您会指定 1D 数据。因此,im2col
可能不是您要查找的内容。如果我理解你想要的是正确的,你会想使用 blockproc
来代替。
希望对您有所帮助!