2015-07-21 58 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.]] 

它總是提供了非相鄰小區的隨機組合。 享受它! :)