Turn grid into a checkerboard pattern in python? - python

I have successfully created a grid, but am now trying to turn my grid into a checkerboard pattern, preferably using a variant of the floodfill command. how do I make sure the program recognizes which squares are even and which are odd?
currently the IDE is set so m[i][j]= 1 gives blue, while m[i][j]= 0 gives red, which I am happy to keep, and so I do not need to define the colors. Thank you.
Code I have so far :
from pylab import *
from numpy import *
from math import *
m=zeros((100,100))
for i in range(100):
for j in range(100):
if (math.floor(i) % 10) != 0:
if (math.floor(j) % 10) != 0:
m[i][j]= 1
else:
m[i][j]= 0
imshow(m)
show()
Code output :

import numpy as np
def make_checkerboard(n_rows, n_columns, square_size):
n_rows_, n_columns_ = int(n_rows/square_size + 1), int(n_columns/square_size + 1)
rows_grid, columns_grid = np.meshgrid(range(n_rows_), range(n_columns_), indexing='ij')
high_res_checkerboard = np.mod(rows_grid, 2) + np.mod(columns_grid, 2) == 1
square = np.ones((square_size,square_size))
checkerboard = np.kron(high_res_checkerboard, square)[:n_rows,:n_columns]
return checkerboard
square_size = 5
n_rows = 14
n_columns = 67
checkerboard = make_checkerboard(n_rows, n_columns, square_size)

You can check the sum of the two indices (row and column) and color it with the first color if it's odd and second otherwise. Something like:
for i in range(nrows):
for j in range(ncols):
m[i][j] = 0 if (i+j)%2 else 1

Use the modulus operation:
m[i][j] = (i+j) % 2

I would create a linear array, fill every second value and reshape.
In your case (even amount of columns), prepend one column and get rid of it after reshaping:
import numpy as np
rows = 100
cols = 100 + 1 # product of rows*cols must be odd, we fix it later
m = np.zeros((rows*cols, 1)) # create array
m[::2] = 1 # fill every second
m = np.reshape(m, (rows, cols)) # reshape array to matrix
m = m[:, :-1] # cut additional column

You can create a checkerboard style array with NumPy, then resize it with scipy's imresize to make that equal to your desired canvas area.
Thus, the steps would be :
1) Create a NumPy array of shape (10,10) corresponding to 10 x 10 sized checkerboard pattern. To do so, start with zeros array and fill the alternate rows and columns with ones :
arr = np.zeros((10,10),dtype=int)
arr[::2,::2] = 1
arr[1::2,1::2] = 1
2) Resize the array 10x to have (100,100) pixel sized output image :
from scipy.misc import imresize # Importing required function
out = imresize(arr,10*np.array(arr.shape),interp='nearest')/255
Output :

With only minimal modification of your code it would look something like this:
from pylab import *
from numpy import *
from math import *
m=zeros((100,100))
for i in range(100):
for j in range(100):
if (math.floor(i) % 10) != 0:
if (math.floor(j) % 10) != 0:
m[i][j]= 1
if (int(i / 10) + int(j / 10)) % 2: # the only two extra lines.
m[i][j] = 0 #
imshow(m)
show()
Alternatively just this (assuming you really need the 100x100) to get rid of the "boundary lines":
m=zeros((100,100))
for i in range(100):
for j in range(100):
m[i][j] = (int(i / 10) + int(j / 10)) % 2
Cheers.

Related

How can I search grids within a numpy array?

I have a 100x100 grid of 1s and 0s, and I want to determine whether there are more than 4 0s within any given 3x3 on the 100x100 array. If less or equal this would return true, greater would return False. How can I do this?
You could also do something like this
from scipy.signal import convolve2d
window_size = 3
kernel = np.ones((window_size, window_size))
test_array = np.zeros((100, 100))
test_array[33:35, 33] = 1
test_array[34, 33:36] = 1
output = convolve2d(test_array, kernel, mode='valid')
threshold = 4
hits = np.nonzero(output >= threshold)
Where the "hits" are the top-left corners of the windows.
You could just do a brute force search
import numpy as np
grid = np.random.randint(0, 5, (100, 100))
summ = 0
searched = 0
for ii in range(100 - delta):
for jj in range(100 - delta):
searched += 1
if np.where(grid[ii:ii+delta, jj:jj+delta] == 0)[0].size > 4:
print('zeros found in (%i,%i) through (%i,%i) ' % (ii, jj, ii+delta, jj+delta))
summ += 1
print('number of sets of zeros > 4: %i/%i' % (summ, searched))

Is there a way to use numpy array functions to get this same effect?

