1 सेल / पिक्सेल के बीज से एक रेखापुंज में कोशिकाओं के बेतरतीब ढंग से आकार के थक्के बनाना?


11

जैसा कि मेरा शीर्षक कहता है, मैं एक रैस्टर के भीतर बीजों से कोशिकाओं के समूह को "विकसित" करना चाहता हूं। मेरा आधार रेखापुंज 1 और 0, 1 के संकेत भूमि और 0 के समुद्र / NA क्षेत्रों से भरा है। 1 से मैं अपने बीज के रूप में 60 यादृच्छिक पिक्सल / कोशिकाओं का चयन करना चाहता हूं, और फिर बेतरतीब ढंग से एक पूर्व-परिभाषित नं के जुड़े हुए झुरमुट को विकसित करता हूं। पिक्सल / सेल की सीमा उस बीज से होती है। मैंने सुना है कि तकनीक को 'फैली हुई डाई' के रूप में संदर्भित किया जा सकता है, लेकिन इस पर बहुत कुछ पाने का कोई सौभाग्य नहीं है। बीज कोशिका को 2 के मान में बदल दिया जाएगा और फिर आसपास के 1 से चुनी गई अगली कोशिका को भी 2 में बदल दिया जाएगा। भविष्य में परिवर्तित होने के लिए 2 के अनुपलब्ध हैं।

यह धागा थोड़ी मदद करता है, क्योंकि मैं आर में भी ऐसा करने के लिए तैयार हूं क्योंकि मैं आरआईएस में जीआईएस डेटा को पढ़ने और हेरफेर करने से परिचित हूं। हालांकि, मुझे जो आवश्यकता है वह मौजूदा क्लंप के आसपास बेतरतीब ढंग से पिक्सेल का चयन करने के लिए नियमों का एक सेट है। ।

अगर किसी ने जीआईएस सेटिंग में सेलुलर ऑटोमेटा के इस अधिक मूल रूप को किया है तो मैं किसी भी सलाह / मार्गदर्शन की सराहना करूंगा।

उदाहरण:

मेरे पास 250 सेल का लक्ष्य है। मैं बेतरतीब ढंग से एक सेल का चयन करता हूं, जिसका मान 1. है। यह मान 2 में बदल गया है। फिर, बीज सेल के पड़ोसियों में से एक = 1 को 2 में बदल दिया जाता है। फिर, दोनों में से किसी एक सेल का पड़ोसी एक 2 मान के साथ चुना गया है और एक 2 में बदल गया है। यह तब तक जारी रहेगा जब तक कि एक निरंतर आकार की संख्या 250 कोशिकाओं तक नहीं पहुंच जाती।

संपादित करें: आगे के प्रश्न

व्हीबर के महान जवाब के आधार पर, मेरे पास कोड के बारे में कुछ प्रश्न हैं:

  1. मुझे कैसे प्राप्त कोशिकाओं के मूल्यों को चर मानों के बजाय सिर्फ एक '2' के लिए आवंटित किया जाता है जो उस क्रम का प्रतिनिधित्व करते हैं जिसमें वे बनाए गए थे?
  2. मुझे '1' के अपने क्षेत्र के भीतर 60 क्लंप्स सेल बनाने की आवश्यकता है। मैंने रैंडम स्टार्टिंग पोजिशन लेने के तरीके ईजाद किए हैं, लेकिन इसे expandफंक्शन के इस्तेमाल से पूरा करने के लिए संघर्ष करें । क्या आप 60 क्लंप बनाने का एक तरीका सुझा सकते हैं जो एक-दूसरे से नहीं टकराते हैं और एक ही अंतिम मैट्रिक्स में निहित होते हैं?

संपादित करें: समस्या का और स्पष्टीकरण

कोशिकाओं का प्रत्येक क्लंप एक परिभाषित आकार के संरक्षित क्षेत्र का प्रतिनिधित्व करेगा जैसे कि 250 सेल। प्रत्येक क्षेत्र को 1 के मूल्य पर कोशिकाओं में शुरू करने और बढ़ने की जरूरत है क्योंकि यह भूमि का प्रतिनिधित्व करता है और 0 के मान के साथ कोशिकाओं से बचता है, क्योंकि यह समुद्र का प्रतिनिधित्व करता है। मुझे एक शून्य मॉडल बनाने के लिए प्रत्येक पुनरावृत्ति में 60 संरक्षित क्षेत्रों के साथ इस 1000 बार पुनरावृत्ति करने की आवश्यकता है, यह दिखाते हुए कि इन क्षेत्रों का वितरण संयोग से क्या होगा। इस कारण से, सभी 60 क्षेत्रों में कोशिकाओं की कुल गिनती 1000 पुनरावृत्तियों में से प्रत्येक में समान होने की आवश्यकता होगी ताकि वे तुलनीय हों। इसलिए, यदि क्षेत्र स्पर्श करते हैं, तो यह ठीक है, लेकिन यदि कोई टक्कर होती है, तो आदर्श रूप से जब तक 250 का लक्ष्य पूरा नहीं हो जाता है तब तक एक और उपलब्ध दिशा में बढ़ेगा।

एक बार इन 1000 संरक्षित क्षेत्र नेटवर्कों के बन जाने के बाद, इनका उपयोग अन्य रिस्तेदार डेटा जैसे कि जैव विविधता उपायों के खिलाफ एक मुखौटा के रूप में किया जाएगा, (ए) यह देखने के लिए कि क्या वे विशेष प्रजातियों की सीमाओं को काटते हैं और (बी) किस विशेष प्रजाति के% में ये यादृच्छिक नेटवर्क होते हैं संरक्षित क्षेत्रों के कवर।

आपकी मदद के लिए अब तक @whuber की बदौलत, मुझे उम्मीद नहीं है कि आप मेरी मदद करने के लिए अधिक समय बिताएंगे, लेकिन मुझे लगा कि मैं अपनी स्थिति को स्पष्ट करने की कोशिश करूंगा और जैसा कि आपने अनुरोध किया है।


आर के अलावा, आप इस विश्लेषण के लिए किन अन्य प्रोग्रामिंग भाषाओं / सॉफ़्टवेयर का उपयोग करने में रुचि रखते हैं?
आरोन

मुझे आर्कगिस या क्यूजीआईएस का उपयोग करने में भी खुशी होगी। दुर्भाग्य से मैं अजगर से परिचित नहीं हूँ। बैश टर्मिनल के माध्यम से GDAL भी एक संभावना है।
जेपीडी

जवाबों:


12

मैं एक ऐसा Rसमाधान पेश करूँगा, जो Rयह बताने के लिए थोड़ा गैर- तरीके से कोडित हो कि यह अन्य प्लेटफार्मों पर कैसे संपर्क किया जा सकता है।

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

कोड टिप्पणी की है और पढ़ने के लिए सीधा होना चाहिए। एल्गोरिथ्म को यथासंभव पूरा करने के लिए, यह परिणाम को प्लॉट करने के लिए अंत को छोड़कर किसी भी ऐड-ऑन का उपयोग नहीं करता है। केवल मुश्किल हिस्सा यह है कि दक्षता और सादगी के लिए यह 1 डी इंडेक्स का उपयोग करके 2 डी ग्रिड में इंडेक्स करना पसंद करता है। रूपांतरण neighborsफ़ंक्शन में होता है , जिसे 2 डी इंडेक्सिंग की आवश्यकता होती है ताकि यह पता लगाया जा सके कि सेल के सुलभ पड़ोसी क्या हो सकते हैं और फिर उन्हें 1 डी इंडेक्स में परिवर्तित कर देता है। यह रूपांतरण मानक है, इसलिए मैं इस पर आगे टिप्पणी नहीं करूंगा, सिवाय इसके कि अन्य जीआईएस प्लेटफार्मों में आप कॉलम और पंक्ति इंडेक्स की भूमिकाओं को उलटना चाह सकते हैं। ( Rस्तंभ अनुक्रमणिका करने से पहले पंक्ति अनुक्रमणिका में परिवर्तन होता है।)

