What does this slicing mean [:, :, 0]? - python

I am trying to understand this code
I can't get my head around what this line is doing. The flow variable is an array of flow vectors with one for each pixel in the image (so a 2d array).
fx, fy = flow[:, :, 0], flow[:, :, 1]
Any help would be appreciated

Let us first simplify the expression. Your code:
fx, fy = flow[:, :, 0], flow[:, :, 1]
is equivalent to:
fx = flow[:, :, 0]
fy = flow[:, :, 1]
So now it boils down on what flow[:, :, 0]. It means that flow is a numpy array with at least three dimensions (let us define N as the number of dimensions). Then flow[:,:,0] is an N-1-dimensional array, where we pick 0 always as the third dimension.
In the context of image processing, an image is usually a 3d-array (given it has color) with dimensions w × h × 3 (three color channels). So here it means that flow[:,:,0] will generate a w × h view where for each pixel, we select the red channel (given the red channel is the first channel).
So if flow is a 5 × 4 × 3 matrix, like:
>>> flow
array([[[ 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]]])
Then we will obtain for each 3-tuple the first element, making it:
>>> flow[:,:,0]
array([[ 0, 3, 6, 9],
[12, 15, 18, 21],
[24, 27, 30, 33],
[36, 39, 42, 45],
[48, 51, 54, 57]])
and by querying flow[:,:,1], we obtain:
>>> flow[:,:,1]
array([[ 1, 4, 7, 10],
[13, 16, 19, 22],
[25, 28, 31, 34],
[37, 40, 43, 46],
[49, 52, 55, 58]])
mind that these are views: if you alter flow, it will have impact on fx and fy as well, even if you did these assignments before.

Related

Numpy select elements with a condition along axis

I have a 2D numpy array x as:
[ [ 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] ]
I want to extract the arguments of rows for which any element in the row is less than 25. So, what I need for output is [0,1,2,3,4,5,6,7] for just the rows but using np.where(x<35) is giving me the list of 2D arguments for all possible values. In other words, I what I want are the arguments of all the rows of x where at least one element is less than 25, but what I am getting are the arguments of all the elements of x that are less than 25.
What should I do? Is there a specific function for this or should I just select the unique values from the returned list of arguments?
One way would be this:
import numpy as np
# x is your array
x1 = (x < 25).sum(axis = 1)
rows = np.where(x1 > 0)[0]
The row indices are in rows as array([0, 1, 2, 3, 4, 5, 6, 7]).
You can also use nonzero as:
rows = np.nonzero((x < 25).sum(axis = 1))[0]

Slicing a numpy array based on argmax of another numpy array [duplicate]

This question already has answers here:
Index n dimensional array with (n-1) d array
(3 answers)
Closed 2 years ago.
I have two arrays, and are as follows:
import numpy as np
np.random.seed(42)
a = (np.random.uniform(size=[2, 5, 3]) * 100).astype(int)
b = (np.random.uniform(size=[2, 5, 3]) * 100).astype(int)
Ouput of array a:
array([[[37, 95, 73],
[59, 15, 15],
[ 5, 86, 60],
[70, 2, 96],
[83, 21, 18]],
[[18, 30, 52],
[43, 29, 61],
[13, 29, 36],
[45, 78, 19],
[51, 59, 4]]])
The output of array b is as follows:
array([[[60, 17, 6],
[94, 96, 80],
[30, 9, 68],
[44, 12, 49],
[ 3, 90, 25]],
[[66, 31, 52],
[54, 18, 96],
[77, 93, 89],
[59, 92, 8],
[19, 4, 32]]])
Now I am able to get the argmax of array a using the following code:
idx = np.argmax(a, axis=0)
print(idx)
Output:
array([[0, 0, 0],
[0, 1, 1],
[1, 0, 0],
[0, 1, 0],
[0, 1, 0]], dtype=int64)
Is it possible to slice array b using the argmax output of array a, so that I get the following output:
array([[60, 17, 6],
[94, 18, 96],
[77, 9, 68],
[44, 92, 49],
[ 3, 4, 25]])
I tried different ways, but not successful. Kindly help.
Using numpy advanced indexing:
import numpy as np
np.random.seed(42)
a = (np.random.uniform(size=[2, 5, 3]) * 100).astype(int)
b = (np.random.uniform(size=[2, 5, 3]) * 100).astype(int)
idx = np.argmax(a, axis=0)
_, m, n = a.shape
b[idx, np.arange(m)[:,None], np.arange(n)]
array([[60, 17, 6],
[94, 18, 96],
[77, 9, 68],
[44, 92, 49],
[ 3, 4, 25]])

How to access array by a list of point coordinates

I have array A = np.ones((4,4,4)) and another array that represent the coordinates of point in array A called B, lets assume that B = [[2,2,2], [3,2,1]].
I tried to access A by array indexing like A[B], but it didn't works.
How i can do it in elegant way, that also work for B that it's have a higher dimensions like B of shape (10, 20, 3) ?
You can pass a list of coordinates, but you should transpose the list. Such that the items of the i-th dimension are passed as the i-th element in the indexing, for example with:
A[tuple(np.transpose(B))]
For a 4×4×4 matrix:
>>> A = np.arange(64).reshape(4,4,4)
>>> A
array([[[ 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]]])
we get for the given coordinates:
>>> A[tuple(np.transpose(B))]
array([42, 57])
and if we calculate these manually, we get:
>>> A[2,2,2]
42
>>> A[3,2,1]
57
Background:
A[1,2,3] is short for A[(1,2,3)] (so in a tuple). You can fetch multiple items with A[([2,3], [2,2], [2,1])] but then you thus first need to transpose the data.
Since the data is represented as [[2,2,2], [3,2,1]], we thus first need to transpose it to [[2,3], [2,2], [2,1]]. Next we wrap it in a tuple, and can use this to subscript A.

Pytorch tensor indexing: How to gather rows by tensor containing indices

I have the tensors:
ids: shape (7000,1) containing indices like [[1],[0],[2],...]
x: shape(7000,3,255)
ids tensor encodes the index of bold marked dimension of x which should be selected.
I want to gather the selected slices in a resulting vector:
result: shape (7000,255)
Background:
I have some scores (shape = (7000,3)) for each of the 3 elements and want only to select the one with the highest score. Therefore, I used the function
ids = torch.argmax(scores,1,True)
giving me the maximum ids. I already tried to do it with gather function:
result = x.gather(1,ids)
but that didn't work.
Here is a solution you may look for
ids = ids.repeat(1, 255).view(-1, 1, 255)
An example as below:
x = torch.arange(24).view(4, 3, 2)
"""
tensor([[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 6, 7],
[ 8, 9],
[10, 11]],
[[12, 13],
[14, 15],
[16, 17]],
[[18, 19],
[20, 21],
[22, 23]]])
"""
ids = torch.randint(0, 3, size=(4, 1))
"""
tensor([[0],
[2],
[0],
[2]])
"""
idx = ids.repeat(1, 2).view(4, 1, 2)
"""
tensor([[[0, 0]],
[[2, 2]],
[[0, 0]],
[[2, 2]]])
"""
torch.gather(x, 1, idx)
"""
tensor([[[ 0, 1]],
[[10, 11]],
[[12, 13]],
[[22, 23]]])
"""
using the example of David Ng I found out another way to do it:
idx = ids.flatten() + torch.arange(0,4*3,3)
tensor([ 0, 5, 6, 11])
x.view(-1,2)[idx]
tensor([[ 0, 1],
[10, 11],
[12, 13],
[22, 23]])
Another solution may provide better memory read pattern in cases where the dimensions are higher.
# data
x = torch.arange(60).reshape(3, 4, 5)
# index
y = torch.randint(0, 4, (12,), dtype=torch.int64).reshape(3, 4)
# result
z = x[torch.arange(x.shape[0]).repeat_interleave(x.shape[1]), y.flatten()]
z = z.reshape(x.shape)
An example result of the x, y, z will be
Tensor([[[ 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]]])
tensor([[1, 1, 2, 3],
[3, 1, 1, 0],
[1, 1, 1, 1]])
tensor([[[ 5, 6, 7, 8, 9],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]],
[[35, 36, 37, 38, 39],
[25, 26, 27, 28, 29],
[25, 26, 27, 28, 29],
[20, 21, 22, 23, 24]],
[[45, 46, 47, 48, 49],
[45, 46, 47, 48, 49],
[45, 46, 47, 48, 49],
[45, 46, 47, 48, 49]]])

How to implement tf.space_to_depth with numpy?

