[R-sig-Geo] groupping contiguous identical raster cells
Babak Naimi
naimi at itc.nl
Wed Mar 28 14:34:59 CEST 2012
Dear Robert and list,
I wrote a function, named 'group', to find the spatially contiguous groups of identical valued pixels in a raster layer and assign them unique integer identifiers (same as the GROUP function in Idrisi). I used the Rasterlayer object in the function to get and set values in the grouping procedure. Unfortunately the procedure is not efficient. When I converted the raster into matrix (in 'group2' function), the efficiency is incredibly improved but I think it still has problem with bigger rasters. It is not also a memory-safe function!
I was wondering if anyone can help to modify the function and enhance the efficiency. Following I show the results of some experiments on these functions (the source of the functions is attached at the end).
r1 <- c(rep(1,100),rep(2,100),sample(c(3,4),200,replace=T))
r1 <- raster(matrix(r1,nc=20,nr=20,byrow=T))
system.time(
g1 <- group(r1)
)
user system elapsed
2.56 0.00 2.59
system.time(
g2 <- group2(r1)
)
user system elapsed
0.06 0.00 0.06
# bigger raster:
r2 <- c(rep(1,10000),rep(2,10000),sample(c(3,4),20000,replace=T))
r2 <- raster(matrix(r2,nc=200,nr=200,byrow=T))
system.time(
g3 <- group(r2)
)
user system elapsed
1488.39 3.54 1547.00
system.time(
g4 <- group2(r2)
)
user system elapsed
230.47 0.52 237.54
#--------------------
# The source of functions:
cellNeighbors<-function(cell,nr,nc,type="queen") {
row <- trunc((cell-1)/nc) + 1
col <- cell - ((row-1) * nc)
if (type == "rook") {
r <- c(-1,0,1,0)
c <- c(0,1,0,-1)
} else {
r <- c(-1,-1,-1,0,1,1,1,0)
c <- c(-1,0,1,1,1,0,-1,-1)
}
row <- row - r
col <- col - c
row[row < 1 | row > nr] <- NA
col[col < 1 | col > nc] <- NA
rc <- cbind(row, col)
v <- (rc[,1]-1) * nc + rc[,2]
w <- which(is.na(v))
if (length(w) > 0) v <- v[-w]
v
}
#---------
group <- function(x,type="queen") {
g <- raster(x)
nc <- x at ncols
nr <- x at nrows
cells <- 1:ncell(x)
w <- which(is.na(x[cells]))
if (length(w) > 0) cells <- cells[-w]
groupID <- 0
Neigh.cells <- c()
while (length(cells) > 0) {
groupID <- groupID + 1
cell <- cells[1]
g[cell] <- groupID
cells <- cells[-1]
cell.n <- cellNeighbors(cell,nr,nc,type=type)
w <- which(x[cell.n] == x[cell])
if (length(w) > 0) Neigh.cells <- c(Neigh.cells,cell.n[w])
while (length(Neigh.cells) > 0) {
cell <- Neigh.cells[1]
Neigh.cells <- Neigh.cells[-1]
w <- which(cells == cell)
if (length(w) > 0) {
cells <- cells[-w]
g[cell] <- groupID
cell.n <- cellNeighbors(cell,nr,nc,type=type)
ww <- which(x[cell.n] == x[cell])
if (length(ww) > 0) Neigh.cells <- c(Neigh.cells,cell.n[ww])
}
}
}
g
}
#--------
group2 <- function(x,type="queen") {
gr <- raster(x)
nc <- x at ncols
nr <- x at nrows
cells <- 1:ncell(x)
x <- t(as.matrix(x))
g <- x
g[] <- NA
w <- which(is.na(x[cells]))
if (length(w) > 0) cells <- cells[-w]
groupID <- 0
Neigh.cells <- c()
while (length(cells) > 0) {
groupID <- groupID + 1
cell <- cells[1]
g[cell] <- groupID
cells <- cells[-1]
cell.n <- cellNeighbors(cell,nr,nc,type=type)
w <- which(x[cell.n] == x[cell])
if (length(w) > 0) Neigh.cells <- c(Neigh.cells,cell.n[w])
while (length(Neigh.cells) > 0) {
cell <- Neigh.cells[1]
Neigh.cells <- Neigh.cells[-1]
w <- which(cells == cell)
if (length(w) > 0) {
cells <- cells[-w]
g[cell] <- groupID
cell.n <- cellNeighbors(cell,nr,nc,type=type)
ww <- which(x[cell.n] == x[cell])
if (length(ww) > 0) Neigh.cells <- c(Neigh.cells,cell.n[ww])
}
}
}
gr[] <- t(g)
gr
}
#---------------------
Best regards,
Babak
Babak Naimi
PhD Candidate, Natural Resources Department,
Faculty of Geo-Information Science and Earth Observations (ITC), University of Twente,
P.O. Box 217, 7500 AE Enschede, The Netherlands
Tel: +31 53 4874212
More information about the R-sig-Geo
mailing list