utils.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import math
  2. import ee
  3. def radians(img):
  4. """Converts image from degrees to radians"""
  5. return img.toFloat().multiply(math.pi).divide(180)
  6. def hillshade(az, ze, slope, aspect):
  7. """Computes hillshade"""
  8. azimuth = radians(ee.Image.constant(az))
  9. zenith = radians(ee.Image.constant(90).subtract(ee.Image.constant(ze)))
  10. return azimuth \
  11. .subtract(aspect).cos().multiply(slope.sin()).multiply(zenith.sin()) \
  12. .add(zenith.cos().multiply(slope.cos()))
  13. def hillshadeRGB(image, elevation, weight=1, height_multiplier=5, azimuth=0, zenith=45,
  14. contrast=0, brightness=0, saturation=1, castShadows=False, customTerrain=False):
  15. """Styles RGB image using hillshading, mixes RGB and hillshade using HSV<->RGB transform"""
  16. hsv = image.visualize().unitScale(0, 255).rgbToHsv()
  17. z = elevation.multiply(ee.Image.constant(height_multiplier))
  18. terrain = ee.Algorithms.Terrain(z)
  19. slope = radians(terrain.select(['slope'])).resample('bicubic')
  20. aspect = radians(terrain.select(['aspect'])).resample('bicubic')
  21. if customTerrain:
  22. raise NotImplementedError('customTerrain argument is not implemented yet')
  23. hs = hillshade(azimuth, zenith, slope, aspect).resample('bicubic')
  24. if castShadows:
  25. hysteresis = True
  26. neighborhoodSize = 256
  27. hillShadow = ee.Algorithms.HillShadow(elevation, azimuth,
  28. ee.Number(90).subtract(zenith), neighborhoodSize, hysteresis).float()
  29. hillShadow = ee.Image(1).float().subtract(hillShadow)
  30. # opening
  31. # hillShadow = hillShadow.multiply(hillShadow.focal_min(3).focal_max(6))
  32. # cleaning
  33. hillShadow = hillShadow.focal_mode(3)
  34. # smoothing
  35. hillShadow = hillShadow.convolve(ee.Kernel.gaussian(5, 3))
  36. # transparent
  37. hillShadow = hillShadow.multiply(0.7)
  38. hs = hs.subtract(hillShadow).rename('shadow')
  39. intensity = hs.multiply(ee.Image.constant(weight)) \
  40. .add(hsv.select('value').multiply(ee.Image.constant(1)
  41. .subtract(weight)))
  42. sat = hsv.select('saturation').multiply(saturation)
  43. hue = hsv.select('hue')
  44. result = ee.Image.cat(hue, sat, intensity).hsvToRgb() \
  45. .multiply(ee.Image.constant(1).float().add(contrast)).add(ee.Image.constant(brightness).float())
  46. if customTerrain:
  47. mask = elevation.mask().focal_min(2)
  48. result = result.updateMask(mask)
  49. return result