These is a function in tensorflow called tf.space_to_depth. The implementation of this function in Tensorflow source code is so difficult for me. Could you please help me to implement it using numpy?
Here is some code to visualize how this function works. By the way, before everything, it is good to mention that the input to tensorflow's function should have input shape : [batch, height, width, depth]
Assuming this code. First we need to define a tensor:
norm = tf.reshape(tf.range(0,72),(1,6,6,2))
Here is the value of depth 1 (norm[0,:,:,0]):
[[ 0, 2, 4, 6, 8, 10],
[12, 14, 16, 18, 20, 22],
[24, 26, 28, 30, 32, 34],
[36, 38, 40, 42, 44, 46],
[48, 50, 52, 54, 56, 58],
[60, 62, 64, 66, 68, 70]]
Here is the value of depth 2 (norm[0,:,:,1]):
[[ 1, 3, 5, 7, 9, 11],
[13, 15, 17, 19, 21, 23],
[25, 27, 29, 31, 33, 35],
[37, 39, 41, 43, 45, 47],
[49, 51, 53, 55, 57, 59],
[61, 63, 65, 67, 69, 71]]
In the next step, I would like to apply tf.space_to_depth function and here it is:
trans = tf.space_to_depth(norm,2)
Output shape is : (1,3,3,8) and here is the output of this function:
trans[0,:,:,0]
[[ 0, 4, 8],
[24, 28, 32],
[48, 52, 56]]
trans[0,:,:,1]
[[ 1, 5, 9],
[25, 29, 33],
[49, 53, 57]]
trans[0,:,:,2]
[[ 2, 6, 10],
[26, 30, 34],
[50, 54, 58]]
trans[0,:,:,3]
[[ 3, 7, 11],
[27, 31, 35],
[51, 55, 59]]
trans[0,:,:,4]
[[12, 16, 20],
[36, 40, 44],
[60, 64, 68]]
trans[0,:,:,5]
[[13, 17, 21],
[37, 41, 45],
[61, 65, 69]]
trans[0,:,:,6]
[[14, 18, 22],
[38, 42, 46],
[62, 66, 70]]
trans[0,:,:,7]
[[15, 19, 23],
[39, 43, 47],
[63, 67, 71]]
May someone help me how can I implement a vectorized version of this function in numpy?
Appreciating in advance for any response!
You can implement space_to_depth with appropriate calls to the reshape() and swapaxes() functions:
import numpy as np
def space_to_depth(x, block_size):
x = np.asarray(x)
batch, height, width, depth = x.shape
reduced_height = height // block_size
reduced_width = width // block_size
y = x.reshape(batch, reduced_height, block_size,
reduced_width, block_size, depth)
z = np.swapaxes(y, 2, 3).reshape(batch, reduced_height, reduced_width, -1)
return z
Here are the examples from the documentation of tf.space_to_depth:
In [328]: x = [[[[1], [2]],
...: [[3], [4]]]]
...:
In [329]: space_to_depth(x, 2)
Out[329]: array([[[[1, 2, 3, 4]]]])
In [330]: x = [[[[1, 2, 3], [4, 5, 6]],
...: [[7, 8, 9], [10, 11, 12]]]]
...:
In [331]: space_to_depth(x, 2)
Out[331]: array([[[[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]]])
In [332]: x = [[[[1], [2], [5], [6]],
...: [[3], [4], [7], [8]],
...: [[9], [10], [13], [14]],
...: [[11], [12], [15], [16]]]]
...:
In [333]: space_to_depth(x, 2)
Out[333]:
array([[[[ 1, 2, 3, 4],
[ 5, 6, 7, 8]],
[[ 9, 10, 11, 12],
[13, 14, 15, 16]]]])
And here is your example:
In [334]: norm = np.arange(72).reshape(1, 6, 6, 2)
In [335]: trans = space_to_depth(norm, 2)
In [336]: trans[0, :, :, 0]
Out[336]:
array([[ 0, 4, 8],
[24, 28, 32],
[48, 52, 56]])
In [337]: trans[0, :, :, 1]
Out[337]:
array([[ 1, 5, 9],
[25, 29, 33],
[49, 53, 57]])
In [338]: trans[0, :, :, 7]
Out[338]:
array([[15, 19, 23],
[39, 43, 47],
[63, 67, 71]])

Categories