वर्णन करने के लिए, यह कोड xभूमि का प्रतिनिधित्व करने वाला ग्रिड और दुर्गम बिंदुओं की एक नदी जैसी सुविधा लेता है, उस ग्रिड में एक विशिष्ट स्थान (5, 21) पर शुरू होता है (नदी के निचले मोड़ के पास) और 250 बिंदुओं को कवर करने के लिए इसे यादृच्छिक रूप से विस्तारित करता है। । कुल समय 0.03 सेकंड है। (जब सरणी का आकार 10,000 से 3000 पंक्तियों के कारक 5000 स्तंभों से बढ़ा दिया जाता है, तो समय केवल 0.09 सेकंड तक चला जाता है - केवल 3 या तो का एक कारक - इस एल्गोरिथ्म की मापनीयता का प्रदर्शन।) इसके बजाय। बस 0, 1, और 2 के ग्रिड को आउटपुट करना, यह उस अनुक्रम को आउटपुट करता है जिसके साथ नई कोशिकाओं को आवंटित किया गया था। आंकड़े पर सबसे पहले कोशिकाएं हरे रंग की हैं, जो सुनारों के माध्यम से सामन रंगों में स्नातक हैं।

नक्शा

यह स्पष्ट होना चाहिए कि प्रत्येक कोशिका के आठ-बिंदु पड़ोस का उपयोग किया जा रहा है। अन्य पड़ोस के लिए, बस nbrhoodमूल्य को संशोधित करें expand: यह किसी भी दिए गए सेल के सापेक्ष सूचकांक ऑफसेट की एक सूची है। उदाहरण के लिए, "D4" पड़ोस को निर्दिष्ट किया जा सकता है matrix(c(-1,0, 1,0, 0,-1, 0,1), nrow=2)

यह भी स्पष्ट है कि फैलने के इस तरीके की अपनी समस्याएं हैं: यह पीछे छेद छोड़ देता है। यदि वह नहीं है जो इरादा था, तो इस समस्या को ठीक करने के विभिन्न तरीके हैं। उदाहरण के लिए, उपलब्ध कोशिकाओं को एक कतार में रखें ताकि सबसे पहले पाए जाने वाले सेल भी जल्द से जल्द भरे जाएं। कुछ रैंडमाइजेशन अभी भी लागू किया जा सकता है, लेकिन उपलब्ध कोशिकाओं को अब समान (समान) संभावनाओं के साथ नहीं चुना जाएगा। एक और, अधिक जटिल तरीका, संभावनाओं के साथ उपलब्ध कोशिकाओं का चयन करना होगा जो इस बात पर निर्भर करते हैं कि उनके पास कितने भरे हुए पड़ोसी हैं। एक बार एक सेल घेर लिया जाता है, तो आप इसके चयन की संभावना को इतना अधिक कर सकते हैं कि कुछ छेद अधूरा रह जाएगा।

मैं यह टिप्पणी करके समाप्त करूंगा कि यह काफी सेल्युलर ऑटोमेटन (सीए) नहीं है, जो सेल द्वारा सेल आगे नहीं बढ़ाएगा, बल्कि प्रत्येक पीढ़ी में कोशिकाओं के पूरे स्वेट को अपडेट करेगा। अंतर सूक्ष्म है: सीए के साथ, कोशिकाओं के लिए चयन संभावनाएं समान नहीं होंगी।

#
# Expand a patch randomly within indicator array `x` (1=unoccupied) by
# `n.size` cells beginning at index `start`.
#
expand <- function(x, n.size, start) {
  if (x[start] != 1) stop("Attempting to begin on an unoccupied cell")
  n.rows <- dim(x)[1]
  n.cols <- dim(x)[2]
  nbrhood <- matrix(c(-1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1), nrow=2)
  #
  # Adjoin one more random cell and update `state`, which records
  # (1) the immediately available cells and (2) already occupied cells.
  #
  grow <- function(state) {
    #
    # Find all available neighbors that lie within the extent of `x` and
    # are unoccupied.
    #
    neighbors <- function(i) {
      n <- c((i-1)%%n.rows+1, floor((i-1)/n.rows+1)) + nbrhood
      n <- n[, n[1,] >= 1 & n[2,] >= 1 & n[1,] <= n.rows & n[2,] <= n.cols, 
             drop=FALSE]             # Remain inside the extent of `x`.
      n <- n[1,] + (n[2,]-1)*n.rows  # Convert to *vector* indexes into `x`.
      n <- n[x[n]==1]                # Stick to valid cells in `x`.
      n <- setdiff(n, state$occupied)# Remove any occupied cells.
      return (n)
    }
    #
    # Select one available cell uniformly at random.
    # Return an updated state.
    #
    j <- ceiling(runif(1) * length(state$available))
    i <- state$available[j]
    return(list(index=i,
                available = union(state$available[-j], neighbors(i)),
                occupied = c(state$occupied, i)))
  }
  #
  # Initialize the state.
  # (If `start` is missing, choose a value at random.)
  #
  if(missing(start)) {
    indexes <- 1:(n.rows * n.cols)
    indexes <- indexes[x[indexes]==1]
    start <- sample(indexes, 1)
  }
  if(length(start)==2) start <- start[1] + (start[2]-1)*n.rows
  state <- list(available=start, occupied=c())
  #
  # Grow for as long as possible and as long as needed.
  #
  i <- 1
  indices <- c(NA, n.size)
  while(length(state$available) > 0 && i <= n.size) {
    state <- grow(state)
    indices[i] <- state$index
    i <- i+1
  }
  #
  # Return a grid of generation numbers from 1, 2, ... through n.size.
  #
  indices <- indices[!is.na(indices)]
  y <- matrix(NA, n.rows, n.cols)
  y[indices] <- 1:length(indices)
  return(y)
}
#
# Create an interesting grid `x`.
#
n.rows <- 3000
n.cols <- 5000
x <- matrix(1, n.rows, n.cols)
ij <- sapply(1:n.cols, function(i) 
      c(ceiling(n.rows * 0.5 * (1 + exp(-0.5*i/n.cols) * sin(8*i/n.cols))), i))
x[t(ij)] <- 0; x[t(ij - c(1,0))] <- 0; x[t(ij + c(1,0))] <- 0
#
# Expand around a specified location in a random but reproducible way.
#
set.seed(17)
system.time(y <- expand(x, 250, matrix(c(5, 21), 1)))
#
# Plot `y` over `x`.
#
library(raster)
plot(raster(x[n.rows:1,], xmx=n.cols, ymx=n.rows), col=c("#2020a0", "#f0f0f0"))
plot(raster(y[n.rows:1,] , xmx=n.cols, ymx=n.rows), 
     col=terrain.colors(255), alpha=.8, add=TRUE)

थोड़े संशोधनों के साथ हम expandकई क्लस्टर बनाने के लिए लूप कर सकते हैं। एक पहचानकर्ता द्वारा समूहों को अलग करना उचित है, जो यहां 2, 3, ... आदि चलाएगा।

पहले, एक त्रुटि और (बी) के बजाय एक मैट्रिक्स में मान होने पर पहली पंक्ति में expandवापसी (ए) NAमें बदलें । ( प्रत्येक कॉल के साथ एक नया मैट्रिक्स बनाने में समय बर्बाद न करें।) किए गए इस बदलाव के साथ, लूपिंग आसान है: एक यादृच्छिक शुरुआत चुनें, इसके चारों ओर विस्तार करने का प्रयास करें, यदि सफल रहे, तो क्लस्टर इंडेक्स को संचित करें और जब तक दोहराएं। लूप का एक महत्वपूर्ण हिस्सा कई पुनरावृत्तियों को प्राप्त नहीं होने की स्थिति में पुनरावृत्तियों की संख्या को सीमित करना है: इसके साथ ऐसा किया जाता है ।indicesyyindicescount.max

