Random sampling of non-contiguous cells in a pixel grid

Let's assume we have a grid n*n

. We would like to select k << n

random cells in this grid that are not contiguous. If we model this mesh with a 2D Numpy array containing 0

and 1

, what is the most efficient way to do it in Numpy / Python?

Valid example:

enter image description here

Invalid example:

enter image description here

+3


source to share


2 answers


Here's the simplest implementation of rejection fetch. There may be a faster way to perform adjacency checking than an object query_pairs

(which in this case will also check for collisions), since you only want to check if at least one pair exists within that distance threshold.

import numpy as np
from scipy.spatial import cKDTree as kdtree

n = 100
k = 50

valid = False

while not valid:
    # generate k grid indices
    coords_flat = np.random.random_integers(0, n ** 2 - 1, size=k)
    coords = np.unravel_index(coords_flat, dims=(n, n))
    # test there are no adjacent cells
    transposed = np.transpose(coords)
    valid = len(kdtree(transposed).query_pairs(1.0)) == 0

print(coords)

      

Taking a look at the results:



import matplotlib.pyplot as plt
grid = np.zeros((n, n), dtype=np.bool)
grid[coords] = True
plt.imshow(grid)
plt.savefig('result.png')

      

enter image description here

+4


source


I saw that this was already the accepted answer, but it was a tricky one, so I solved the following and I liked it, so I gave an upvote a question :):

import numpy as np

xy = []

x = np.random.randint(0,5)
y = np.random.randint(0,5)

xy.append((x,y))

while True:

    x = np.random.randint(0,5)
    y = np.random.randint(0,5)

    for ii,i in enumerate(xy):    
        if x in [i[0]-1, i[0], i[0]+1]:
            if x == i[0]:
                if y in [i[1]-1, i[1], i[1]+1]:
                    break    
                else:
                    if ii == len(xy) - 1:
                        xy.append((x,y))
                        break
            elif y == i[1]:
                break
        elif ii == len(xy) - 1:
            xy.append((x,y))
            break

    if len(xy) == 3:
        break

for cords in xy:
    print cords

sq =np.zeros((5,5))

for cords in xy:
    sq[cords] = 1

print sq    

      

Output:



(1, 0)
(4, 4)
(4, 1)
[[ 0.  0.  0.  0.  0.]
 [ 1.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  1.]]

      

It always provides a random combination of non-contiguous cells. Enjoy it!:)

+3


source







All Articles