I am trying to filter out all non-gray values within a given tolerance with the following code. It gives the expected results but runs too slowly to use in practice. Is there a way to do the following using numpy operations?
for i in range(height):
for j in range(width):
r, g, b = im_arr[i][j]
r = (r + 150) / 2
g = (g + 150) / 2
b = (b + 150) / 2
mean = (r + g + b) / 3
diffr = abs(mean - r)
diffg = abs(mean - g)
diffb = abs(mean - b)
maxdev = 2
if (diffr + diffg + diffb) > maxdev:
im_arr[i][j][0] = 0
im_arr[i][j][1] = 0
im_arr[i][j][2] = 0
Looping in plain Python is slow: one of the advantages of numpy is that
transversing the arrays is highly optimized. Without commenting on the algorithm, you can get the same results using only numpy, which will be much faster
Since im_arr is an image, it is very likely that the dtype is np.uint8.
That is only 8 bits, so you have to be careful of overflows. In you code, when you add 150 to a number, the result will be of type np.int64. But if you add 150 to an 8-bit np.ndarray, the result will still be of type np.uint8 and it can overflow.
You can either change the array type (using astype) or add a float, which will automatically promote the array to float
mod_img = (im_arr + 150.)/2 # the point of "150." is important
signed_dif = mod_img - np.mean(mod_img, axis=2, keepdims=True)
collapsed_dif = np.sum(np.abs(signed_dif), axis=2)
maxdev = 2
im_arr[collapsed_dif > maxdev] = 0
This can be done without any loop. I'll try to break out every step into a dedicated line
import numpy as np
im_arr = np.random.rand(300,400,3) # Assuming this how you image looks like
img_shifted = (im_arr + 15) / 2 # This can be done in one go
mean_v = np.mean(img_shifted, axis=2) # Compute the mean along the channel axis
diff_img = np.abs(mean_v[:,:,None] - img_shifted) # Broadcasting to subtract n x m from n x m x k
maxdev = 2
selection = np.sum(diff_img, axis=2) > maxdev
im_arr[selection] = 0 # Using fancy indexing with booleans

Generating a random line on a 2d array in python

I've got a 2d array of zeros: 250 by 250. And I want to generate a random straight random line of a specific length (haven't yet decided). Obviously, since it's a line the values that turn from zero to one must be connected in some way, vertically, horizontally, or diagonally; and it also has to be straight. How could I do this? I'm quite stuck with this problem, any help would be appreciated.
We can do:
import numpy as np
SIZE = 250
arr = np.zeros((SIZE, SIZE))
M_POS = np.arange(-SIZE, SIZE)
M_POS = np.r_[M_POS, 1 / M_POS[M_POS!=0]]
M = np.random.choice(M_POS, 1)[0]
N = np.random.choice(np.arange(-SIZE, SIZE), 1)[0]
L = 50
P0 = np.array([0, N])
X_Y = np.array([1, 1 / M]) if abs(M) < 1 else np.array([1, M])
draw_in = np.add(np.repeat([P0], L, axis=0),
np.repeat([X_Y], L, axis=0) * np.arange(L)[:, np.newaxis]).astype(int)
draw_in = draw_in[((draw_in < SIZE) & (draw_in>0)).all(axis=1)]
arr[draw_in[:, 0], draw_in[:, 1]] = 1

Circular mask numpy array in one step

I want to apply a circular mask to all elements in a numpy array with specific values. At the moment my (example) code looks like this:
import numpy as np
n = 14
r = 3 #radius
### example array ###
array = np.zeros((n, n))
array[2,:]=1
array[:,5]=1
array[5,:]=1
array[:,9] = 3
a, b = np.where((array == 1) | (array == 3))
print(array)
### applying mask ###
for i in range(a.size-1):
y,x = np.ogrid[-a[i]:np.size(array, 0)-a[i], -b[i]:np.size(array, 1)-b[i]]
mask = x*x + y*y <= r*r
array[(mask) & (array != 1) & (array != 3)] = 255 # setting elements in neighborhood of 1 and 3 to 255
print(array)
The code works as I want it but my real data is much bigger and the algorithm is very slow. At the moment every point/mask gets evaluated one after another (for loop). Is there a way to create a mask for all 1 and 3 (in this example) at one time?

Can I do a mathematical-shape mask for a (Nx,Ny) matrix?

I have a matrix of numbers (Nx,Ny) and I would like to select from that matrix a mathematical shape coordinates/components as it could be a line with a given slope.
I learned how to create a mask and how to do it in a random way but I cannot think of how to generate a mathematical-shape mask in python.
This is some of the code that I've been able to develop. If you know a better way to do this I will be also grateful of being told.
import random
import numpy as np
threshold = 0.85
radius=40
sq7=1/(radius*radius)
matrix=np.zeros((Nx,Ny))
for i in range(0,Nx):
for j in range(0,Ny):
if ((i-Nx*0.5)*(i-Nx*0.5)*sq7+(j-Ny*0.5)*(j-Ny*0.5)*sq7<=1.0):
matrix[i,j]= 1.0 - 0.1*random.random();
else:
matrix[i,j]=-1.0 + random.random();
randoms = np.random.normal(0,scale=0.002, size=matrix[mask].shape)
mask = matrix**2 < threshold
matrix[mask] += randoms * (1 - matrix[mask]**2)
At the end I found a very easy way of doing so. What I just did was to create a new matrix of the same dimensions as the one that I want to mask and then just by going through the matrix itself and comparing with the values of my function I could do it so easily. I will leave the code here.
def func_normaldist(x,Ny):
y = np.exp(-0.5*(x-int(Ny/2))**2)/np.sqrt(np.pi*2.)
return y
def mask_uvalues_centered_geometry(Nx, Ny): #u
mask = np.zeros((Nx,Ny))
# Initial configuration: rectangle of Nx x Ny
for j in range(0,Ny):
for i in range(0,Nx):
if (i < Ny*Nx*func_normaldist(j,Ny)):# and (i > int(Nx/2 + 1)):
mask[j,i] = True
else:
mask[j,i] = False;
return mask
Nx = 50
Ny = 50
a = mask_uvalues_centered_geometry(Nx,Ny)
print(a)

Categories