user271528
user271528

Reputation:

Fancy indexing with tuples

Say I have a 100x100 array in numpy, from this array I want to select 10 random blocks of (x*x) pixels and change the values of these blocks simultaneously. What is the best way to index the slices for each block? An ideal solution would be something along the lines of the following, where the slices are taken between the pairs of tuples.

A = np.ones(100,100)
blockSize = 10

numBlocks = 15

blockCenter_Row = tuple(np.random.randint(blockSize,high=(100-blockSize),size=numBlocks))
blockCenter_Col = tuple(np.random.randint(blockSize,high=(100-blockSize),size=numBlocks))
rowLeft_Boundary = tuple((i-blockSize/2) for i in blockCenter_Row)
rowRight_Boundary = tuple((i+blockSize/2) for i in blockCenter_Row)
colLower_Boundary = tuple((i-blockSize/2) for i in blockCenter_Row)
colUpper_Boundary = tuple((i+blockSize/2) for i in blockCenter_Row)

for value in range(10):
    A[rowLeft_Boundary:rowRight_Boundary,colLower_Boundary:colUpper_Boundary] = value

Upvotes: 0

Views: 989

Answers (1)

HYRY
HYRY

Reputation: 97271

I think you can use as_strided() to do the trick, if the blocks can be overlaped.

import pylab as pl
from numpy.lib.stride_tricks import as_strided

blockSize = 10
numBlocks = 15
n = 100
a = np.zeros((n, n))

itemsize = a.dtype.itemsize
new_shape = n-blockSize+1, n-blockSize+1, blockSize, blockSize
new_stride = itemsize*n, itemsize, itemsize*n, itemsize
b = as_strided(a, shape=new_shape, strides=new_stride)

idx0 = np.random.randint(0, b.shape[0], numBlocks)
idx1 = np.random.randint(0, b.shape[1], numBlocks)

b[idx0, idx1, :, :] = np.random.rand(numBlocks, blockSize, blockSize)*3 + np.arange(numBlocks).reshape(-1, 1, 1)

pl.imshow(a, cmap="gray", interpolation="nearest")

here is the output:

enter image description here

Upvotes: 3

Related Questions