Numpy-like indexing and assignment with Tensorflow - python

I made a simple example of numpy array indexing and assignment where the goal is to make a small white square on a black screen.
How would I replicate the following code using Tensorflow?
black_img = np.zeros([5, 5, 3])
white_rect = np.ones([3, 3])
size = np.arange(3)
black_img[size, size] = white_rect

You can create constants or variables in TensorFlow.
black_img = np.zeros([5, 5, 3], dtype = np.int32)
black_img_tf = tf.constant(np.zeros([5, 5, 3], dtype = np.int32))
Output:
<tf.Tensor: shape=(5, 5, 3), dtype=int32, numpy=
array([[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]])>
However, TensorFlow does not support item assignment like NumPy.
However, you can create a new constant or variable using results obtained from NumPy operations.
Code:
black_img[size, size] = white_rect
tf.constant(black_img)
Output:
<tf.Tensor: shape=(5, 5, 3), dtype=int32, numpy=
array([[[1, 1, 1],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[1, 1, 1],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[1, 1, 1],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]])>
Note that individual item assignment is not allowed but you can do operations like addition, subtraction on tensors.
c = tf.constant(np.ones([3, 3], dtype = np.int32)) + tf.constant(np.ones([3, 3], dtype = np.int32))
c
Output:
<tf.Tensor: shape=(3, 3), dtype=int32, numpy=
array([[2, 2, 2],
[2, 2, 2],
[2, 2, 2]])>

Related

Getting a list of 3 by 3 boxes in a Sudoku puzzle

