TransWikia.com

PyQGIS: GDAL hillshade patchwork effect

Geographic Information Systems Asked by wotnot on September 10, 2020

I have used QGIS to batch import and visualise tiled elevation data. This is illuminated greyscale, with identical parameters used each time, so I would have expected the result to be seamless and the tile boundaries to be essentially invisible.

However, the result is a ‘patchwork quilt’ effect. The shading is not consistent from one tile to the next. I do not understand why not. This is the code used to apply the hillshading:

  def ShadeRaster(raster, pth):

    import processing   

    parameters = {'INPUT': "", 
      'BAND': 1, 
      'COMPUTE_EDGES': False,
      'ZEVENBERGEN': False,
      'Z_FACTOR': 1.0,
      'SCALE': 1.0,
      'AZIMUTH': 315,
      'COMBINED': False,
      'ALTITUDE': 45,
      'MULTIDIRECTIONAL': False,
      'OUTPUT': ""}

    parameters['INPUT'] =raster.name()
    parameters['OUTPUT'] = pth + '/' + raster.name() + '.tif'

    processing.runAndLoadResults('gdal:hillshade',parameters,feedback=feedback)
    return QgsProject.instance().mapLayersByName('Hillshade')[0]

As you can see, the elevation and azimuth of the light source are always the same. But this is how it looks:

enter image description here

Why?

One Answer

OK... Got it. I changed approach a little bit, having realised that I don't have to run the Hillshade algorithm and generate a TIFF. I can just apply hillshade rendering to the memory raster layer.

I have now got a three stage process (repeated for each grid tile):

  1. Create raster layer from xyz ASCII file
  2. Set contrast enhancement to 'none'
  3. Set render to 'hillshade'

Stages 2 and 3 can actually be done via the QGIS GUI quite easily and applied to multiple layers, but I have done it programmatically.

def ImportRaster(self, raster):

  from PyQt5.QtCore import QFileInfo

  fileInfo = QFileInfo(raster)
  path = fileInfo.filePath()
  baseName = fileInfo.baseName()

  layer = QgsRasterLayer(path, baseName)
  QgsProject.instance().addMapLayer(layer)

  return layer if layer.isValid() else None

def setNoEnhancement(self, layer): # set contrast enhancement to 'no enhancement'
  ContrastEnhancement = QgsContrastEnhancement.NoEnhancement
  myBand = layer.renderer().grayBand()
  myType = layer.renderer().dataType(myBand)
  myEnhancement = QgsContrastEnhancement(myType)
  myEnhancement.setContrastEnhancementAlgorithm(ContrastEnhancement, True)
  layer.renderer().setContrastEnhancement(myEnhancement)

def setRenderHillshade(self, layer): # set render type to 'hillshade'
  r = QgsHillshadeRenderer(layer.dataProvider(), 1, 315, 45)
  layer.setRenderer(r)

def XYZToShadedTIFF(self, fname):

  l = self.ImportRaster(fname) # import file, return layer 'l'

  if not l is None:
    self.setNoEnhancement(l) # ContrastEnhancement to 'none'
    self.setRenderHillshade(l) # hillshade

This works.

Thanks Michael for the assistance.

Answered by wotnot on September 10, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP