how to extract line in images(3bands) using numpy in python? - python

In order to modify the value of a particular vertical line in the image, i want to extract the 3-band vertical line of the image.
When I was a two dimensional array, I extracted the vertical lines with the following code:
vertical_line = array[:,[1]]
I tried to use this code in a 3d array image but it failed.
#image shape(b,g,r) (100,100,3)
# my try
vertical_line_try_1 = image[:,[1]][3]#result => [[255,255,255]]
vertical_line_try_2 = image[:,[1][3]]#result => IndexError: list index out of range
vertical_line_try_3 = image[:,[1],[3]]#result => IndexError: index 3 is out of bounds for axis 2 with size 3
How can I extract the vertical lines of three bands at once without writing a loop?

When you index with a slice the corresponding dimension is kept (since you get a possible stridded range of values). On the other hand, when you index with a single number that dimension disappears.
Ex:
a = np.random.randn(4,5)
# Let's get the third column in the matrix
print(a[:, 2].shape) # prints `(4,)` -> we get a vector
print(a[:, 2:3].shape) # prints `(4,1)` -> we keep the result as a column matrix
From your two dimensional example it seems you are using advanced indexing just as a way to keep the dimension. If that is true, using a slice containing a single element as I have shown is cleaner (my opinion) and faster (tested with %timeit in IPython).
Now, back to your question. It looks like you want to extract all values whose index of the second dimension is equal to 1, similar to the red part in the figure below.
If that is the case, then just use either image[:,1, :] (or just image[:,1]) if you to get the values as a matrix, or image[:,1:2, :] if you want a 3D array.
It is also useful to understand what your failed attempts were actually doing.
image[:,[1]][3]: This is actually two indexing operations in the same line.
First, image[:,[1]] would return a 100x1x3 array, and then the second indexing with [3] would take the fourth line. Since this second indexing is a regular one (not a fancy and not a slice), then the indexed dimension disappears and you get a 1x3 array in the end
image[:,[1][3]]: This one I'm not really sure what it is doing
image[:,[1],[3]]: This means "take all values from the first dimension, but only the ones from the second index of the first dimension and the fourth index of the third dimension. Since the third dimension only has "size" 3, then trying to get the fourth index results in the out of bound error.

Related

Why do axes transpose upon indexing? [duplicate]

I have a 5 dimension array like this
a=np.random.randint(10,size=[2,3,4,5,600])
a.shape #(2,3,4,5,600)
I want to get the first element of the 2nd dimension, and several elements of the last dimension
b=a[:,0,:,:,[1,3,5,30,17,24,30,100,120]]
b.shape #(9,2,4,5)
as you can see, the last dimension was automatically converted to the first dimension.
why? and how to avoid that?
This behavior is described in the numpy documentation. In the expression
a[:,0,:,:,[1,3,5,30,17,24,30,100,120]]
both 0 and [1,3,5,30,17,24,30,100,120] are advanced indexes, separated by slices. As the documentation explains, in such case dimensions coming from advanced indexes will be first in the resulting array.
If we replace 0 by the slice 0:1 it will change this situation (since it will leave only one advanced index), and then the order of dimensions will be preserved. Thus one way to fix this issue is to use the 0:1 slice and then squeeze the appropriate axis:
a[:,0:1,:,:,[1,3,5,30,17,24,30,100,120]].squeeze(axis=1)
Alternatively, one can keep both advanced indexes, and then rearrange axes:
np.moveaxis(a[:,0,:,:,[1,3,5,30,17,24,30,100,120]], 0, -1)

What does numpy.concatenate do with a single argument?

I have read about concatenate. But, did not see the function taking a single list as input.It must have two lists as input.
Consider the following statement in a program that I want to execute
row = np.concatenate(row, 1)
What is concatenate doing here? It is taking only one list named row.
Probably you have seen it most often used like this:
c = np.concatenate([a, b])
but you can of course also do:
ab = [a, b]
c = np.concatenate(ab)
Look at row before and after concatenating to see what is going on.
The first argument of np.concatenate is supposed to be a sequence of objects (think vectors or matrices). The second argument is the axis along which the concatenation is to be performed. See help(np.concatenate) for the full docstring.
For your command to be valid, the objects in the row sequence must have at least a 0th and a 1st dimension. This would typically be a matrix, but the name row is suggestive of a set of row vectors that have dimension [0, d].
If you concatenate n vectors of shape [0, d] along the 1st dimension, this will result in an object of shape [0, n*d]. Which is a very long row vector.

Slicing 3d Arrays

