You are calling with single brackets, use double. Raster stack is a kind of list:
Reproducible example (different sensor, same procedure)
library(raster)
library(RStoolbox)
data(lsat)
output_name <- paste0('raster',1:10,'.tif')
stack_b4 <-list()
stack_b8 <-list()
for(i in 1:10){
stack_b4[[i]] <- lsat[[3]]
stack_b8[[i]] <- lsat[[4]]
}
stack_b4 <- stack(stack_b4)
stack_b8 <- stack(stack_b8)
AOI_Repro <- as(extent(lsat,50,150,50,150),'SpatialPolygons')
For your procedure:
for (i in 1:length(stack_b4)) {
b4_crop <- crop(stack_b4[[i]],AOI_Repro)
b8_crop <- crop(stack_b8[[i]],AOI_Repro)
ndvi <- (b4_crop-b8_crop)/(b4_crop-b8_crop)
writeRaster(ndvi,output_name[i])
}
A better approach (IMO):
for (i in 1:length(stack_b4)) {
b4_crop <- crop(stack_b4[[i]],AOI_Repro)
b8_crop <- crop(stack_b8[[i]],AOI_Repro)
ndvi <- overlay(x = b4_crop, y = b8_crop, fun = function(x,y) (y-x)/(y+x))
writeRaster(ndvi,output_name[i])
}
A faster approach:
NDVI <- function(x,y){(y-x)/(y+x)}
beginCluster(12) # your availables cores
for (i in 1:length(stack_b4)) {
b4_crop <- crop(stack_b4[[i]],AOI_Repro)
b8_crop <- crop(stack_b8[[i]],AOI_Repro)
ndvi <- clusterR(stack(b4_crop,b8_crop), calc, args = list(fun = NDVI))
writeRaster(ndvi,output_name[i])
}
endCluster()
Less lines:
stack_b4c <- crop(stack_b4, AOI_Repro)
stack_b8c <- crop(stack_b8, AOI_Repro)
mapply(FUN = function(x,filename) writeRaster(x, filename),x = mapply(function(x,y) (y-x)/(y+x), as.list(stack_b4c), as.list(stack_b8c)), filename=as.list(output_name))