2015-06-16 10 views
9

मेरे पास अद्वितीय आईडी पैच/क्षेत्रों के सेट के साथ एक रास्टर है जिसे मैंने दो-आयामी पायथन numpy सरणी में परिवर्तित कर दिया है। मैं प्रत्येक रास्टर पैच के निकटतम किनारों को अलग करने वाली न्यूनतम दूरी प्राप्त करने के लिए सभी क्षेत्रों के बीच युग्मित यूक्लिडियन दूरी की गणना करना चाहता हूं। चूंकि सरणी मूल रूप से एक रास्टर था, एक समाधान को कोशिकाओं में विकर्ण दूरी के लिए खाते की आवश्यकता होती है (मैं हमेशा रास्टर रिज़ॉल्यूशन द्वारा गुणा करके कोशिकाओं में मापा गया दूरी को मीटर में बदल सकता हूं)।अद्वितीय पायथन सरणी क्षेत्रों के बीच दूरी की गणना?

मैं के रूप में this answer to a related question में सुझाव दिया scipy.spatial.distance से cdist समारोह के साथ प्रयोग किया गया है, लेकिन अब तक मैं उपलब्ध प्रलेखन का उपयोग कर मेरी समस्या का समाधान नहीं कर पाए थे। अंत परिणाम के रूप में, मेरे पास आदर्श रूप से क्षेत्रों के सभी संभावित संयोजनों के बीच दूरी सहित "आईडी से आईडी, दूरी" के रूप में एक्स द्वारा 3 सरणी होगी।

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

क्या आप नमूना आउटपुट प्रदान कर सकते हैं? –

+0

पूरी तरह से ऊपर सरणी के माध्यम से जाने के बिना, पहले कुछ परिणामों का एक नमूना आदर्श रूप से [इस तरह कुछ] देखेंगे (http://i.imgur.com/HE7YTmG.jpg?1), पहले स्तंभ के साथ " "क्षेत्र, दूसरा" टू "क्षेत्र, और तीसरा" दूरी "कॉलम। विशिष्ट परिणाम निश्चित रूप से दूरी की गणना करने के लिए उपयोग किए गए एल्गोरिदम के आधार पर भिन्न हो सकते हैं, लेकिन उस ballpark में कुछ है जो मैं बाद में हूं। –

उत्तर

2
एक छवि निम्न कोड के साथ गणना की जा सकती की लेबल क्षेत्रों के बीच

दूरियां,

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) 

यह पूर्णांक मान लिया गया है:

यहाँ मेरी इनपुट डेटा जैसी एक नमूना डेटासेट है आईडी, और अगर यह मामला नहीं है तो विस्तारित करने की आवश्यकता होगी। उदाहरण के लिए, ऊपर परीक्षण डाटा के साथ, गणना की दूरी मैट्रिक्स, है

# 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 

जबकि पूर्ण उत्पादन here पाया जा सकता है। ध्यान दें कि यह प्रत्येक पिक्सेल के केंद्र से यूक्लेडियन दूरी लेता है। उदाहरण के लिए, जोन 1 और 3 के बीच की दूरी 2.0 है, जबकि वे 1 पिक्सेल से अलग हैं।

यह एक क्रूर-बल दृष्टिकोण है, जहां हम विभिन्न क्षेत्रों के पिक्सेल के बीच सभी जोड़ी दूरी की गणना करते हैं। यह ज्यादातर अनुप्रयोगों के लिए पर्याप्त होना चाहिए। फिर भी, यदि आपको बेहतर प्रदर्शन की आवश्यकता है, तो scipy.spatial.cKDTree पर एक नज़र डालें जो cdist की तुलना में दो क्षेत्रों के बीच न्यूनतम दूरी की गणना करने में अधिक कुशल होगा।

+1

उत्कृष्ट उत्तर के लिए धन्यवाद। आईडी अच्छी तरह से काम करता है, आईडी = 6 क्षेत्र के लिए दूरी की गणना नहीं करने के अलावा ('श्रेणी' फ़ंक्शन में अंतिम तत्व शामिल नहीं है; आसानी से 1 से' n = input_array.max() ') जोड़कर ठीक किया जा सकता है। मेरे पास एकमात्र मुद्दा है (संभवतः मेरे द्वारा प्रदान किए गए उदाहरण सरणी की गलती) यह है कि मेरे वास्तविक डेटा सरणी में आईडी नंबरिंग हमेशा शून्य से शुरू नहीं हो सकती है या लगातार हो सकती है: यानी मेरे पास 3 की आईडी वाले क्षेत्रों का एक सेट हो सकता है , एक ही सरणी में 8, 22 और 450। इसके लिए उपर्युक्त खाते को मैं कैसे सामान्यीकृत कर सकता हूं? –

संबंधित मुद्दे