matlab:将向量划分为固定大小的重叠块

Posted

技术标签:

【中文标题】matlab:将向量划分为固定大小的重叠块【英文标题】:matlab: dividing vector into overlapping chunks of fixed size 【发布时间】:2014-01-03 18:30:47 【问题描述】:

我有一个向量,我想将其拆分为大小为cs 的重叠子向量,以sh 为单位。想象一下输入向量是:

v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]

给定 chunksize 为 4 (cs=4) 和 shift 为 2 (sh=2),结果应如下所示:

[1 2 3 4]
[3 4 5 6]
[5 6 7 8]
[7 8 9 10]
[9 10 11 12]

请注意,输入向量不一定能被chunksize 整除,因此会丢弃一些子向量。有没有什么快速的方法来计算它,而不需要使用例如for 循环? 在相关的post 中,我发现了如何做到这一点,但在考虑非重叠子向量时。

【问题讨论】:

【参考方案1】:

这个呢?首先,我根据cssh 生成起始索引,用于从全长向量中切出单个向量,然后删除所有idx+cs 超过向量长度的索引,然后我正在切片通过arrayfun 取出单个子向量,然后将它们转换为矩阵:

v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;

idx = 1:(cs-sh):length(v);
idx = idx(idx+cs-1 <= length(v))
A = arrayfun(@(i) v(i:(i+cs-1)), idx, 'UniformOutput', false);
cell2mat(A')

例如对于cs=5; sh=3;,这将给出:

idx =

     1     3     5     7


ans =

     1     2     3     4     5
     3     4     5     6     7
     5     6     7     8     9
     7     8     9    10    11

根据值cs; sh 的来源,您可能需要引入一个简单的错误检查,以便cs &gt; 0;sh &lt; cssh &lt; 0 如果您想在两者之间保留一些值,理论上是可能的。

编辑:修复了一个非常小的错误,现在应该针对 sh 和 cs 的不同组合运行。

【讨论】:

我为什么要这样做?它也适用于不同的数字。 idx 只应该给我子向量的起始索引,因此我定义。需要 cs-sh 作为步骤 - 编辑:我尝试使用不同的向量和不同数量的 cssh 并且效果很好。 对于cs=5; sh=3,我假设起始索引是1 4 7,而不是1 3 5 7。如果是这种情况,可以使用idx=1:sh:length(v) 抱歉,我得告诉你,这是错误的。只是重新考虑一下。 1 3 5 7 是正确的索引 - 只需看看我的输出矩阵,它显然是正确的(您可以清楚地看到长度为 5(即 5 列),即 chunksize cs=5)和三个重叠条目(最后三个条目每行是下一行的前三个条目)【参考方案2】:

我想最简单的方法实际上是使用循环。 矢量化解决方案可以更快,但如果结果被正确预分配,循环也应该表现得不错。

v = 1:13
cs = 4;
sh = 2;

myMat = NaN(floor((numel(v) - cs) / sh) + 1,cs);
count = 0;

for t = cs:sh:numel(v)
   count = count+1;
   myMat(count,:) = v(t-cs+1:t);
end

【讨论】:

我不明白为什么这是必要的,尤其是当 Tin 要求没有for-loop 的解决方案时。 @bjoern:我同意丹尼斯的观点,他的解决方案更简单。 Arrayfun 基本上也是一个 for 循环,在这种情况下甚至更慢。 丹尼斯,我认为你的代码仍然有错误 -> v(t-3:t); 这应该是什么?我的意思是其中缺少关于 cs 的内容,现在您总是获取 3 个错误的条目 这也是我第一次更改以纠正它,但它仍然有问题,cs = 5; sh = 2; 给了我矩阵中的三个重叠条目,而不是 2 @DennisJaheruddin:我认为您计算块数的方式不正确,请参阅我的答案。您仅根据sh 计算要为myMat 预分配的行数,同时还应包括cs。对于cs = 10sh = 2,它应该只产生 2 行,而在你的情况下它预分配 5 行。【参考方案3】:

您可以通过以下方式使用函数bsxfun

v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;

A = v(bsxfun(@plus,(1:cs),(0:sh:length(v)-cs)'));

这是它的工作原理。 bsxfun 在 2 个数组上应用一些基本功能,如果输入的大小不合适,则执行一些类似 repmat 的功能。在这种情况下,我生成第一个块的索引,并添加每个块的偏移量。由于一个输入是行向量,另一个是列向量,因此结果是一个矩阵。最后,当使用矩阵索引向量时,结果是一个矩阵,这正是您所期望的。

而且它是单行的,(几乎)总是很有趣:)。

【讨论】:

cs = 5;sh = 2; 试试,会给你三个而不是两个(两个是正确的,因为 sh=2)重叠条目 @bjoern 正如我在对您的问题的评论中提到的,您的解决方案确实给出了不同的结果。但是,这并不一定意味着它是正确的。 好的,现在我明白你指的是什么了。我 100% 确定 sh 描述了重叠条目的数量,但现在我看到你们都将其称为另一种衡量标准。对不起,我的错,真的一定错过了哦,我现在才看到描述不是唯一的,因为发布的例子是模棱两可的 one-liner bsxfun(几乎)总是值得 +1!【参考方案4】:

您有信号处理工具箱吗?那么命令是buffer。先看一下裸输出:

buffer(v, 4, 2)

ans =
     0     1     3     5     7     9    11
     0     2     4     6     8    10    12
     1     3     5     7     9    11    13
     2     4     6     8    10    12     0

这显然是正确的想法,只需稍作调整即可为您提供所需的输出:

[y z] = buffer(v, 4, 2, 'nodelay');
y.'

ans =
     1     2     3     4
     3     4     5     6
     5     6     7     8
     7     8     9    10
     9    10    11    12

也就是说,请考虑按列保留向量,因为这样可以更好地匹配大多数用例。例如,每个窗口的平均值只是矩阵的mean,因为默认是按列排列的。

【讨论】:

我喜欢使用这些没有人知道它已经在工具箱中的小宝石。问题是它可能会在最后一帧中留下部分数据,但这取决于您想要实现的目标。【参考方案5】:

您可以通过ndgrid 完成此操作:

>> v=1:13; cs=4; sh=2;
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1)
>> chunks = X+Y
chunks =
     1     2     3     4
     3     4     5     6
     5     6     7     8
     7     8     9    10
     9    10    11    12

second syntax of the colon operator (j:i:k) 的好处是,如果您打算丢弃额外的条目,则不必精确计算 k(例如,1:2:6 给出 [1 3 5]),如这个问题。它会自动转到j+m*i,其中m = fix((k-j)/i)

不同的测试:

>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y
chunks =
     1     2     3     4     5
     4     5     6     7     8
     7     8     9    10    11
    10    11    12    13    14

然后将形成一个带有v=1:17 的新行。这会根据需要处理所有情况吗?

【讨论】:

以上是关于matlab:将向量划分为固定大小的重叠块的主要内容,如果未能解决你的问题,请参考以下文章

AVS3编码块划分

基本分页内存管理

根据内容大小将 HTML 划分为页面

使用 MATLAB 将图像分成大小相等的块并使用 Gabor 滤波器

非连续内存分配

网络划分子网js算法