Image 使用blockproc或im2col在图像上重叠滑动窗口?
我必须将dct2应用于图像的小窗口,最好使用重叠窗口 我发现Matlab中有两个函数可以使blockproc和im2col成为可能。我在理解这两个方面都有困难,希望能澄清一下 blockproc可用于使用BorderSize和TrimBorder参数在滑动窗口上实现my函数Image 使用blockproc或im2col在图像上重叠滑动窗口?,image,matlab,image-processing,image-segmentation,dct,Image,Matlab,Image Processing,Image Segmentation,Dct,我必须将dct2应用于图像的小窗口,最好使用重叠窗口 我发现Matlab中有两个函数可以使blockproc和im2col成为可能。我在理解这两个方面都有困难,希望能澄清一下 blockproc可用于使用BorderSize和TrimBorder参数在滑动窗口上实现my函数 B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false'); 我意识到这会创建一个[64+2*5,64+2*5]块,并在每个块上应用@fun
B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false');
我意识到这会创建一个[64+2*5,64+2*5]块,并在每个块上应用@fun函数。但由于我无法进入调试中的@fun函数来验证正确的操作,我不能确定这是我所需要的。
我的上述代码是否符合我的需要?我知道我在B中得到了一个串联的结果,但它应该在一个重叠的滑块上。这能满足我的需要吗
第二种是im2col。im2colA,[mn],block_type将块划分为m×n块,并将它们排列在列中,因此每列都是一个块?如果是,如何控制重叠?如果每个块都是一列,我能在每个列上成功地应用dct2函数吗?因为我怀疑它会接受向量作为输入
如能澄清,将不胜感激 好的,这是一个相当复杂的问题。我将试着把它分成几个部分,并分别回答每个问题 问题1 blockproc可用于使用BorderSize和TrimBorder参数在滑动窗口上实现my函数
B = blockproc(A,[64,64],fun,'BorderSize',[5,5], 'TrimBorder', 'false');
B=blockprocA[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执行此操作:
需要注意的是,块大小(在本例中为1 x 1)和边框大小(在本例中为1 x 1)的设置与预期的3 x 3块不同。为了探究为什么会出现这种情况,我们需要进一步了解BorderSize是如何工作的。对于块的给定中心,BorderSize允许您捕获超出原始大小块尺寸的值/像素。对于超出矩阵边界的位置,默认情况下,我们将这些位置填充为零。BorderSize允许我们捕获更多2M+2N像素,其中M和N是您想要的水平和垂直边界大小。这将允许我们在原始块的上方和下方再捕获M个像素,在原始块的左侧和右侧再捕获N个像素
因此,对于A中的值1,如果块大小为1 x 1,这意味着元素仅由1组成,如果边界大小为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
您可以使用我们可以将平均值应用于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分别设置为floorK/2 x floorK/2。如果K是个古怪的人,事情就会变得简单
例如,如果希望在滑动窗口的基础上进行5 x 5的平均值过滤操作,可以将BorderSize设置为[2 2],即K=5和floorK/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 wit复制此文件
h尺寸为5 x 5时,还可得出:
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。im2colA,[mn],block_type将块划分为m×n块,并将它们排列在列中,因此每列都是一个块?如果是,如何控制重叠?如果每个块都是一列,我能在每个列上成功地应用dct2函数吗?因为我怀疑它会接受向量作为输入
您是正确的,im2col将每个像素邻域或块转换为一列,这些列的串联形成输出矩阵。可以通过“块类型”参数控制块是重叠的还是不同的。指定默认用于控制此操作的“独特”或“滑动”。您还可以使用m和n控制每个邻域的大小
但是,如果您的目标是将dct2与im2col的输出一起应用,那么您将无法得到所需的结果。具体而言,dct2将每个数据点在2D数据中的空间位置考虑在内,并用作变换的一部分。通过将每个像素邻域转换为单个列,每个块原来存在的二维空间关系现在消失了。dct2需要2D空间数据,但您可以指定1D数据。因此,im2col可能不是您想要的。如果我正确理解了您的需求,您将希望使用blockproc
希望这有帮助 非常感谢@rayryeng的出色和详细的解释。当你可以得到这样一个详细而有用的回复时,赏金被添加并给予:@FarazKhan-哦,非常感谢你的赏金!你根本不需要!顺便说一句,这与我所说的不能在滑动窗口方法中使用blockproc与你之前的问题相矛盾。。。因为在我做了一些实验之后,你当然可以。。。你只需要在参数上胡闹。这是一个非常有趣的问题,我也从中学到了一些东西。另外,谢谢你提出这个问题!在使用上述代码之后,我相信blockproc产生的输出对于我的分类器来说并不理想。每个块应该生成一个1x200大小的向量,但我得到的是一个1x1600大小的向量。我发现这是blockproc的工作,因为它连接了4个块的结果,ul_输出、ll_输出、ur_输出、lr_输出,所以它将区域划分为更小的块,然后连接在一起,这对我的分类器不起作用。因为我需要每个块单独的输出。我试图更改内部函数设置,但失败。@FarazKhan-您是否可以发布另一个问题,并更详细地谈谈您在做什么?我也许能帮你回答你的问题。我同意,有很多话要说。我将开始一个新问题: