2015-06-16 15 views
9

İki boyutlu bir Python numpy dizisine dönüştürdüğüm benzersiz ID yamaları/bölgeleri içeren bir rasterim var. Ben için çift yönlü hesaplamak istiyorum Tüm raster yamanın en yakın kenarlarını ayıran minimum mesafeyi elde etmek için arasındaki tüm bölgeler arasındaki Öklid uzaklıkları. Dizi başlangıçta bir raster olduğundan, bir çözüm hücreler arası çapraz mesafeleri hesaba katmak zorundadır (raster çözünürlüğü ile çarparak her zaman hücrelerde ölçülen mesafeleri metreye geri dönüştürebilirim).Benzersiz Python dizi bölgeleri arasındaki mesafelerin hesaplanması?

this answer to a related question önerildiği gibi scipy.spatial.distance den cdist fonksiyonu ile denediği, ama şu ana kadar mevcut belgeleri kullanarak benim sorunu çözmek yapamaz oldum. Bir sonuç olarak ideal olarak, tüm olası bölge kombinasyonları arasındaki mesafeler dahil olmak üzere "ID'den ID'ye, mesafe" biçiminde bir 3'e X dizisine sahip olacağım. Bu tamsayı varsayar

import numpy as np 
import matplotlib.pyplot as plt 

# Sample study area array 
example_array = np.array([[0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0], 
          [0, 0, 2, 0, 2, 2, 0, 6, 0, 3, 3, 3], 
          [0, 0, 0, 0, 2, 2, 0, 0, 0, 3, 3, 3], 
          [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0], 
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3], 
          [1, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3], 
          [1, 1, 1, 0, 0, 0, 3, 3, 3, 0, 0, 3], 
          [1, 1, 1, 0, 0, 0, 3, 3, 3, 0, 0, 0], 
          [1, 1, 1, 0, 0, 0, 3, 3, 3, 0, 0, 0], 
          [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
          [1, 0, 1, 0, 0, 0, 0, 5, 5, 0, 0, 0], 
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4]]) 

# Plot array 
plt.imshow(example_array, cmap="spectral", interpolation='nearest') 

Example array with numbered regions

+0

Örnek çıktı sağlar mısınız? –

+0

Aşırı bir şekilde diziden geçmeden, ilk birkaç sonuçtan oluşan bir örnek, bu gibi bir şeye benzeyecektir (http://i.imgur.com/HE7YTmG.jpg?1). "bölge, bölgeye" ikinci "ve üçüncü" mesafe "sütununa. Belirli sonuçlar elbette mesafeleri hesaplamak için kullanılan algoritmaya bağlı olarak değişebilirdi, ama o top sahasında bir şey peşindeyim. –

cevap

2
aşağıdaki kodla hesaplanabilir bir resmin etiketli bölgeler arasında

Mesafeler,

import itertools 
from scipy.spatial.distance import cdist 

# making sure that IDs are integer 
example_array = np.asarray(example_array, dtype=np.int) 
# we assume that IDs start from 1, so we have n-1 unique IDs between 1 and n 
n = example_array.max() 

indexes = [] 
for k in range(1, n): 
    tmp = np.nonzero(example_array == k) 
    tmp = np.asarray(tmp).T 
    indexes.append(tmp) 

# calculating the distance matrix 
distance_matrix = np.zeros((n-1, n-1), dtype=np.float) 
for i, j in itertools.combinations(range(n-1), 2): 
    # use squared Euclidean distance (more efficient), and take the square root only of the single element we are interested in. 
    d2 = cdist(indexes[i], indexes[j], metric='sqeuclidean') 
    distance_matrix[i, j] = distance_matrix[j, i] = d2.min()**0.5 

# mapping the distance matrix to labeled IDs (could be improved/extended) 
labels_i, labels_j = np.meshgrid(range(1, n), range(1, n)) 
results = np.dstack((labels_i, labels_j, distance_matrix)).reshape((-1, 3)) 

print(distance_matrix) 
print(results) 

: Burada

benim giriş verilerini benzeyen örnek bir veri kümesi var Kimlikler ve eğer durum böyle değilse uzatılmalıdır. tam çıkış here bulunabilir ise, örneğin, yukarıda belirtilen test verileri ile, Mesafe ölçüsü matrisi,

# From 1    2   3   4    5   # To 
[[ 0.   4.12310563 4.   9.05538514 5.  ] # 1 
[ 4.12310563 0.   3.16227766 10.81665383 8.24621125] # 2 
[ 4.   3.16227766 0.   4.24264069 2.  ] # 3 
[ 9.05538514 10.81665383 4.24264069 0.   3.16227766] # 4 
[ 5.   8.24621125 2.   3.16227766 0.  ]] # 5 

olup. Bunun, her bir pikselin merkezinden Eucledian mesafesini aldığını unutmayın. Örneğin, 1 ve 3 bölgeleri arasındaki mesafe, 1 pikselle ayrılırken, 2.0'dır.

Bu, farklı bölgelerin pikselleri arasındaki tüm ikili uzaklıkları hesapladığımız bir kaba kuvvet yaklaşımıdır. Bu çoğu uygulama için yeterli olmalıdır. Yine de, daha iyi bir performansa ihtiyacınız varsa, scipy.spatial.cKDTree numaralı telefona bakın; bu, cdist ile karşılaştırıldığında, iki bölge arasındaki minimum mesafeyi hesaplamakta daha verimli olacaktır.

+1

Mükemmel cevap için teşekkürler. Kod, ID = 6 bölgesi için mesafelerin hesaplanmaması haricinde iyi çalışır ('range 'fonksiyonu son elemanı içermez; 1'den n = input_array.max()') eklenerek kolayca sabitlenebilir. Sahip olduğum tek sorun (muhtemelen sağladığım örnek dizinin bir hatası), gerçek veriler dizimde kimlik numaralandırmanın her zaman sıfırdan başlayamayacağı veya ardışık olabileceğidir: yani, 3 kimliğine sahip bir bölgeler kümesine sahip olabilirim. Aynı dizide 8, 22 ve 450. Bunu açıklamak için yukarıdakileri nasıl genelleştirebilirim? –

İlgili konular