识别R栅格包中的重叠区域

Ben*_*min 8 r raster image-processing

包:

数据:

  • 一个有10个波段的rasterStack.
  • 每个带包含由NA围绕的图像区域
  • 频带是合乎逻辑的,即图像数据为"1",周围区域为"0"/ NA
  • 每个带的"图像区域"彼此不完全对齐,但大多数具有部分重叠

目的:

  • 编写一个快速函数,可以返回每个"区域"的rasterLayer或单元格编号,例如,仅包含来自第1和第2波段的数据的像素落在区域1中,包含仅来自第3和第4波段的数据的像素落在第2区域中如果返回了rasterLayer,我需要能够稍后将区域值与带编号进行匹配.

第一次尝试:

# Possible band combinations
values = integer(0)
for(i in 1:nlayers(myraster)){
 combs = combn(1:nlayers(myraster), i)
 for(j in 1:ncol(combs)){
  values = c(values, list(combs[,j]))
 }
}

# Define the zone finding function
find_zones = function(bands){

 # The intersection of the bands of interest
 a = subset(myraster, 1)
 values(a) = TRUE
 for(i in bands){
  a = a & myraster[[i]]
 }

 # Union of the remaining bands
 b = subset(myraster, 1)
 values(b) = FALSE
 for(i in seq(1:nlayers(myraster))[-bands]){
  b = b | myraster[[i]]
 }

 #plot(a & !b)
 cells = Which(a & !b, cells=TRUE)
 return(cells)
}

# Applying the function
results = lapply(values, find_zones)
Run Code Online (Sandbox Code Playgroud)

我当前的函数需要很长时间才能执行.你能想到一个更好的方法吗?请注意,我不只是想知道每个像素有多少个带有数据,我还需要知道哪个带.这样做的目的是之后以不同的方式处理不同的区域.

另请注意,现实场景是3000 x 3000或更多的栅格,可能超过10个频段.


编辑

一些样本数据由10个偏移图像区域组成:

# Sample data
library(raster)    
for(i in 1:10) {
  start_line = i*10*1000
  end_line = 1000000 - 800*1000 - start_line
  offset = i * 10
  data = c(rep(0,start_line), rep(c(rep(0,offset), rep(1,800), rep(0,200-offset)), 800), rep(0, end_line))
  current_layer = raster(nrows=1000, ncols=1000)
  values(current_layer) = data
  if(i == 1) {
    myraster = stack(current_layer)
  } else {
    myraster = addLayer(myraster, current_layer)
  }
}
NAvalue(myraster) = 0  # You may not want to do this depending on your solution...
Run Code Online (Sandbox Code Playgroud)

显示示例数据的样子

Jor*_*eys 6

编辑:使用尼克的技巧和矩阵乘法更新答案.


您可以尝试以下功能,使用Nick的技巧和矩阵乘法进行优化.现在的瓶颈是填充堆叠的单独层,但我想时间现在已经很好了.内存使用量稍微少一些,但考虑到你的数据和R的性质,我不知道你是否能在不妨碍性能大的时候蚕食一下.

> system.time(T1 <- FindBands(myraster,return.stack=T))
   user  system elapsed 
   6.32    2.17    8.48 
> system.time(T2 <- FindBands(myraster,return.stack=F))
   user  system elapsed 
   1.58    0.02    1.59 
> system.time(results <- lapply(values, find_zones))
  Timing stopped at: 182.27 35.13 217.71
Run Code Online (Sandbox Code Playgroud)

该函数返回一个rasterStack,其中包含绘图中存在的不同级别组合(这不是所有可能的级别组合,因此您已经获得了一些增益),或者具有级别编号和级别名称的矩阵.这允许您执行以下操作:

levelnames <- attr(T2,"levels")[T2]
Run Code Online (Sandbox Code Playgroud)

获取每个单元格点的级别名称.如下所示,您可以轻松地将该矩阵放在rasterLayer对象中.

功能 :

 FindBands <- function(x,return.stack=F){
    dims <- dim(x)
    Values <- getValues(x)
    nn <- colnames(Values)

    vec <- 2^((1:dims[3])-1)
    #Get all combinations and the names
    id <- unlist(
                lapply(1:10,function(x) combn(1:10,x,simplify=F))
              ,recursive=F)

    nameid <- sapply(id,function(i){
      x <- sum(vec[i])
      names(x) <- paste(i,collapse="-")
      x
    })
    # Nicks approach
    layers <- Values %*% vec
    # Find out which levels we need
    LayerLevels <- unique(sort(layers))
    LayerNames <- c("No Layer",names(nameid[nameid %in% LayerLevels]))

    if(return.stack){
        myStack <- lapply(LayerLevels,function(i){
          r <- raster(nr=dims[1],nc=dims[2])
          r[] <- as.numeric(layers == i)
          r
          } )
        myStack <- stack(myStack)
        layerNames(myStack) <- LayerNames
        return(myStack)

    } else {

      LayerNumber <- match(layers,LayerLevels)
      LayerNumber <- matrix(LayerNumber,ncol=dims[2],byrow=T)
      attr(LayerNumber,"levels") <- LayerNames
      return(LayerNumber)
    }    
}
Run Code Online (Sandbox Code Playgroud)

使用RobertH的数据进行概念验证:

r <- raster(nr=10, nc=10)
r[]=0
r[c(20:60,90:93)] <- 1
s <- list(r)
r[]=0
r[c(40:70,93:98)] <- 1
s <- c(s, r)
r[]=0
r[50:95] <- 1
s <- (c(s, r))
aRaster <- stack(s)


> X <- FindBands(aRaster,return.stack=T)
> plot(X)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

> X <- FindBands(aRaster,return.stack=F)
> X
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    1    1    1    1    1    1    1    1    1     1
 [2,]    1    1    1    1    1    1    1    1    1     2
 [3,]    2    2    2    2    2    2    2    2    2     2
 [4,]    2    2    2    2    2    2    2    2    2     4
 [5,]    4    4    4    4    4    4    4    4    4     8
 [6,]    8    8    8    8    8    8    8    8    8     8
 [7,]    7    7    7    7    7    7    7    7    7     7
 [8,]    5    5    5    5    5    5    5    5    5     5
 [9,]    5    5    5    5    5    5    5    5    5     6
[10,]    6    6    8    7    7    3    3    3    1     1
attr(,"levels")
[1] "No Layer" "1"        "2"        "3"        "1-2"      "1-3"
       "2-3"      "1-2-3"   

> XX <- raster(ncol=10,nrow=10)
> XX[] <- X
> plot(XX)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述