यहां एक उदाहरण दिया गया है जहां 60 क्लस्टर केंद्रों को समान रूप से यादृच्छिक पर चुना जाता है।

size.clusters <- 250
n.clusters <- 60
count.max <- 200
set.seed(17)
system.time({
  n <- n.rows * n.cols
  cells.left <- 1:n
  cells.left[x!=1] <- -1 # Indicates occupancy of cells
  i <- 0
  indices <- c()
  ids <- c()
  while(i < n.clusters && length(cells.left) >= size.clusters && count.max > 0) {
    count.max <- count.max-1
    xy <- sample(cells.left[cells.left > 0], 1)
    cluster <- expand(x, size.clusters, xy)
    if (!is.na(cluster[1]) && length(cluster)==size.clusters) {
      i <- i+1
      ids <- c(ids, rep(i, size.clusters))
      indices <- c(indices, cluster)
      cells.left[indices] <- -1
    }                
  }
  y <- matrix(NA, n.rows, n.cols)
  y[indices] <- ids
})
cat(paste(i, "cluster(s) created.", sep=" "))

यहां 500 ग्रिड द्वारा 310 पर लागू होने पर परिणाम (क्लस्टर्स के लिए पर्याप्त रूप से छोटा और मोटे होना) स्पष्ट है। इसे निष्पादित करने में दो सेकंड लगते हैं; 5000 ग्रिड (100 गुना बड़ा) पर 3100 से अधिक समय (24 सेकंड) लगता है, लेकिन समय काफी अच्छी तरह से बढ़ रहा है। (अन्य प्लेटफार्मों पर, जैसे कि C ++, समय को शायद ही ग्रिड आकार पर निर्भर होना चाहिए।)

60 कलस्टर


हाय व्हीबर। इसके लिए बहुत बहुत धन्यवाद, मैं वास्तव में इसकी सराहना करता हूं। मैं बस थोड़ा सा प्रयोग कर रहा हूं और जल्द ही कुछ फॉलोअप प्रश्नों के साथ वापस आ सकता हूं।
जेपीडी

+1 जीआईएस एसई पर कुछ अधिक जटिल सवालों के ऐसे गहन जवाब देने के लिए धन्यवाद।
रडार

@whuber। अपने उत्तर के आधार पर प्रश्न का थोड़ा विस्तार किया है। एक बार फिर धन्यवाद!
जेपीडी

1
# 1 का उत्तर तुच्छ है: पंक्ति को इसके y[indices] <- 1:length(indices)द्वारा प्रतिस्थापित करें y[indices] <- 2। # 2 का उत्तर लगभग सरल है: बस लूप।
whuber

@whuber। अपडेट के लिए फिर से धन्यवाद। अब क्लैम्प्स क्लैशिंग का मुद्दा है, और परिणामस्वरूप क्लैंप्स को परिभाषित संख्या से कम आकार देते हैं size.clusters। मैं यह कैसे सुनिश्चित कर सकता हूं कि एक क्लंप सही आकार तक बढ़ता है, जैसा कि, फिलहाल, मुझे लगता है कि यह मौजूदा क्लंप में बढ़ने की कोशिश करता है, विफल रहता है, लेकिन फिर भी एक सफल विस्तार के रूप में पंजीकृत करता है। मैं भी एक औसत अशक्त मॉडल शैली डाटासेट बनाने 1000 बार 60 clumps के उत्पादन में पुनरावृति करना चाहते हैं। क्या हर बार लूपिंग के भीतर रैंडम पोजिशन अलग-अलग होगी for?
जेपीडी

3

कभी भी अपना ऑपरेशन किए बिना, और खेलने के लिए अतिरिक्त समय नहीं, मैं केवल आपकी सूची में इन दो लिंक को जोड़ सकता हूं:

वेक्टर बिंदु के आधार पर निकटतम रेखापुंज सेल मान ज्ञात करें (पहला उत्तर (4 वोटों के साथ) जो मुझे साज़िश है)।

इसके अलावा: क्या हॉथ की ग्रिडस्प्रेड मदद करेगा?

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.