Trying to extract a patch given 8 points from NumPy array - python

I have an array which looks like this
boxes = [268,885,426,865,406,707,248,727]
It's a collection of (x,y) points. If I plot this using this function:
def draw_boxes_on_image_mod(image, boxes):
image_copy = image.copy()
image_copy = np.array(image_copy)
cv2.line(image_copy, (boxes[0],boxes[1]),(boxes[2],boxes[3]),(0,255,255),2)
cv2.line(image_copy, (boxes[4], boxes[5]),(boxes[6],boxes[7]),(0,255,255),2)
cv2.line(image_copy, (boxes[0],boxes[1]),(boxes[6],boxes[7]),(0,255,255),2)
cv2.line(image_copy, (boxes[4], boxes[5]),(boxes[2],boxes[3]),(0,255,255),2)
scipy. misc.imsave('/home/ryan/TEST.png', image_copy)
return image_copy
I get an image with a rectangle drawn on the part of the image I'm interested in, But what I want is to extract that portion and convert it into an image.
I was thinking of using NumPy indexing to achieve this but
image = image[268:426]
I am finding it difficult to understand how to index the (x,y) values together.
Any suggestions would be really helpful.Thanks in advance.

When you just call A[1:3] all you are asking for are the rows 1 and 2, the rows including 1 and stopping before 3, so you must take into account columns as well to get the exact subsection you need.
You can do this in numpy by stating the range of the rows and columns, the subsection of the array you want will start at a row and end at row + m as well as starting at a column and ending at column + n
For example take
A = np.array([[0, 0, 0, 0],
[0, 1, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 0]])
We want just the values in the middle set to 1, so we select them with
Asub = A[1:3,1:3]
To get
[[1 1]
[1 1]]

Related

numpy vectorization of cellular automata

Trying to optimize my current implementation of a program that generates cellular automata using Wolfram Numbering. I am having trouble applying the rule to the board after calculating the neighbors for each cell. The current example uses 2 states and is the same as Conway's Game of Life, but my program can do any number of states. The decimal 224 corresponds to the ruleset for CGOL in the following way:
[0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0]
Basically, there are 18 positions, or nine possible neighborhood sums for each state (0-8).
If the current cell is 1, you index into the rule in the following way:
>>> [0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0][1::2]
[0, 0, 1, 1, 0, 0, 0, 0, 0]
1 being the value of the cell, and 2 being the number of states. As you can see, if the state is 1, then if there are 2 or 3 neighbors the cell survives, else dies. From there you index w/ the neighborhood sum for that cell to get the actual update value of the cell. So to update a cell in each generation you do: Rule[state_value::total_states][sum of neighbors].
E.g.,
>>> [0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0][1::2][2]
1
Currently then, I have the grid of all cells, called world, of an arbitrary shape, another equally shaped numpy array that has the sum of all the neighbors for each of those cells calculated using convolve from scipy - call it nbrs -, and the previously mentioned list for the rule - is it possible to update the value of each cell in world while avoiding a for loop?
For instance:
world = rule[cell_value::total_states][sum_of_neighbors_for_given_cell_in_nbrs]
You haven't given us a lot of code to work with, so here is a minimal idea of how it could work.
First, create an array that you can index with the current state to get the rule:
rule = [0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0]
rule_map = np.stack((rule[0::2], rule[1::2]), axis=0)
Now you can use your current states to get the rule for each cell:
world = np.random.randint(2, size=(5, 6))
cur_cell_rules = rule_map[world] # shape: (5, 6, 9)
To get the new world state, we can use index interators. Here, I use an array containing all world indices to first get the (flattened) current cell neighborhood sums, and then use those to get the (flattened) new states. In the assignment, I unflatten it again to the world shape. (There probably is an easier way to do this...)
cur_cell_neighborhood_sum = ... # shape: (5, 6)
world_ind = np.asarray([*np.ndindex(world.shape)])
# update world
world[world_ind[:, 0], world_ind[:, 1]] = cur_cell_rules[world_ind[:, 0], world_ind[:, 1], cur_cell_neighborhood_sum[world_ind[:, 0], world_ind[:, 1]]]
Edit:
To avoid the large cur_cell_rules array, you can go the other way, too:
world_potential = rule_map[:, cur_cell_neighborhood_sum] # shape: (2, 5, 6)
# update world, this time in smaller steps
world_flat = world[world_ind[:, 0], world_ind[:, 1]]
world_new_flat = world_potential[world_flat, world_ind[:, 0], world_ind[:, 1]]
world[world_ind[:, 0], world_ind[:, 1]] = world_new_flat

