Python - Average values of numpy multidimensionnal array every specific time - python

I have a multidimensionnal array "test[:,:,:]" and i would like to get averaged values on the test.shape[0] dimension for every 4 "frames" i would like to keep the same dimensions of my array and substitute the 4 values by the mean value.
As example:
test=np.array([[[ 2., 1., 1.],
[ 1., 1., 1.]],
[[ 3., 1., 1.],
[ 1., 1., 1.]],
[[ 3., 1., 1.],
[ 1., 1., 1.]],
[[ 5., 1., 1.],
[ 1., 1., 1.]],
[[ 2., 1., 1.],
[ 1., 1., 1.]],
[[ 3., 1., 1.],
[ 1., 1., 1.]],
[[ 3., 1., 1.],
[ 1., 1., 1.]],
[[ 5., 1., 1.],
[ 1., 1., 1.]],
[[ 2., 1., 1.],
[ 1., 1., 1.]]])
for i in range(test.shape[0]-1,4):
test_mean = (test[i,:,:]+test[i+1,:,:]+test[i+2,:,:]+test[i+3,:,:])/4.
But, i don't keep the same dimension...what is the best way to do that?

You are overwriting test_mean every time. A good start is:
test_mean = np.zeros_like(test)
for i in xrange(test.shape[0]-4):
test_mean[i] = test[i:i+4].mean(axis=0)
Here is a more efficient implementation from scipy:
from scipy.ndimage import uniform_filter1d
test_mean2 = uniform_filter1d(test, 4, axis=0)
Check the documentation to understand how the result is stored and what options you have to treat boundary values.

Related

Python - Concatenating two images and adding up their color channels

I have two 500x500 images, and need to merge them together and add up their channels.
When I used Numpy's concatenate function for instance, the returned output becomes 500x1000, and not sure if the color channels are added at all.
The output I'm looking for for merging two colored 500x500 images would be 500x500x6.
How can I perform that in Python?
Thanks.
a couple of options, if you want separate RGB or stuck together:
np.stack([np.zeros((2,2,3)), np.ones((2,2,3))], axis=2)
Out[157]:
array([[[[ 0., 0., 0.],
[ 1., 1., 1.]],
[[ 0., 0., 0.],
[ 1., 1., 1.]]],
[[[ 0., 0., 0.],
[ 1., 1., 1.]],
[[ 0., 0., 0.],
[ 1., 1., 1.]]]])
np.concatenate([np.zeros((2,2,3)), np.ones((2,2,3))], axis=2)
Out[158]:
array([[[ 0., 0., 0., 1., 1., 1.],
[ 0., 0., 0., 1., 1., 1.]],
[[ 0., 0., 0., 1., 1., 1.],
[ 0., 0., 0., 1., 1., 1.]]])
to address the above, extract each original img:
two_img =np.stack([np.zeros((2,2,3)), np.ones((2,2,3))], axis=2)
two_img[...,0,:]
Out[160]:
array([[[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.]]])
two_img[...,1,:]
Out[161]:
array([[[ 1., 1., 1.],
[ 1., 1., 1.]],
[[ 1., 1., 1.],
[ 1., 1., 1.]]])
too_img = np.concatenate([np.zeros((2,2,3)), np.ones((2,2,3))], axis=2)
too_img[...,0:3]
Out[163]:
array([[[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.]]])
too_img[...,3:]
Out[164]:
array([[[ 1., 1., 1.],
[ 1., 1., 1.]],
[[ 1., 1., 1.],
[ 1., 1., 1.]]])

Elegant way to create a nxn boundary mask for convolution in python

