shindig
shindig

Reputation: 355

Segment raster image with pixel values and population size

I usually use ENVI to do this process, however I am trying to move towards keeping everything within R to script more of my raster processing.

Within ENVI, the tool I use is called "Segmentation Image." The parameters include pixel thresholds, a population minimum, and number of neighbors considered. It works by first finding all pixels that meet the defined thresholds then grouping those pixels together if they collectively meet the population size.

Is there a way to pull this off within R? It seems like a relatively simple analysis, but I can't seem to find a function that will do it.

Thanks you!

Upvotes: 1

Views: 424

Answers (2)

shindig
shindig

Reputation: 355

Using Robert's example above, this is the code that I ended up with to accomplish my task.

# set parameters
min_val <- 0.5
min_pop <- 9
neighbors <- 8

# reclassify all cells
# values between -1 and min_val become 0
# values between min_val and 1 become 1
r <- ndvi
r[r > min_val] <- 1
r[r <= min_val] <- 0

# clump together cells
rc <- clump(r, directions = neighbors, gaps = TRUE)

# get patch size and select those larger than min_pop
f <- freq(rc)
ff <- f[f[,2] >= min_pop, 1]
ff <- ff[!is.na(ff)]

# select those larger than 10
msk <- subs(rc, data.frame(ff, 1))

# mask original NDVI raster
z <- mask(ndvi, msk)

# make result binary
z[z > 0] <- 1
z[is.na(z)] <- 0}

Upvotes: 0

Robert Hijmans
Robert Hijmans

Reputation: 47536

Example data

library(raster)
vi <- raster(ncols=20, nrows=20, xmn=0, xmx=1, ymn=0, ymx=1)
set.seed(101)
values(vi) <- runif(ncell(vi)) * .9

Reclassify

m <- c(-1, 0.5, 0, 
        0.5, 1, 1)
r <- reclassify(vi, m)

Find patches (here only Rook-case patches)

rc <- clump(r, directions=4) 
#plot(rc)

Get patch size and select those larger than 10

f <- freq(rc)
ff <- f[f[,2]>10, 1]
ff <- ff[!is.na(ff)]

Select the patches larger than 10

msk <- subs(rc, data.frame(ff, 1))

And use that to select the grid cells in the original raster

z <- mask(vi, msk)

Upvotes: 1

Related Questions