for x, y in [np.int32(tr[-1]) for tr in self.tracks]:
cv2.circle(mask, (x, y), 5, 0, -1)
p = cv2.goodFeaturesToTrack(frame_gray, mask=mask, **feature_params)
if p is not None:
for x, y in np.float32(p).reshape(-1, 2):
self.tracks.append([(x, y)])
I am confused by these for loops, I am quite new to python 3.From what I gather it is first stepping through the x,y values for each tr (from the end? is that what the -1 indicates?)
anyway for each tr in its instance: self.tracks. The bottom for loop is doing the same in the numpy float array:p? Why are they using 'reshape'? What is that doing?
If someone wouldn't mind perhaps just stepping through it for me
I'd greatly appreciate.
self.tracks seems to be an (n,2) list. The outer loop takes each of these values, turns them two by two into integers x and y, then performs a function/method cv2.circle with an object mask and several other parameters. container[-1] indicates that you want the value of the last index of container.
The values of the function/method goodFeaturesToTrack are assigned to p(which seem to be an array or None). ** indicates that feature_params is a dictionary of parameters(if a function is defined as myfunc(a,b=2,c=3,d=5) you could change some of these values for that
function call by calling myfunc("value of a",**mydict) with mydict being a dictionary containing zero or more of the optional variables a, b and c (eg mydict={'b':8,d:0} would change b and d from their default values to 8 and 0 respectively.
a new (float-valued) x and y are then extracted from a reshape of p and appended back to the list self.tracks as a pair.
The -1 in the reshape indicate that you dont care about how long the given axis as long as the other axis has the right shape. eg. an array of 10 values would be reshaped to (5,2) a (4,4) would be reshaped to (8,2) etc. This could have been found by searching for numpy.reshape:
newshape : int or tuple of ints
The new shape should be compatible with the original shape. If an >integer, then the result will be a 1-D array of that length. One shape >dimension can be -1. In this case, the value is inferred from the length of >the array and remaining dimensions.
Related
EDIT:
I've made some progress on testing this out on a simple level, and now want to expand to a for loop. I've updated the question.
I have a function that take a three dimensional array and masks certain elements within the array based on specific conditions. See below:
#function for array masking
def masc(arr,z):
return(np.ma.masked_where((arr[:,:,2] <= z+0.05)*(arr[:,:,2] >= z-0.05), arr[:,:,2]))
arr is a 3D array and z is a single value.
I now want to iterate this for multiple Z values. Here is an example with 2 z values:
masked_array1_1 = masc(xyz,z1)
masked_array1_2 = masc(xyz,z2)
masked_1 = masked_array1_1.mask + masked_array1_2.mask
masked_array1 = np.ma.array(xyz[:,:,2],mask=masked_1)
The masked_array1 gives me exactly what i'm looking for.
I've started to write a forloop to iterate this over a 1D array of Z values:
mask_1 = xyz[:,:,2]
for i in range(Z_all_dim):
mask_1 += (masc(xyz,IWX_new[0],IWY_new[0],MWX[0],MWY[0],Z_all[i]).mask)
masked_array1 = np.ma.array(xyz[:,:,2], mask = mask_1)
Z_all is an array of 7 unique z values. This code does not work but i feel like i'm very close. Does anyone see if i'm doing something wrong?
I'm new to numpy & have a question about it :
according to docs.scipy.org, the "shape" method is "the dimensions of the array. For a matrix with n rows and m columns, shape will be (n,m)"
Suppose I am to create a simple array as below:
np.array([[0,2,4],[1,3,5]])
Using the "shape" method, it returns (2,3) (i.e. the array has 2 rows & 3 columns)
However, for an array ([0,2,4]), the shape method would return (3,) (which means it has 3 rows according to the definition above)
I'm confused : the array ([0,2,4]) should have 3 columns not 3 rows so I expect it to return (,3) instead.
Can anyone help to clarify ? Thanks a lot.
This is just notation - in Python, tuples are distinguished from expression grouping (or order of operations stuff) by the use of commas - that is, (1,2,3) is a tuple and (2x + 4) ** 5 contains an expression 2x + 4. In order to keep single-element tuples distinct from single-element expressions, which would otherwise be ambiguous ((1) vs (1) - which is the single-element tuple and which a simple expression that evaluates to 1?), we use a trailing comma to denote tuple-ness.
What you're getting is a single dimension response, since there's only one dimension to measure, packed into a tuple type.
Numpy supports not only 2-dimensional arrays, but multi-dimensional arrays, and by multi-dimension I mean 1-D, 2-D, 3-D .... n-D, And there is a format for representing respective dimension array. The len of array.shape would get you the number of dimensions of that array. If the array is 1-D, the there is no need to represent as (m, n) or if the array is 3-D then it (m, n) would not be sufficient to represent its dimensions.
So the output of array.shape would not always be in (m, n) format, it would depend upon the array itself and you will get different outputs for different dimensions.
So I have image data which I am iterating through in order to find the pixel which have useful data in them, I then need to find these coordinates subject to a conditional statement and then put these into an array or DataFrame. The code I have so far is:
pix_coor = np.empty((0,2))
for (x,y), value in np.ndenumerate(data_int):
if value >= sigma3:
pix_coor.append([x,y])
where data is just an image array (129,129). All the pixels that have a value larger than sigma3 are useful and the other ones I dont need.
Creating an empty array works fine but when I append this it doesn't seem to work, I need to end up with an array which has two columns of x and y values for the useful pixels. Any ideas?
You could simply use np.argwhere for a vectorized solution -
pix_coor = np.argwhere(data_int >= sigma3)
In numpy, array.append is not an inplace operation, instead it copies the entire array into newly allocated memory (big enough to hold it along with the new values), and returns the new array. Therefore it should be used as such:
new_arr = arr.append(values)
Obviously, this is not an efficient way to add elements one by one.
You should use probably a regular python list for this.
Alternatively, pre allocate the numpy array with all values and then resize it:
pix_coor = np.empty((data_int.size, 2), int)
c = 0
for (x, y), value in np.ndenumerate(data_int):
if value >= sigma3:
pix_coor[c] = (x, y)
c += 1
numpy.resize(pix_coor, (c, 2))
Note that I used np.empty((data_int.size, 2), int), since your coordinates are integral, while numpy defaults to floats.
I am new to python, so please, bear with me!
This function:
def kerf(X,m):
[n_samples, ]= X.shape
n_sa, n_fe = m.shape
ker = np.zeros((n_samples, n_sa))
for i, x_i in enumerate(X):
for j, m_j in enumerate(m):
ker[i, j] = (np.dot(x_i, m_j)) # problem is here!!
return ker
I call it like this:
Z=kerf(myarray[0,[0,1]],myarray[:,[0,1]])
ker[i, j] = (np.dot(x_i, m_j))
ValueError: setting an array element with a sequence.
myarray is basically the same matrix. Why?
When I replace the problem line with:
print(np.dot(x_i, m_j).shape)
it repeatedly prints (2,).
ker[i, j] takes 1 value; 2 values is sequence.
Please give us the dimensions of the arrays at various points, such as myarray (I guessed and tried a (3,4)), and at the problem point. print(...shape) is an essential debugging tool in numpy.
Do you need help on figure out why it's (2,)? May I suggest stepping through the loop in an interactive shell, looking at shapes at various points along the way.
the 2 inputs to the dot look like:
(1.0, array([ 1., 1.]))
a scalar, and a 2 element array - so the dot is also a 2 element array.
You need to explain what size you expect these 2 arrays to be, and what size you expect the dot. Actually we can get the result - it's got to be (1,) or a scalar - 1 value to put in the one slot ker.
You can probably replace the double iteration with a single dot product (or if need be with an einsum call). But let's get this iteration working first.
I'm messing around with 2-dimensional slicing and don't understand why leaving out some defaults grabs the same values from the original array but produces different output. What's going on with the double brackets and shape changing?
x = np.arange(9).reshape(3,3)
y = x[2]
z = x[2:,:]
print y
print z
print shape(y)
print shape(z)
[6 7 8]
[[6 7 8]]
(3L,)
(1L, 3L)
x is a two dimensional array, an instance of NumPy's ndarray object. You can index/slice these objects in essentially two ways: basic and advanced.
y[2] fetches the row at index 2 of the array, returning the array [6 7 8]. You're doing basic slicing because you've specified only an integer. You can also specify a tuple of slice objects and integers for basic slicing, e.g. x[:,2] to select the right-hand column.
With basic slicing, you're also reducing the number of dimensions of the returned object (in this case from two to just one):
An integer, i, returns the same values as i:i+1 except the dimensionality of the returned object is reduced by 1.
So when you ask for the shape of y, this is why you only get back one dimension (from your two-dimensional x).
Advanced slicing occurs when you specify an ndarray: or a tuple with at least one sequence object or ndarray. This is the case with x[2:,:] since 2: counts as a sequence object.
You get back an ndarray. When you ask for its shape, you will get back all of the dimensions (in this case two):
The shape of the output (or the needed shape of the object to be used for setting) is the broadcasted shape.
In a nutshell, as soon as you start slicing along any dimension of your array with :, you're doing advanced slicing and not basic slicing.
One brief point worth mentioning: basic slicing returns a view onto the original array (changes made to y will be reflected in x). Advanced slicing returns a brand new copy of the array.
You can read about array indexing and slicing in much more detail here.