我必须将dct2
应用于我的图片的小窗口,最好是使用重叠窗口。
我发现Matlab中有两个函数可以使blockproc
和im2col
成为可能。我也很难理解,并希望得到一些澄清。
blockproc
可用于使用BorderSize
和TrimBorder
参数在滑动窗口上实现我的函数。
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
函数吗?因为我怀疑它会将向量作为输入吗?
非常感谢一些澄清。
答案 0 :(得分:9)
好的,这是一个非常复杂的问题。我将尝试将其分解为单独的部分,并将分别回答每个问题。
blockproc
可用于使用BorderSize
和TrimBorder
参数在滑动窗口上实现我的函数。
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
像素,其中M
和N
是您想要的水平和垂直边框大小。这样,我们就可以在原始块的上方和下方捕获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
。最后,true
为PadPartialBlocks
以确保所有块的大小相同。运行上面的代码时,我们得到的结果是:
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
我正在进行一些时序测试,似乎在此上下文中使用的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
将块分成m个n块,并将它们排列成列,因此每列是一个块?如果是这样,重叠如何控制?如果每个块都是一列,我可以在每列上成功应用im2col
函数吗?因为我怀疑它会将向量作为输入吗?
你是正确的im2col(A,[m n],block_type)
将每个像素邻域或块转换为单个列,这些列的串联形成输出矩阵。您可以通过dct2
参数控制块是重叠还是不同。指定im2col
或block_type
(默认值)以控制此操作。您还可以使用distinct
和sliding
控制每个社区的大小。
但是,如果您的目标是将m
与n
的输出结合使用,那么您将无法获得所需内容。具体而言,dct2
将2D数据中每个数据点的空间位置考虑在内,并用作转换的一部分。通过将每个像素邻域变换为单个列,最初存在于每个块的2D空间关系现在消失了。 im2col
期望2D空间数据,但您将指定1D数据。因此,dct2
可能不是您正在寻找的。如果我理解你想要什么,你会想要使用dct2
。
希望这有帮助!