我必须将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)会将块划分为n个块,并将它们按列排列,所以每一列都是块吗?如果是的话,如何控制重叠?如果每个块都是一个列,那么我能成功地在每个列上应用dct2函数吗?因为我怀疑它是否会以向量作为输入?
如能作出一些澄清,将不胜感激。
发布于 2015-03-13 20:23:09
好吧,这是一个相当复杂的问题。我将试着把它分成不同的部分,并分别回答每一个问题。
问题1
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假设我们想取上面矩阵中每个3x3重叠邻域的平均值,然后将那些超越矩阵边界的元素进行零填充。你可以用blockproc来做这个
B = blockproc(A, [1 1], @(x) mean(x.data(:)), 'BorderSize', [1 1], 'TrimBorder', false, 'PadPartialBlocks', true);需要注意的是,块大小(在本例中为1x1)和BorderSize (1x1)的设置与您对3x3块的预期不同。为了了解为什么会出现这种情况,我们需要进一步了解BorderSize是如何工作的。对于给定的块中心,BorderSize允许您捕获超出最初大小块的维度的值/像素。对于那些超出矩阵边界的位置,默认情况下我们会将这些位置设置为零。BorderSize允许我们更多地捕获2M + 2N像素,其中M和N是您想要的水平和垂直边框大小。这将使我们能够捕获更多的M像素,包括原来块的上方和下面的像素,以及在原始块的左边和右边的N更多的像素。
因此,对于A中的值1,如果块大小为1x1,这意味着元素仅由1组成,如果我们的BorderSize为1x1,这意味着我们的最后一个块是:
0 0 0
0 1 6
0 2 7因为我们的块体大小是1,下一个街区将集中在6,我们会得到一个3x3像素网格,以此类推。同样重要的是,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验证我们是否得到了相同的结果,其中我们可以将平均值应用于3x3滑动街区:
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进行滑动操作,则需要注意如何分别设置块大小和边框大小。在这种情况下,一般规则是始终将块大小设置为1x1,并允许BorderSize指定每个块的大小。具体来说,对于大小为K x K的块,可以分别将BorderSize设置为floor(K/2) x floor(K/2)。如果K古怪的话,这会让事情变得简单。
例如,如果您希望在滑动窗口的基础上进行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使用大小为5x5的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
第二个是
im2col。im2col(A,[m n],block_type)会将块划分为n个块,并将它们按列排列,所以每一列都是块吗?如果是的话,如何控制重叠?如果每个块都是一个列,那么我能成功地在每个列上应用dct2函数吗?因为我怀疑它是否会以向量作为输入?
您是正确的,因为im2col将每个像素邻域或块转换为单个列,这些列的级联形成输出矩阵。您可以控制这些块是重叠的还是由block_type参数区分的。指定distinct或sliding (这是默认的)来控制这一点。您还可以使用m和n控制每个社区的大小。
但是,如果您的目标是将dct2应用于im2col的输出,那么您将无法得到所需的东西。具体来说,dct2考虑到了2D数据中每个数据点的空间位置,并将其用作转换的一部分。通过将每个像素邻域转换成一个列,原来每个块的2D空间关系已经消失。dct2需要2D空间数据,但是您需要指定一维数据。因此,im2col可能不是您要找的东西。如果我正确地理解了您想要的内容,那么您将希望使用blockproc。
希望这能有所帮助!
https://stackoverflow.com/questions/29040688
复制相似问题