MATLAB中矩阵中斑块的圆周移位

mar*_*man 9 matlab matrix

如何在矩阵的每个补丁索引中循环元素而不显式迭代每个补丁?

例

我可以想到执行此循环的迭代方法是使用MATLAB的circshift函数.我可以遍历矩阵中的每个MxN补丁,并对该补丁的元素执行循环移位.

(注意:circshift采用一个数组并将第一个(或第k个)索引移动到后面,将所有内容向前移动以腾出空间.使用矩阵,您只需向量化它,移动它并重新形状,利用MATLAB的列 -主要线性索引)

如果我要迭代我更大的每个MxN窗口(j*M xk*N为整数j,k)矩阵,那将是很好的.但是,我希望能够避免for循环并利用MATLAB的矢量化代码一次性完成这项工作.

通过示例进行一次完整迭代(某些矩阵B中的2x2补丁)将是:

B =           -->   B =           -->   B =           -->   B =
[ 5 6 7 8 ]   -->   [ 5 6 7 8 ]   -->   [ 6 5 8 7 ]   -->   [ 6 5 8 7 ]
[ 5 6 7 8 ]   -->   [ 6 5 8 7 ]   -->   [ 6 5 8 7 ]   -->   [ 5 6 7 8 ]
[ 5 6 7 8 ]   -->   [ 5 6 7 8 ]   -->   [ 6 5 8 7 ]   -->   [ 6 5 8 7 ]
[ 5 6 7 8 ]   -->   [ 6 5 8 7 ]   -->   [ 6 5 8 7 ]   -->   [ 5 6 7 8 ]
Run Code Online (Sandbox Code Playgroud)

任何想法如何使这种转变工作没有明确迭代每个补丁?我觉得线性索引是关键,但我不知道为什么.只要每个补丁元素都在每个补丁索引中结束,我也不关心旋转的顺序.

提前致谢!

编辑:这是一个使用for循环来复制和粘贴的玩具实现来演示我正在寻找的东西.应该包含在答案中的唯一for循环是k-iterator(控制最终需要进行的移位数)

A = repmat(1:4, 4, 1); % Input matrix

% k represents the total number of shifts to be made
for k = 1:4

    % Iterate through each patch
    for i = 1:2:size(A,1)
        for j = 1:2:size(A,2)
            tmp = A(i:i+1,j:j+1); % Isolate specific patch

            % Circularly shift the vectorized patch, reshape it to a matrix
            % and insert it back into the original matrix
            A(i:i+1,j:j+1) = reshape(circshift(tmp(:),1), 2, 2);
        end
    end
    display(A) % Display each completely shifted iteration
end
Run Code Online (Sandbox Code Playgroud)

hba*_*rts 2

一个简单的方法是使用blockproc图像处理工具箱中的函数。blockproc将图像(或者一般来说:矩阵)划分为定义大小的块,并对每个块应用一个函数:

B = blockproc(A,blockSize,fun);
Run Code Online (Sandbox Code Playgroud)

使用blockproc,我们可以将矩阵划分A2 x 2多个补丁,并对每个补丁应用循环移位。请注意,blockproc创建一个block_struct数据类型并调用fun(block_struct). 要获取数据,只需使用data结构体的字段即可。这将导致

B = blockproc(A, [2,2], @(x)reshape(circshift(x.data(:),1),2,2));
Run Code Online (Sandbox Code Playgroud)

或者使用提供的示例代码:

A = repmat(1:4, 4, 1);
for k=1:4
    A = blockproc(A, [2,2], @(x)reshape(circshift(x.data(:),1),2,2));
    display(A);
end
Run Code Online (Sandbox Code Playgroud)

这会创建所需的输出

[ 1 2 3 4 ]      [ 2 1 4 3 ]      [ 2 1 4 3 ]      [ 1 2 3 4 ] 
[ 1 2 3 4 ]  ->  [ 1 2 3 4 ]  ->  [ 2 1 4 3 ]  ->  [ 2 1 4 3 ]  -> ...
[ 1 2 3 4 ]      [ 2 1 4 3 ]      [ 2 1 4 3 ]      [ 1 2 3 4 ] 
[ 1 2 3 4 ]      [ 1 2 3 4 ]      [ 2 1 4 3 ]      [ 2 1 4 3 ]
Run Code Online (Sandbox Code Playgroud)

您还可以定义如何处理矩阵不能分为2 x 2块的情况,例如,如果它有维度5 x 7(如注释中所述)。通过设置PadPartialBlocks为 true,所有部分块将被填充,以便它们形成完整2 x 2块。PadMethod您可以根据需要将该属性设置为以下值之一:

  • x其中x是一个数字,所有附加点都将设置为该数字。
  • replicate将重复矩阵的边界元素A
  • symmetricA用其自身的对称反射进行填充