This is my third post in this series, here are the links to the Part 1 and Part 2. Sorry for the delay, but at that time I got completely consumed with my PhD thesis and this story just went out of my mind.
To the point. There were 2 types of shadows I had to deal with: cloud shadows and cast shadows (from building and trees). In scientific literature you can find several relatively complicated algorithms to deal with them (including DEM usage for cast shadow detection) and I definitely should have used some of them, but… I was too lazy to implement them when there were couple of quick’n’dirty workarounds available.
Cloud shadow removal
To remove cloud shadows I decided to calculate ratio between mean pixel value of the lighted up and shadowed parts of the raster for each band and multiply shadowed pixels by this ratio. I manually created a mask for shadowed areas. There were 3 areas and their borders were quite distinct in NIR channels:
|Cloud shadows in one of the NIR bands|
I drew several polygons over shadows in QGIS and converted them to raster (Raster -> Conversion -> Rasterise). Now everything was ready for patching:
library(raster) library(rgdal) # load rasters image <- stack('2013_IEEE_GRSS_DF_Contest_CASI.tif') # hyper spectral imagery s_mask <- raster('shadow_mask.tif') # mask for cloud shadow # extract shadowed area m_cloud <- s_mask m_cloud[m_cloud < 1] <- NA shadowed <- mask(image, m_cloud) # calculate zonal statistics zd <- zonal(image, s_mask, fun = 'mean', na.rm = T) zd <- as.data.frame(zd) # calculate ratio between lighted up and shadowed zones zd[3,] <- zd[1,] / zd[2,] # recalculae data in shadows multiplyer <- zd[3,] multiplyer <- multiplyer[,2:ncol(zd)] multiplyer <- as.numeric(multiplyer) enlight <- shadowed*multiplyer # patch layer restored <- cover(enlight, image, progress = 'text') # save result wr <- writeRaster(restored, filename = 'restored.tif', datatype = 'GTiff', overwrite = TRUE)
Now it's time to check out results:
|The same NIR band after cloud shadow removal|
Yes, we can easily find patched areas, but overall result is good for such simple approach.
Cast shadow removal
Shadows from buildings can be processed the same way as cloud shadows as shown above except mask creation approach is different. In case of cast shadows they have to be detected automatically (for there are a bit more than 3 as in case with clouds). Using one of the NIR bands I created a learning sample of points and passed it to Random Forest algorithm to classify imagery into shadowed and non-shadowed areas. I will not describe here this classification process for Random Forest was used for overall classification of the imagery and it is the subject of my next post of this series.