Issue with matrix slicing in n-deminsional matrix - python

I was stuck in python function, but later solved it. I have a question regarding the python n-dimensional notation. That matrix was A(2,4,4,3). So what's the difference in accessing the matrix as A[:][0:3, 0:3, 3] and A[:][ 0:3, 0:3 ][3]

Test array(2,4,4,3):
[[[[ 0 1 2] [[[48 49 50]
[ 3 4 5] [51 52 53]
[ 6 7 8] [54 55 56]
[ 9 10 11]] [57 58 59]]
[[12 13 14] [[60 61 62]
[15 16 17] [63 64 65]
[18 19 20] [66 67 68]
[21 22 23]] [69 70 71]]
[[24 25 26] [[72 73 74]
[27 28 29] [75 76 77]
[30 31 32] [78 79 80]
[33 34 35]] [81 82 83]]
[[36 37 38] [[84 85 86]
[39 40 41] [87 88 89]
[42 43 44] [90 91 92]
[45 46 47]]] [93 94 95]]]
With data[0:4, 0:4, 1] you getting each second element from 4x4 array:
[[[ 3 4 5] [[51 52 53]
[15 16 17] [63 64 65]
[27 28 29] [75 76 77]
[39 40 41]] [87 88 89]]]
On the other hand with data[0:4, 0:4][1] you will get second part of 4x4x2 array:
[[[48 49 50]
[51 52 53]
[54 55 56]
[57 58 59]]
[[60 61 62]
[63 64 65]
[66 67 68]
[69 70 71]]
[[72 73 74]
[75 76 77]
[78 79 80]
[81 82 83]]
[[84 85 86]
[87 88 89]
[90 91 92]
[93 94 95]]]

Related

How can I get uneven submatrices from NxN matrix?

I have a large NxN matrix that I'm looking to retrieve multiple submatrices from. Each of these submatrices can be different sizes but they can't overlap (see attached pic). Is there a function in Python that could remotely do what I'm looking to achieve?
example of submatrices in NxN matrix
This is what I've written so far; however, it doesn't give me back a square submatrix
import numpy as np
# Create a 10x10 matrix
matrix = np.arange(0, 100).reshape((10, 10))
print(matrix)
# Define the sizes of the submatrices
submatrix_sizes = [4, 4, 5]
# Calculate the starting and ending indices for each submatrix
starts = np.cumsum([0] + submatrix_sizes[:-1])
ends = np.cumsum(submatrix_sizes)
# Split the matrix into submatrices of the specified sizes
submatrices = np.split(matrix, ends, axis=1)[:-1]
# Print the submatrices
for i, submatrix in enumerate(submatrices):
print(f"Submatrix {i+1}:")
print(submatrix)
Output
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]
[50 51 52 53 54 55 56 57 58 59]
[60 61 62 63 64 65 66 67 68 69]
[70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 88 89]
[90 91 92 93 94 95 96 97 98 99]]
Submatrix 1:
[[ 0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]
[50 51 52 53]
[60 61 62 63]
[70 71 72 73]
[80 81 82 83]
[90 91 92 93]]
Submatrix 2:
[[ 4 5 6 7]
[14 15 16 17]
[24 25 26 27]
[34 35 36 37]
[44 45 46 47]
[54 55 56 57]
[64 65 66 67]
[74 75 76 77]
[84 85 86 87]
[94 95 96 97]]
Submatrix 3:
[[ 8 9]
[18 19]
[28 29]
[38 39]
[48 49]
[58 59]
[68 69]
[78 79]
[88 89]
[98 99]]
Your starts and ends are not calculated correctly:
It is impossible to have index of 13 on any axis on a 10x10 matix.
you don't use the calculated starts while slicing
starts = np.cumsum([0] + submatrix_sizes[:-1])
# has to be disiced how to calculate these correctly
ends = np.cumsum(submatrix_sizes)
breaks = list(zip(starts, ends))
# slicing x and y axis not only x
submatrix_sizes = [matrix[elem[0]:elem[1], elem[0]:elem[1]] for elem in breaks]

Why is 4D realisation of Max-Pooling in numpy misleading?

I'm trying to understand an algorithm of Max-Pooling in numpy. There are many answers like this that offer to give a new 4 - dimensional shape to two - dimensional image and then call np.max on axis 1 and 3:
window = (2, 4)
arr = np.random.randint(99, size=(1,8,12))
shape = (arr.shape[1]//window[0], window[0], arr.shape[2]//window[1], window[1])
out = arr.reshape(shape).max(axis=(1, 3))
According to my visual understanding, I should operate on axis=(0, 2) so it will shrink to the size 1 and produce an output like so:
That makes a lot of sense but it's not correct:
arr = np.random.randint(99, size=(1,8,12)) =
[[[ 7 55 21 88 69 35 7 7 73 54 16 80]
[70 79 62 55 42 5 77 81 38 52 69 39]
[58 78 48 35 5 93 47 64 18 25 73 25]
[14 8 63 27 28 46 29 68 28 38 51 79]
[70 15 37 51 72 27 44 79 1 79 75 9]
[ 4 27 0 90 15 30 95 62 14 8 69 57]
[24 29 26 44 72 89 74 78 39 29 6 2]
[82 12 0 11 54 38 61 79 91 92 53 28]]]
--------------------------------------------------
arr.reshape(4, 2, 3, 4).max(axis=(0, 2)) =
[[73 93 75 88]
[91 92 95 90]]
--------------------------------------------------
arr.reshape(4, 2, 3, 4).max(axis=(1, 3)) =
[[88 81 80]
[78 93 79]
[90 95 79]
[82 89 92]]
So it doesn't ever agree with my picture in reality. What is the source of this disagreement? What are the reasons it's not working as expected?

How to get all pixs by certain indices from a image array

The image array shape is (540, 960, 3), and it like this:
img_rgb = [[[ 95 71 71]
[ 95 71 71]
[ 95 71 71]
...
[182 171 181]
[182 171 181]
[182 171 181]]
[[ 95 71 70]
[ 95 71 70]
[ 95 71 71]
...
[183 172 182]
[183 172 182]
[183 172 182]]
[[ 95 72 70]
[ 95 71 70]
[ 95 71 71]
...
[183 172 182]
[183 172 182]
[183 172 182]]
...
[[ 36 35 45]
[ 36 35 45]
[ 36 35 45]
...
[ 49 45 50]
[ 49 45 50]
[ 49 45 50]]
[[ 36 35 45]
[ 36 35 45]
[ 36 35 45]
...
[ 49 45 50]
[ 49 45 50]
[ 49 45 50]]
[[ 36 35 45]
[ 36 35 45]
[ 36 35 45]
...
[ 49 45 50]
[ 49 45 50]
[ 49 45 50]]]
And I want to get elements by indices that indicate the each element index, and the indices like this:
indices = [
[0, 0], [0, 1], [0, 2]
]
Expected output
[
[ 95 71 71],
[ 95 71 71],
[ 95 71 71],
]
There are tow similar question in those link, one is Python numpy 2D array sum over certain indices, and another is Finding the (x,y) indexes of specific (R,G,B) color values from images stored in NumPy ndarrays.
It got a IndexError: too many indices for array When I tried question one by img_rgb[tuple(indices)].
You just need to transpose indices.
img_rgb[tuple(np.transpose(indices))]
np.tranpose() would work even if indices is just a list, since it expects as input any "array-like" structure.

Create 3D NumPy array with sequential number

I wanted to create a 3D NumPy array with sequential numbers like so:
[[[11 27 43]
[12 28 44]
[13 29 45]
[14 30 46]]
[[15 31 47]
[16 32 48]
[17 33 49]
[18 34 50]]
[[19 35 51]
[20 36 52]
[21 37 53]
[22 38 54]]
[[23 39 55]
[24 40 56]
[25 41 57]
[26 42 58]]]
I did this: A = np.arange(11, 59).reshape((4, 4, 3)) but I got this instead:
[[[11 12 13]
[14 15 16]
[17 18 19]
[20 21 22]]
[[23 24 25]
[26 27 28]
[29 30 31]
[32 33 34]]
[[35 36 37]
[38 39 40]
[41 42 43]
[44 45 46]]
[[47 48 49]
[50 51 52]
[53 54 55]
[56 57 58]]]
So it's not the sequence that I wanted. I had done some additional steps to get the correct 3D array. First, I shaped the numbers into a 2D array: A = np.arange(11, 59).reshape((-1, 4)) to get this:
[[11 12 13 14]
[15 16 17 18]
[19 20 21 22]
[23 24 25 26]
[27 28 29 30]
[31 32 33 34]
[35 36 37 38]
[39 40 41 42]
[43 44 45 46]
[47 48 49 50]
[51 52 53 54]
[55 56 57 58]]
Then, I splitted and stacked the 2D array and got the 3D array that I wanted: A = np.dstack(np.vsplit(A, 3))
[[[11 27 43]
[12 28 44]
[13 29 45]
[14 30 46]]
[[15 31 47]
[16 32 48]
[17 33 49]
[18 34 50]]
[[19 35 51]
[20 36 52]
[21 37 53]
[22 38 54]]
[[23 39 55]
[24 40 56]
[25 41 57]
[26 42 58]]]
Now I'm wondering if there is a more elegant and straightforward way to achieve the same result. Thanks you.
Get the ranged array, reshape and then permute axes -
np.arange(11, 59).reshape(3,4,4).transpose(1,2,0)
Another way to permute axes would be to use np.moveaxis -
np.moveaxis(np.arange(11, 59).reshape(3,4,4),0,2)
Discussion : A general intuition to solving such problems.

How can I turn random matrix into a table?

Here is the code I'm given.
import random
def create_random_matrix(rows_min, rows_max, cols_min, cols_max):
matrix = []
# generate a random number for the number of rows
# notice that randint works differently from similar functions
# you have seen in that rows_min and rows_max are both inclusive
# http://docs.python.org/3/library/random.html#random.randint
rows = random.randint(rows_min, rows_max)
for row in range(rows):
# add a row to the matrix
matrix.append([])
# generate a random number for the number of columns
cols = random.randint(cols_min, cols_max)
# generate a random number between 1 and 100 for each
# cell of the row
for col in range(cols):
matrix[row].append(random.randint(1, 100))
# done
return matrix
def print_matrix(twod_list):
print(twod_list)
if __name__ == "__main__":
random_matrix = create_random_matrix(8, 12, 3, 7)
print_matrix(random_matrix)
The code creates a random matrix like this:
[[52, 23, 11, 95, 79], [3, 63, 11], [5, 78, 3, 14, 37], [89, 98, 10], [24, 60, 80, 73, 84, 94], [45, 14, 28], [51, 19, 9], [43, 86, 63, 71, 19], [58, 6, 43, 17, 87, 64, 87], [77, 57, 97], [9, 71, 54, 20], [77, 86, 22]]
But how can I change the code to output something like this instead?
36 83 35 73
28 11 3 45 30 44
39 97 3 10 90 5 42
55 73 56 27 7 37
84 49 35 43
100 20 22 95 75 25
58 81 26 34 41 44 72
32 23 21
31 37 1
95 90 26 6 78 49 22
5 17 31
86 25 73 56 10
This is a simple solution to your problem to print the members of a list of lists:
mymatrix = [[52, 23, 11, 95, 79], [3, 63, 11], [5, 78, 3, 14, 37], [89, 98, 10], [24, 60, 80, 73, 84, 94], [45, 14, 28], [51, 19, 9], [43, 86, 63, 71, 19], [58, 6, 43, 17, 87, 64, 87], [77, 57, 97], [9, 71, 54, 20], [77, 86, 22]]
for list in mymatrix:
for item in list:
print item,
print
the output would look like:
52 23 11 95 79
3 63 11
5 78 3 14 37
89 98 10
24 60 80 73 84 94
45 14 28
51 19 9
43 86 63 71 19
58 6 43 17 87 64 87
77 57 97
9 71 54 20
77 86 22
just change the way you print it:
>>> for i in random_matrix:
... print " ".join(str(j) for j in i)
...
52 23 11 95 79
3 63 11
5 78 3 14 37
89 98 10
24 60 80 73 84 94
45 14 28
51 19 9
43 86 63 71 19
58 6 43 17 87 64 87
77 57 97
9 71 54 20
And just for fun, in one line:
print "\n".join(" ".join(str(j) for j in i) for i in random_matrix)

Categories