2015-07-21 85 views
3

假设我们有一个n*n网格。我们想选择k << n这个网格的不相邻的随机单元格。如果我们用一个包含01的2D Numpy数组来模拟这个网格,在Numpy/Python中这样做的最有效方法是什么?像素网格中非相邻单元的随机采样

有效例子:

enter image description here

非有效实例:

enter image description here

+0

你想从什么分布?你是否想从包含所有非相邻像素k元组的空间中获得均匀样本,因为这些组合采样问题可能非常困难(例如采样矩阵具有固定的行和列总和),即使它们看起来像容易在第一腮红。 – ely

+0

@ Mr.F我正在寻找统一的样品。我不是在寻找所有的k元组。只有一个非相邻像素的k元组很好。 –

+1

如果您的网格中的单元格非常稀疏,那么我只会进行拒绝采样。通过统一采样生成一些候选点,然后检查它们中的任何一个是否相邻,重复直到找到一组有效的点。您可以检查稀疏数据(即点坐标),而不是检查完整的n * n网格。 – YXD

回答

4

这里是一个简单的实现拒绝抽检。由于您只想测试此距离阈值内是否至少有一对,因此可能会有一种比query_pairs事件(在这种情况下还会检查冲突)更快的方式进行邻接检查。

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) 

考虑看看结果:

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

+0

您的拒绝抽样算法似乎没有工作。我认为可能'有效= len(kdtree(coords).query_pairs(1.0))== 0'没有做到这里的意思。试试'query_pairs(10)'或者其他大于1的数字......你会发现它不会产生所需的结果。 – user11

+1

谢谢你指出这一点。问题在于数据应该被转置:“kdtree”将输入视为两个50维数据点。我更新了代码。 – YXD

3

我看到了,这已经是一个公认的答案,但它是一个艰巨的任务,所以我解决了如下,我喜欢它,因此我给了一个upvote问题:):

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  

输出:

(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.]] 

它总是提供了非相邻小区的随机组合。 享受它! :)