I want to find each 3x3 submatrix from a bigger matrix. I'm stuck on how to slice each matrix without knowing the size of that matrix. If I know it is a 4x4 matrix, I can slice each submatrix one by one:
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]]
That is only the first 3x3 submatrix out of 4. The matrix can be 3x3, 4x3, 4x4, etc. all the way up to 10x10. Doing it manually for each is definitely out of the question. Is there a way for me to slice each 3x3 submatrix without knowing the size of the bigger matrix?
Matrices are a bit confusing from a human point of view (erm... at least for this human who's answering :-P): when you do m[1][2], the first 1 determines the height (the Y axis, if you may) rather than the width while the subsequent 2 determines the width (the X axis) which is not what we humans are used to.
With that in mind, you could do something like this (note that I changed the sample input m to a 6x5 matrix, just to make sure that a more generic case would work properly).
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('------')
Outputs
[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]
------
I believe this would work as long as your slice_x and slice_y are smaller than the width and the height respectively. Play with the values of slice_x and slice_y, and make sure it does what you want.
[[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)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With