I want to slice 3D arrays in a way to only print the last element of each row in the 2nd array.
In my 3D Array:
np.random.seed(42)
M = np.random.randint(10, size=(2,2,10))
print(M)
I tried accessing the last elements of the 2nd Array in a way like this:
print(M[1::2]) ## which just prints me the whole 2nd Array
print(M[1::,2]) ## which gives me an error of index 2 being out of bounds
I understand the first print() method like:
1: # chose the second array
: # chose all rows of the 2nd array
:2 # chose every second index of the row and print it
strangely it prints the whole array which confuses me.
The second print() method i was hoping to at least print the 2nd index alone but I get that error message.
So I tried around more and came up with that code:
print(M[1:,0:,::2])
It gives me the result I want, but I cannot read the code.
I understand
1: ## which chooses the 2nd array
but ,0:,::2 is confusing me. ::2 is chosing every 2nd index I guess but I still don't understand when I can make ':' and when not. Or what is the meaning of ',' in the slicing process.
In numpy,the operator works as follows :- [start_index:end_index:step].
This means that when you index M[1:,0:,::2] what you are actually indexing is everything from the first index of the first dimension([1:]), then everything from the start of the second dimension([0:]), and finally every element with a step of 2 ([::2]).
The , is used to seperate the dimensions so I assume what you actually want to do is M[:,1,-1] to get the last element of every 2nd array.

Why is the change of values in one array is affecting the value on another array (with exact same values) that isn't involved in the operation?

When I run the command "negative_only[negative_only>0]=0" (which should make positive values = 0 on the array "negative_only") the values on a similar array ("positive_only") are also changed. Why is this happening? I'm using Python 3.7 (Windows 10 / Spyder IDE).
The code where the two arrays are being manipulated is below. The "long_dollars_ch" is an array of ~2700 x 60 with some positive values, some negative values and a lot of zeros. This code is part of a loop that is cycling through each row of the array "long_dollars_ch".
# calculations to isolate top contributors to NAV change for audits
top_check = 3 # number of top values changes to track
# calculate dollar change (for longs), and create array with most positive/negative values
long_dollars_ch[c_day,:] = long_shares[c_day,:]*hist_prices_zeros[c_day,:]-long_shares[c_day,:]*hist_prices_zeros[c_day-1,:]
positive_only = long_dollars_ch[c_day,:]
positive_only[positive_only<0]=0 #makes non-positive values zero
idx = np.argsort(positive_only) #creat index representing sorted values for only_positive for c_day
non_top_vals = idx[:-top_check]
negative_only = long_dollars_ch[c_day,:]
negative_only[negative_only>0]=0 #makes non-negative values zero
idx = np.argsort(negative_only) #creat index representing sorted values for only_negative for c_day
non_bottom_vals = idx[:-top_check]
# create array that shows the most positive/negative dollar change for "top-check" securities
long_dollars_ch_pos[c_day,:] = positive_only
long_dollars_ch_pos[c_day,:][non_top_vals] *= 0
long_dollars_ch_neg[c_day,:] = negative_only
long_dollars_ch_neg[c_day,:][non_bottom_vals] *= 0
The objective of this code is to create two arrays. One that has only the top "top_check" positive values (if any) and another that has the bottom "top_check" negative values (if any) for each row of the original array "long_dollars_ch". However, it appears that Python is considering the "positive_only" and "negative_only" the same "variable". And therefore, the operation with one of them affects the values inside the other (that was not part of the operation).
its quite simple.
In numpy np.array x = np.array y you do not copy array :)
You make a reference to array x.
In other words, you do not have two array after using "=". You still have one array x, and a reference to that array (y is that reference).
positive_only = long_dollars_ch[c_day,:]
.
.
,
negative_only = long_dollars_ch[c_day,:]
do not make a copy of long_dollars_ch, but only makes references to it.
you need to use copy method, or other method (numpy provides few of them) to make it work.
Here is a documentation
EDIT: I posted wrong link, now it is ok.

Removing a subarray after using numpy.split

Title kinda says it all, I'm trying to make two new matrices after using numpy.split, so:
#A is some mxn matrix
numfolds=5
folds = numpy.split(A,numfolds)
#now folds is 5 equalish subarrays which can be called out
#subarray1 is the second fold (the second fifth of A along axis=0 by default)
subarray1 = folds[2]
#numpy.delete does not get rid of the second subarray in A
arrayWithoutSubArray1 = numpy.concatenate(numpy.delete(folds[2]))
How do a make a matrix which is all but one subarray in A, in this example. I'd rather not use loops. Thanks in advance.
(Posted on behalf of the OP).
The solution is to do the delete outside of the concatenate and index properly.
#A is some mxn matrix
numfolds=5
folds = numpy.split(A,numfolds)
#now folds is 5 equalish subarrays which can be called out
#subarray1 is the second fold (the second fifth of A along axis=0 by default)
subarray1 = folds[2]
#numpy.delete does not get rid of the second subarray in A
arrayWithoutSubArray1 = numpy.delete(folds,2,0)
arrayWithoutSubArray1 = numpy.concatenate(arrayWithoutSubArray1)

Categories

Resources