0

I have a classified image with three categories (specific grass species: 1, ground: 2, other vegetation: 3). I am trying to calculate the area of each category. For the classification process I used the superClass RStoolbox method. For the calculating area method, I am using another code in a similar question, but am having some trouble with my image being in a superClass format type. I tried exporting and importing the file as a new raster and ended up getting a different error. Any suggestions?

img <- brick("C:/Users/name/location/Blung/null.tif")
shp <- st_read("C:/Users/name/location/Blung/Training.shp")
shpS4 <- as_Spatial(shp)

NDVI.Overlay <- function(b1, b4) {
  NDVI.Calc <- (b4 - b1) / (b4 + b4)
  return(NDVI.Calc)
}

NDVI <- overlay(img[[1]], img[[4]], fun = NDVI.Overlay)

img_update <- addLayer(img, NDVI)
names(img_update) <- c('b1', 'b2', 'b3', 'b4', 'NDVI')

SC <- superClass(img, trainData = shpS4, responseCol = "id", model = "rf", tuneLength = 1, trainPartition = 0.8)

SC[] = sample(1:3, ncell(SC), replace=TRUE)
counts <- tapply(area(SC), SC[], sum)

Error in (function (classes, fdef, mtable)  : 
  unable to find an inherited method for function ‘area’ for signature ‘"superClass"’
writeRaster(SC$map, filename = "C:/Users/name/location/Blung_classification_R.tif")
img_processing <- raster("C:/Users/name/location/Blung/Blung_classification_R.tif")

img_processing[] = sample(1:3, ncell(img_processing), replace=TRUE)
counts <- tapply(area(img_processing), img_processing[], sum)

Error in res[i] <- readBin(x@file@con, what = dtype, n = 1, size = dsize,  : 
  replacement has length zero
In addition: Warning messages:
1: In .local(x, ...) :
  This function is only useful for Raster* objects with a longitude/latitude coordinates
2: In .rasterFromRasterFile(grdfile, band = band, objecttype, ...) :
  size of values file does not match the number of cells (given the data type)

1 Answer 1

1

You are overwriting the elements in your list in using SC[] <- .... Look at the result of your list object before and after applying that specific line of code.

Let' recreate a semblance of your model.

library(RStoolbox)
library(raster)

data(rlogo)
train <- readRDS(system.file("external/trainingPoints.rds", 
                 package="RStoolbox"))
SC <- superClass(rlogo, trainData = train, responseCol = "class", 
                 model = "rf", tuneLength = 1, 
                 trainPartition = 0.7)

Now, we simply can extract the prediction to a separate object or you can use a double bracket index SC[["map"]] and not create a new object.

pred <- SC[["map"]]

Is your data in a geographic (lat/long) coordinate projection? The raster::area function is intended to return area in a decimal degree geographic projection, which is honestly not good practice for remote sensing analysis. Besides, the function needs an index to know what cells to look at and not an overall count of cells.

If you are working in a projected coordinate system then simply returning the class counts lets you get to area, based on the known cell resolution. This can be done easily by passing a vector of the predicted raster to table and applying the a cell resolution scaling factor, say 30m^2.

table(pred[])*(30^2) # or
raster::freq(pred)*(30^2)

I am curious as to the point of creating a random sample of 1:3 matching the number of cells in the raster.

You are creating a random sample containing the values of [1,2,3].

rs <- sample(1:3, 100, replace=TRUE)

Now, lets create a vector (p) that we would consider the prediction. And get the counts in relation to the random sample.

p <- sample(1:3, 100, replace=TRUE)
  tapply(p, rs, length)

Now, compare those to the actual counts (note; the second line is a brute force approach to verify the tapply results). The random sample aggregation results do not seem to match the actual counts.

tapply(p, p, length)
  length(p[p == 1])
6
  • Sorry, but I am not fully following what you are doing with the creating a random sample, but when I ran the table(pred[]*(res^2) I am having an Error: ` cannot allocate vector of size 5.5 Gb`. I think I need to take equal interval samples, run that for each one and then merge them back together??
    – Binx
    Commented Apr 27, 2020 at 22:53
  • I am also using a projected coordinate system.
    – Binx
    Commented Apr 27, 2020 at 22:53
  • You do not have enough memory to read in a vector of the classified raster. This was going to be an issue with your code as well. I will post a workaround in a bit. My point with the random sample is to demonstrate that what you are attempting with SC[] = sample(1:3, ncell(SC), replace=TRUE) makes no sense and will yield incorrect results. Commented Apr 27, 2020 at 23:18
  • Gotcha, I will remove that part of the code. But yes, I am also working on the memory problem as well!
    – Binx
    Commented Apr 27, 2020 at 23:21
  • Have you tried raster::freq(SC[["map"]]) to return class-level cell counts? It is a raster package function but, I do not recall if it is memory safe. Commented Apr 27, 2020 at 23:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.