5. Usando Camadas Raster

Dica

Os trechos de código desta página precisam das seguintes importações se você estiver fora do console do pyqgis:

 1from qgis.core import (
 2    QgsRasterLayer,
 3    QgsProject,
 4    QgsPointXY,
 5    QgsRaster,
 6    QgsRasterShader,
 7    QgsColorRampShader,
 8    QgsSingleBandPseudoColorRenderer,
 9    QgsSingleBandColorDataRenderer,
10    QgsSingleBandGrayRenderer,
11)
12
13from qgis.PyQt.QtGui import (
14    QColor,
15)

5.1. Detalhes da Camada

Uma camada raster consiste em uma ou mais bandas raster - conhecidas como rasters de banda única e multibanda. Uma banda representa uma matriz de valores. Uma imagem colorida (por exemplo, foto aérea) é um raster composto por faixas vermelhas, azuis e verdes. Rasters de banda única normalmente representam variáveis ​​contínuas (por exemplo, elevação) ou variáveis ​​discretas (por exemplo, uso do solo). Em alguns casos, uma camada raster vem com uma paleta e os valores raster referem-se às cores armazenadas na paleta.

O código a seguir assume que o objeto rlayer é uma QgsRasterLayer.

rlayer = QgsProject.instance().mapLayersByName('srtm')[0]
# get the resolution of the raster in layer unit
print(rlayer.width(), rlayer.height())
919 619
# get the extent of the layer as QgsRectangle
print(rlayer.extent())
<QgsRectangle: 20.06856808199999875 -34.27001076999999896, 20.83945284300000012 -33.75077500700000144>
# get the extent of the layer as Strings
print(rlayer.extent().toString())
20.0685680819999988,-34.2700107699999990 : 20.8394528430000001,-33.7507750070000014
# get the raster type: 0 = GrayOrUndefined (single band), 1 = Palette (single band), 2 = Multiband
print(rlayer.rasterType())
0
 # get the total band count of the raster
print(rlayer.bandCount())
1
# get the first band name of the raster
print(rlayer.bandName(1))
Band 1: Height
# get all the available metadata as a QgsLayerMetadata object
print(rlayer.metadata())
<qgis._core.QgsLayerMetadata object at 0x13711d558>

5.2. Renderizador

Quando uma camada raster é carregada, ela obtém um renderizador padrão com base em seu tipo. Pode ser alterado nas propriedades da camada ou usando programação.

Para consultar o renderizador atual:

print(rlayer.renderer())
<qgis._core.QgsSingleBandGrayRenderer object at 0x7f471c1da8a0>
print(rlayer.renderer().type())
singlebandgray

To set a renderer, use the setRenderer() method of QgsRasterLayer. There are a number of renderer classes (derived from QgsRasterRenderer):

As camadas raster de banda única podem ser desenhadas nas cores cinza (valores baixos = preto, valores altos = branco) ou com um algoritmo de pseudo-cor que atribui cores aos valores. Rasters de banda única com uma paleta também podem ser desenhados usando a paleta. Camadas de multibandas geralmente são desenhadas mapeando as bandas para cores RGB. Outra possibilidade é usar apenas uma banda para desenhar.

5.2.1. Rasters com Banda Única

Digamos que queremos uma camada raster de renderização de banda única com cores que variam de verde a amarelo (correspondendo a valores de pixel de 0 a 255). No primeiro estágio, prepararemos um objeto QgsRasterShader e configuraremos sua função de sombreamento:

1fcn = QgsColorRampShader()
2fcn.setColorRampType(QgsColorRampShader.Interpolated)
3lst = [ QgsColorRampShader.ColorRampItem(0, QColor(0,255,0)),
4      QgsColorRampShader.ColorRampItem(255, QColor(255,255,0)) ]
5fcn.setColorRampItemList(lst)
6shader = QgsRasterShader()
7shader.setRasterShaderFunction(fcn)

Os sombreador mapeia as cores conforme especificado pelo seu mapa de cores. O mapa de cores é fornecido como uma lista de valores de pixels com cores associadas. Existem três modos de interpolação:

  • linear (Interpolated): a cor é interpolada linearmente a partir das entradas do mapa de cores acima e abaixo do valor do pixel

  • discreto (Discrete): a cor é obtida da entrada mais próxima do mapa de cores com valor igual ou superior

  • exato (Exact): a cor não é interpolada, apenas pixels com valores iguais às entradas do mapa de cores serão desenhados

Na segunda etapa, associaremos esse sombreador à camada raster:

renderer = QgsSingleBandPseudoColorRenderer(rlayer.dataProvider(), 1, shader)
rlayer.setRenderer(renderer)

O número ``1 ‘’ no código acima é o número da banda (as bandas raster são indexadas a partir de uma).

Finally we have to use the triggerRepaint() method to see the results:

rlayer.triggerRepaint()

5.2.2. Rasters Multibandas

By default, QGIS maps the first three bands to red, green and blue to create a color image (this is the MultiBandColor drawing style). In some cases you might want to override these setting. The following code interchanges red band (1) and green band (2):

rlayer_multi = QgsProject.instance().mapLayersByName('multiband')[0]
rlayer_multi.renderer().setGreenBand(1)
rlayer_multi.renderer().setRedBand(2)

No caso de apenas uma banda ser necessária para a visualização do raster, o desenho de banda única pode ser escolhido, tanto em níveis de cinza quanto em pseudocolor.

We have to use triggerRepaint() to update the map and see the result:

rlayer_multi.triggerRepaint()

5.3. Valores de Consulta

Raster values can be queried using the sample() method of the QgsRasterDataProvider class. You have to specify a QgsPointXY and the band number of the raster layer you want to query. The method returns a tuple with the value and True or False depending on the results:

val, res = rlayer.dataProvider().sample(QgsPointXY(20.50, -34), 1)

Another method to query raster values is using the identify() method that returns a QgsRasterIdentifyResult object.

ident = rlayer.dataProvider().identify(QgsPointXY(20.5, -34), QgsRaster.IdentifyFormatValue)

if ident.isValid():
  print(ident.results())
{1: 323.0}

In this case, the results() method returns a dictionary, with band indices as keys, and band values as values. For instance, something like {1: 323.0}

5.4. Editing raster data

You can create a raster layer using the QgsRasterBlock class. For example, to create a 2x2 raster block with one byte per pixel:

block = QgsRasterBlock(Qgis.Byte, 2, 2)
block.setData(b'\xaa\xbb\xcc\xdd')

Raster pixels can be overwritten thanks to the writeBlock() method. To overwrite existing raster data at position 0,0 by the 2x2 block:

provider = rlayer.dataProvider()
provider.setEditable(True)
provider.writeBlock(block, 1, 0, 0)
provider.setEditable(False)