Whats the most pythonic way of writing a function that returns a nxn boundary mask for convolotion, e.g for 3x3 it will return [[1,1,1],[1,0,1],[1,1,1]], for 5x5 it will return [[1,1,1,1,1],[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[1,1,1,1,1]] and so on.
this works (but isnt so pythonic):
def boundaryMask(size):
mask=np.zeros((size,size))
for i in range(size):
mask[0][i]=1
mask[i][0]=1
mask[i][size-1]=1
mask[size-1][i]=1
return mask
One option would be to create an array of ones, and then assign zeros to the center of the array using slicing:
N = 4
x = np.ones((N, N))
x[1:-1, 1:-1] = 0
x
#array([[ 1., 1., 1., 1.],
# [ 1., 0., 0., 1.],
# [ 1., 0., 0., 1.],
# [ 1., 1., 1., 1.]])
Put in a function and test on various sizes:
def boundaryMask(size):
mask=np.ones((size,size))
mask[1:-1,1:-1] = 0
return mask
boundaryMask(1)
# array([[ 1.]])
boundaryMask(2)
#array([[ 1., 1.],
# [ 1., 1.]])
boundaryMask(3)
#array([[ 1., 1., 1.],
# [ 1., 0., 1.],
# [ 1., 1., 1.]])
boundaryMask(4)
#array([[ 1., 1., 1., 1.],
# [ 1., 0., 0., 1.],
# [ 1., 0., 0., 1.],
# [ 1., 1., 1., 1.]])

Putting multiple columns into callable sub arrays python

I have a set of data which is in columns, where the first column is the x values. How do i read this in?
If you want to store both, x and y values you can do
ydat = np.zeros((data.shape[1]-1,data.shape[0],2))
# write the x data
ydat[:,:,0] = data[:,0]
# write the y data
ydat[:,:,1] = data[:,1:].T
Edit:
If you want to store only the y-data in the sub arrays you can simply do
ydat = data[:,1:].T
Working example:
t = np.array([[ 0., 0., 1., 2.],
[ 1., 0., 1., 2.],
[ 2., 0., 1., 2.],
[ 3., 0., 1., 2.],
[ 4., 0., 1., 2.]])
a = t[:,1:].T
a
array([[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.],
[ 2., 2., 2., 2., 2.]])

Using broadcasting to multiply matrix rows according to elements in a vector?

Let's say I have a matrix
x=array([[ 0., 0., 0.],
[ 0., 0., 1.],
[ 0., 1., 0.],
[ 0., 1., 1.],
[ 1., 0., 0.],
[ 1., 0., 1.],
[ 1., 1., 0.],
[ 1., 1., 1.]])
I want to get
array([[ 0., 0., 0.],
[ 0., 0., 2.],
[ 0., 3., 0.],
[ 0., 4., 4.],
[ 5., 0., 0.],
[ 6., 0., 6.],
[ 7., 7., 0.],
[ 8., 8., 8.]])
How to write the one-line expression between x and range(1,9)? And what is the code for the same operation for columns?
x * np.arange(1, 9).reshape(-1, 1)
or
x * arange(1, 9)[:, np.newaxis]
Both forms make a column vector out of arange(1, 9), which broadcasts nicely along the y axis of x.
"The same operation for columns" is just the transpose of the above, i.e. skip the reshape operation:
x * arange(1, 4)

Slicing a 20×20 area around known indices (x, y) in a numpy array

I have a large 2D numpy array for which I know a pair of indices which represent one element of the array. I want to set this element and the surrounding 20×20 area equal to zero; I have attempted using a slicing technique:
s = array[x:10, y:10]
s == 0
However, although x and y are previously defined, this is an 'invalid slice'.
I would appreciate any suggestions as to how I can accomplish this as I am new to Python.
my_array[x - 10:x + 10, y - 10:y + 10] = 0
or
s = my_array[x - 10:x + 10, y - 10:y + 10]
s[:] = 0
I believe you mean array[x:x+10,y:y+10]
You select multiple elements of an array A with A[start:stop] where start and stop are zero-based indices.
For a 2D Array this applies as well: A[start1:stop1, start2:stop2].
With the following script
import numpy as np
A = np.ones((5,5))
A looks like this
[[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1.]]
with
A[1:4,1:4] = 0
you get
[[ 1. 1. 1. 1. 1.]
[ 1. 0. 0. 0. 1.]
[ 1. 0. 0. 0. 1.]
[ 1. 0. 0. 0. 1.]
[ 1. 1. 1. 1. 1.]]
Note that for the block of zeros to be centered on your x,y coordinates, it must be of odd size. For instance, the block of zeros in the following is not centered the coordinates x,y = 4,6 but on the center coordinates of that cell, that is x, y = 4.5, 5.5:
import numpy
a = numpy.ones((10,10))
x,y = 4,6
s = 2
a[x - s: x + s, y-s: y + s] = 0
array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 1., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 1., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 1., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
whereas this one is:
a = numpy.ones((10,10))
x,y = 4,6
s = 2
a[x - s: x + s + 1, y-s: y + s + 1] = 0
print a
array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 0., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 0., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 0., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 0., 1.],
[ 1., 1., 1., 1., 0., 0., 0., 0., 0., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
If the script is for pixel based image processing, this could be an important distinction.

Categories