Mask an image where masked pixels exist in list of pixel values

I am trying to mask an image where the masked values correspond to any one of several of values in a list.
Consider the following "image" and "pixel values"
import numpy
img = numpy.arange(27).reshape(3,3,3) #something to represent an image
pixels = [numpy.array([0,1,2]), numpy.array([9,10,11])] #arbitrarily selected "pixel" values
I am trying to come up with some procedure that will output a 2d mask array where masked values correspond to pixel values in the list pixels
Goal:
In [93]: mask
Out[93]:
array([[1, 0, 0],
[1, 0, 0],
[0, 0, 0]])
Attempt 1 from this answer:
mask = numpy.zeros( img.shape[:2], dtype = "uint8" )
mask[numpy.in1d(img, pixels).reshape(mask.shape)] = 1
This results in ValueError: cannot reshape array of size 27 into shape (3,3)
I believe this answer assumes a 2d input as img
Attempt 2:
mask = numpy.zeros(img.shape[:2])
for x,y in [(x,y) for x in range(img.shape[0]) for y in range(img.shape[1])]:
if img[x,y,:] in pixels:
mask[x,y] = 1
This results in ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all(), but imagine there's a more concise approach than looping through each value.
Setup
Make sure your pixels is a numpy.array first:
pixels = np.array(pixels)
You can make use of broadcasting here, just be careful that the memory requirement is not too high:
(img[:, None] == pixels[:, None]).all(-1).sum(1)
array([[1, 0, 0],
[1, 0, 0],
[0, 0, 0]])
You are getting a ValueError, because you use np.array as "input" for if statement. But it has to be a bollean or a number. When you use numpy.all, you turn numpy array into boolean (it is True when all elements are diffrent then zero).
Solution
for x,y in [(x,y) for x in range(img.shape[0]) for y in range(img.shape[1])]:
if numpy.all(numpy.isin(img[x, y, :], pixels)):
mask[x,y] = 1
Convert your pixels to a list of lists and then you can do this by using simple list comprehension:
pixels = [list(pixel) for pixel in pixels]
mask = [[int(list(row) in pixels) for row in i] for i in img]
OUTPUT:
[[1, 0, 0], [1, 0, 0], [0, 0, 0]]
np.array returns a value for each element when you do a comparison using ==, which is why it gives you that error when you compare using in. sublist in list returns a single truth value.
A solution I found which is faster than the other answers so far and requires minimal additional memory:
mask = numpy.zeros( img.shape[:2], dtype=bool )
for pixel in numpy.unique(pixels, axis=0):
mask |= (img == pixel).all(-1)

Create matrix with same in and out degree for all nodes