Assuming the sudoku puzzle is a 9 by 9 and is filled with 0-9. I want is 9 lists, with each list containing a 3 by 3 Sudoku box.
This is what I have:
grid = [[5, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 8, 7, 0, 6, 0],
[0, 0, 0, 0, 0, 3, 0, 0, 0],
[0, 5, 0, 0, 6, 1, 0, 7, 0],
[0, 0, 2, 0, 0, 0, 9, 0, 0],
[0, 0, 0, 4, 0, 0, 0, 0, 0],
[0, 0, 0, 5, 0, 0, 0, 4, 0],
[9, 0, 0, 0, 4, 8, 7, 0, 0],
[0, 8, 0, 3, 0, 0, 0, 0, 0]]
list1 = []
for i in range(0,3):
for j in range(0,3):
list1.append(grid[i][j])
list2 = []
for i in range(0,3):
for j in range(4,7):
list2.append(grid[i][j])
and it goes on and on.......
How do I simplify this for loop for getting a list of 3 by 3 boxes in Sudoku puzzle?
You need to add a step parameter to your range()s so that you start reading in each box at the appropriate row / column index:
from itertools import product
boxes = []
for row_start, col_start in product(range(0, 9, 3), repeat=2):
boxes.append([
[grid[row][col] for col in range(col_start, col_start + 3)]
for row in range(row_start, row_start + 3)
])
print(boxes)
This outputs:
[
[[5, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [0, 8, 7], [0, 0, 3]],
[[0, 0, 1], [0, 6, 0], [0, 0, 0]],
[[0, 5, 0], [0, 0, 2], [0, 0, 0]],
[[0, 6, 1], [0, 0, 0], [4, 0, 0]],
[[0, 7, 0], [9, 0, 0], [0, 0, 0]],
[[0, 0, 0], [9, 0, 0], [0, 8, 0]],
[[5, 0, 0], [0, 4, 8], [3, 0, 0]],
[[0, 4, 0], [7, 0, 0], [0, 0, 0]]
]
from pprint import pprint as pp
SIZE = 3
sudoku = [[[0] * SIZE for _ in range(SIZE)] for _ in range(SIZE * SIZE)]
# example of populating it
for i in range(SIZE):
for j in range(SIZE):
counter = i * SIZE + j
sudoku[counter][i][j] = counter + 1
pp(sudoku)
output
[[[1, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 2, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 3], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [4, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 5, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 6], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [7, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 8, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 9]]]

Strange behavior of skimage.morphology.skeletonize3d

It is strange the if using skimage.morphology.skeletonize_3don structure as below. It will remove all elements. Such structure is a equilateral triangle in 3d space.
array = np.array([
[[0, 1, 0],
[0, 0, 1],
[0, 0, 0]],
[[0, 0, 0],
[0, 1, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]]).astype('uint8')
morphology.skeletonize_3d(array)
Output:
array([[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]], dtype=uint8)
It results as an empty array. This is strange. Could anyone explain it? How to avoid it?

fill numpy array with sequence of numbers

I have a numpy array with the shape (6, 3, 4) that I'd like to fill with an ascending sequence of numbers so that the resulting array is this:
array([[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[1, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[2, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[3, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[4, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]],
[[5, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]]], dtype=uint8)
I do not want to use a loop, if possible.
I've tried the following with no luck:
import numpy as np
new_row = np.zeros([6, 3, 4], dtype=np.uint8)
new_row[:,0:1,0:1] = range(6)
which results in ValueError: could not broadcast input array from shape (6) into shape (6,1,1)
Any help appreciated

Change all positive values in array to 1 (Python)

So I have several 3D arrays that I need to add together. Each array consists of entries with either 0 or 1. All arrays also have the same dimension. Now, when I add these arrays together some of the values overlap (which they do). However, I just need to know how the structure of the total combined array is, which means that I don't need the values 1, 2 or 3 when 2 or 3 arrays have overlapped. This also just need to be one, and of course, wherever there is a zero, the value zero just need to remain zero.
So basically what I have is:
array1 =
[[[1, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 1, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 1], [1, 1, 1], [0, 0, 0]]]
array2 =
[[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 0, 0], [1, 1, 0], [0, 0, 0]],
[[0, 0, 1], [0, 1, 0], [0, 0, 0]]]
So when adding them together I get:
array_total = array1 + array2 =
[[[2, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [1, 1, 0], [0, 0, 0]],
[[0, 0, 2], [1, 2, 1], [0, 0, 0]]]
Where I actually want it to give me:
array_total = array1 + array2 =
[[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [1, 1, 0], [0, 0, 0]],
[[0, 0, 1], [1, 1, 1], [0, 0, 0]]]
So can anyone give me a hint to how this is done ?
(Assuming those are numpy arrays, or array1 + array2 would behave differently).
If you want to "change all positive values to 1", you can do this
array_total[array_total > 0] = 1
But what you actually want is an array that has a 1 where array1 or array2 has a 1, so just write it directly like that:
array_total = array1 | array2
Example:
>>> array1 = np.array([[[1, 0, 0], [0, 0, 0], [0, 0, 0]],
... [[0, 1, 0], [0, 0, 0], [0, 0, 0]],
... [[0, 0, 1], [1, 1, 1], [0, 0, 0]]])
>>> array2 = np.array([[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
... [[0, 0, 0], [1, 1, 0], [0, 0, 0]],
... [[0, 0, 1], [0, 1, 0], [0, 0, 0]]])
>>> array1 | array2
array([[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [1, 1, 0], [0, 0, 0]],
[[0, 0, 1], [1, 1, 1], [0, 0, 0]]])

label 3d numpy array with scipy.ndimage.label

I've got a large 3d numpy array which consists of ones and zeros. I would like to use the scipy.ndimage.label tool to label the features in each sub-array (2d).
A subset of the 3d-array looks like:
import numpy as np
from scipy.ndimage import label
subset = np.array([[[1, 0, 0],
[1, 0, 1],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 1],
[0, 0, 1]],
[[0, 0, 0],
[1, 0, 0],
[0, 1, 1]],
[[0, 0, 0],
[1, 0, 0],
[1, 1, 1]]], dtype=uint8)
When I use the label tool on a small part of this subset is works correct:
>>>label(subset[0:3])
(array([[[1, 0, 0],
[1, 0, 2],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 2],
[0, 0, 2]],
[[0, 0, 0],
[1, 0, 0],
[0, 2, 2]]]), 2)
However, when I use the entire subset the label tool is not working properly:
>>>label(subset)
(array([[[1, 0, 0],
[1, 0, 1],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 1],
[0, 0, 1]],
[[0, 0, 0],
[1, 0, 0],
[0, 1, 1]],
[[0, 0, 0],
[1, 0, 0],
[1, 1, 1]]]), 1)
Any ideas how this problem can be tackled?
ps.
The complete array which I am trying to label consists of 350219 2d arrays.
I answered this question with the help of dan-man.
I had to define a new 3D structure for the label tool:
import numpy as np
from scipy.dimage import label
str_3D = np.array([[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
[[0, 1, 0],
[1, 1, 1],
[0, 1, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]], dtype='uint8')
Now the label returns the following for my subset:
>>> label(subset, structure=str_3D)
# outputs:
(array([[[1, 0, 0],
[1, 0, 2],
[0, 0, 0]],
[[0, 0, 0],
[3, 0, 4],
[0, 0, 4]],
[[0, 0, 0],
[5, 0, 0],
[0, 6, 6]],
[[0, 0, 0],
[7, 0, 0],
[7, 7, 7]]]), 7)

Categories

Resources