如何从任意大小的矩阵中切割每个3x3子矩阵?

时间:2018-01-03 19:44:12

标签: python python-3.x

我想从更大的矩阵中找到每个3x3子矩阵。我不知道如何在不知道矩阵大小的情况下切割每个矩阵。如果我知道它是一个4x4矩阵,我可以逐个切割每个子矩阵:

m = [[1, 5, 9, 2], 
     [0, 4, 6, 1], 
     [6, 1, 8, 8], 
     [4, 7, 3, 5]]

s1 = [m[0][:3], m[1][:3], m[2][:3]]

s1 = [[1, 5, 9], 
      [0, 4, 6], 
      [6, 1, 8]]

这只是4个中的第一个3x3子矩阵。矩阵可以是3x3,4x3,4x4等,一直到10x10。手动完成每个操作绝对是不可能的。有没有办法让我在不知道更大矩阵的大小的情况下对每个3x3子矩阵进行切片?

4 个答案:

答案 0 :(得分:2)

[[m[i][j:j+3], m[i+1][j:j+3], m[i+2][j:j+3]] for j in range(len(m[0])-2) for i in range(len(m)-2)]

答案 1 :(得分:1)

从人的角度来看,矩阵有点令人困惑(呃......至少对于那些正在回答: - P 的人类):当你做{{ 1}},第一个m[1][2]确定高度(Y轴,如果可能)而不是 width ,而后续1确定宽度(X轴),这不是我们人类习惯的。

考虑到这一点,你可以做这样的事情(请注意,我将示例输入2更改为6x5矩阵,只是为了确保更通用的案例能正常工作)。

m

输出

m = [[1, 5, 9, 2, 4, 7],
     [0, 4, 6, 1, 5, 7],
     [6, 1, 8, 8, 6, 8],
     [4, 7, 3, 5, 7, 9],
     [8, 9, 6, 3, 1, 1],
     ]

slice_x = 3
slice_y = 3


def test_slice():
    width = len(m[0])
    height = len(m)
    slices = []
    for i in range(0, height - slice_y + 1):
        for j in range(0, width - slice_x + 1):
            slices.append(
                [
                    [m[a][b] for b in range(j, j + slice_x)]
                    for a in range(i, i + slice_y)
                ]
            )
    return slices


if __name__ == "__main__":
    slices = test_slice()
    for sl in slices:
        for row in sl:
            print(row)
        print('------')

我相信只要您的[1, 5, 9] [0, 4, 6] [6, 1, 8] ------ [5, 9, 2] [4, 6, 1] [1, 8, 8] ------ [9, 2, 4] [6, 1, 5] [8, 8, 6] ------ [2, 4, 7] [1, 5, 7] [8, 6, 8] ------ [0, 4, 6] [6, 1, 8] [4, 7, 3] ------ [4, 6, 1] [1, 8, 8] [7, 3, 5] ------ [6, 1, 5] [8, 8, 6] [3, 5, 7] ------ [1, 5, 7] [8, 6, 8] [5, 7, 9] ------ [6, 1, 8] [4, 7, 3] [8, 9, 6] ------ [1, 8, 8] [7, 3, 5] [9, 6, 3] ------ [8, 8, 6] [3, 5, 7] [6, 3, 1] ------ [8, 6, 8] [5, 7, 9] [3, 1, 1] ------ slice_x分别小于slice_ywidth,这就有效。使用heightslice_x的值进行游戏,并确保它符合您的要求。

答案 2 :(得分:1)

我一直在寻找同样的问题。我对这个提议不满意,因为它涉及大循环。因此,计算时间可能会随着矩阵的维数(图像增加)而消耗。我想出了一个使用卷积的解决方案。因此,我的循环具有子图像大小的维度。我们可能会做得更好,但这是功能。希望能帮到你:

import scipy
import numpy as np

def split_mat(mat,dim):
    '''
    Split one image in sub-image of dimension dim x dim
    '''
    
    for i in range(dim):
        for j in range(dim):
            kernel=np.zeros([dim,dim])
            kernel[i,j]=1
            tmp=scipy.signal.convolve2d(mat,kernel,mode='valid').flatten()
            if i+j==0:
                nb_img=len(tmp)
                res=np.zeros([int(dim**2),nb_img])
            
            res[i*dim+j,:]=tmp
            
    return res.reshape([dim,dim,nb_img])[::-1,::-1,:]

你可以这样测试:

mat=np.random.random([100,100])
dim=5
sp_mat=split_mat(mat,dim)
# The extracted matrix number i is visible by :
sp_mat[:,:,i]

答案 3 :(得分:0)

我建议您使用numpy

Numpy数组有一个有用的函数形状。

m转换为numpy.array

import numpy as np
np_m = np.array([np.array(row) for row in m])

如果np_m转换为numpy数组,那么

row, col = np_m.shape 

然后你可以迭代每个索引并排除;第一行,第一列,最后一行和最后一列。

list_of_s = []
for r in range(1, row-1):
    for c in range(1, col-1):
        s_new = np_m[r-1:r+1][c-1:c+1]
        list_of_s.append(s_new)

list_of_sm

中包含的所有3x3矩阵(作为numpy数组)的列表(非numpy数组)