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

Python 如何从任意大小的矩阵中分割每个3x3子矩阵?,python,python-3.x,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,

我想从一个更大的矩阵中找到每个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子矩阵进行切片?

我建议使用
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\u of_s
是包含在
m
中的所有3x3矩阵(作为numpy数组)的列表(非numpy数组)。从人类的角度来看,矩阵有点混乱(呃…至少对于回答:-p):当你做
m[1][2]
,第一个
1
决定高度(Y轴,如果可以的话)而不是宽度,而随后的
2
确定的宽度(X轴)不是我们人类习惯的宽度

[[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)]
考虑到这一点,您可以这样做(注意,我将示例输入
m
更改为6x5矩阵,只是为了确保更通用的情况能够正常工作)

输出

[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\u x
slice\u y
分别小于
width
height
,这就行了。玩
slice\u x
slice\u y
的值,确保它能满足你的要求。

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

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]

所以你想要
2x2
矩阵的
3x3
矩阵在这里?我想从一个更大的矩阵中得到所有可能的3x3矩阵。是的,但在这个例子中有四个子矩阵?或者我们可以忽略第三行的子矩阵吗?@WillemVanOnsem想象一个大小为3x3的卷积过滤器在这个数组上。你会共有4个窗口,4个不同的重叠区域。您的输入矩阵(
m
)的宽度是否总是与高度相同(4x4,5x5…),或者是否可以有4x2?
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]