I've stated this question in graph theory terms, but that conceptualization isn't necessary.
What I'm trying to do, using Python, is produce a matrix of zeros and ones, where every row has the same number of ones and every column has the same number of ones. The number for rows will not be the same as the number for columns when the number of rows (sending nodes) does not equal the number of columns (receiving nodes) -- which is something I'm allowing.
It makes sense to me to do this in numpy, but there may be other packages (like networkx?) that would help.
Here's the function I'm looking to write with the desired inputs and outputs:
n_pre = 4 # number of nodes available to send a connection
n_post = 4 # number of nodes available to receive a connection
p = 0.5 # proportion of all possible connections that exist
mat = generate_mat(n_pre, n_post, p)
print mat
The output would be, for example:
[[0, 1, 0, 1],
[1, 0, 1, 0],
[1, 1, 0, 0],
[0, 0, 1, 1]]
Notice, every column and every row has two ones in it. Aside from this constraint, the positions of the ones should be random (and vary from call to call of this function).
In graph theory terms, this means every node has an in-degree of 2 and an out-degree of 2 (50% of all possible connections, as specified with p = 0.5).
For a square matrix, what you describe is the adjacency matrix of a random k-regular directed graph, and there are known algorithms to generate such graphs. igraph implements one:
# I think this is how you call it - it's an instance method for some reason.
igraph.Graph().K_Regular(n, k, directed=True)
networkx has a function for random k-regular undirected graphs:
networkx.random_regular_graph(k, n)
For a non-square matrix, what you describe is isomorphic to a random biregular graph. I have found no convenient existing implementation for random biregular graphs, but the term should be a good starting point for searching for known algorithms.
First, do the pre-work so that we have available the size of the square matrix and the population pop of each row and column. Now, initialize a matrix with pop ones on the diagonal. For n = 6 and pop = 3, you'd have
[[1, 1, 1, 0, 0, 0]
[0, 1, 1, 1, 0, 0]
[0, 0, 1, 1, 1, 0]
[0, 0, 0, 1, 1, 1]
[1, 0, 0, 0, 1, 1]
[1, 1, 0, 0, 0, 1]]
Now, apply your friendly neighborhood random shuffle operation to the columns, then the rows (or in the other order). There's your matrix. A shuffle of rows-only or columns-only does not change the population on either axis.

Python vtkInterface0.9.3 library examples not working

I found out about vtkInterface, a python vtk wrapper that facilitates vtk plotting.
Trying to run their first example, under Initialize from Numpy Arrays in this page: vtkInterface.PolyData, by simply running the code as is, and it results in a gray render window with nothing in it.
Some of the other examples do work but this is exactly the thing that I need at the moment and was wondering if anybody has tried it and knows what might be wrong.
Example Code:
import numpy as np
import vtkInterface
# mesh points
vertices = np.array([[0, 0, 0],
[1, 0, 0],
[1, 1, 0],
[0, 1, 0]])
# mesh faces
faces = np.hstack([[4, 0, 1, 2, 3], # square
[3, 0, 1, 4], # triangle
[3, 1, 2, 4]]) # triangle
surf = vtkInterface.PolyData(vertices, faces)
# plot each face with a different color
surf.Plot(scalars=np.arange(3))
The example is wrong. It lacks a fifth point. For example this will work.
vertices = np.array([[0, 0, 0],
[1, 0, 0],
[1, 1, 0],
[0, 1, 0],
[0.5, 0.5, -1]])
Explanation: In VTK, faces are encoded in the following way:
face_j = [ n, i_0, i_1, ..., i_n ]
Here, n is the number of points per face, and i_k are the indices of the points in the vertex-array. The face is formed by connecting the points vertices[i_k] with k in range(0,n). A list of faces is created by simply concatenating the single face specifications:
np.hstack([face_0, face_1, ..., face_j, ...])
The advantage of this encoding is that the number of points used per face, n, can vary. So a mesh can consist of lines, triangles, quads, etc.
In the example, the vertex with id 4 is used in the second and third face. So vertices is required to consist of at least five entries. Surprisingly, the sample doesn't crash, as VTK almost certainly would if some faces were accessing non-existing points.

How can I make an 8by8 grid in Python and then be able to move a counter around it?

I need to make an 8by8 grid on python to form the basis of a game I am making. I then need to be able to move a counter around this grid. Thanks
Firstly clarify what exactly is this counter?
To address the grid, python lets you have multi-dimensional lists (list of lists)
Example:
# A 4x4 grid with all values to zero
grid = [[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]
# It doesn't have to be numbers it can be any object
# Accessing the grid
for y in range(len(grid)): # Goes through each row
for x in range(len(grid[y])): # Goes through each column in the row
grid[y][x] # This gets the value in y-row, x-column
But if you are working with 2D data structure (or higher), I recommend numpy.
Numpy offers easy use of multi-dimensional lists (or arrays as they are called)
import numpy as np
grid = np.zeros((4,4)) # np.zeros just fills the array with zeros
# (4,4) is the shape (4x4 = (4,4), 4x4x4 = (4,4,4) and so on)
# The grid can be accessed the same way as above
Hope this helps if not well then I guess we need more details

Categories