5. ラスタレイヤを使う

ヒント

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. レイヤの詳細

ひとつのラスタレイヤは、1つまたは複数のラスタバンド(シングルバンドおよびマルチバンドラスタと呼ばれる)で構成されています。1つのバンドは、値の行列を表します。カラー画像(航空写真など)は、赤、青、緑のバンドで構成されるラスタです。シングルバンドのラスタは、通常、連続変数(標高など)または離散変数(土地利用など)を表します。ラスタレイヤにパレットが付属し、ラスタ値がパレットに格納されている色を参照する場合もあります。

次のコードは rlayerQgsRasterLayer オブジェクトであると仮定しています。

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. レンダラー

ラスタレイヤがロードされると、そのタイプに応じたデフォルトレンダラーが取得されます。これは、レイヤプロパティまたはプログラムによって変更することができます。

現在のレンダラーを問い合わせるには:

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

レンダラーを設定するには、 QgsRasterLayersetRenderer() メソッドを使います。レンダラークラス( QgsRasterRenderer から派生したもの)は多数存在します:

シングルバンドのラスタレイヤは、グレーカラー(低い値=黒、高い値=白)、または値に色を割り当てる疑似カラーアルゴリズムで描画することができます。パレットを持つシングルバンドラスタは、そのパレットを使って描画することもできます。マルチバンドレイヤは、通常、バンドをRGBカラーにマッピングして描画します。他には、描画に1つのバンドだけを使うこともできます。

5.2.1. シングルバンドラスタ

例えば、緑から黄色までの色(0から255までのピクセル値に対応)を持つシングルバンドのラスタレイヤをレンダリングしたいとします。最初の段階では、 QgsRasterShader オブジェクトを用意し、シェーダ関数を設定します:

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)

シェーダはカラーマップで指定された色をマッピングします。カラーマップは、ピクセル値と関連する色のリストとして提供されます。補間には3つのモードがあります:

  • 線形 (Interpolated): ピクセル値の上下のカラーマップエントリから線形補間された色

  • 離散 (Discrete): 同じかそれ以上の値を持つ、最も近いカラーマップのエントリから取得された色

  • 同値 (Exact): 色は補間されず、カラーマップのエントリと同じ値を持つピクセルのみが描画されます

第2ステップでは、このシェーダをラスタレイヤに関連付けます:

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

上のコードにある 1 という数字はバンド番号です(ラスタバンドは1から始まるインデックスを持ちます)。

最後に、結果を見るために triggerRepaint() メソッドを使わなければなりません:

rlayer.triggerRepaint()

5.2.2. マルチバンドラスタ

デフォルトでは、QGISは最初の3つのバンドを赤、緑、青にマッピングしてカラー画像を作成します(これが MultiBandColor という描画スタイルです)。場合によってはこれらの設定を上書きしたいこともあるでしょう。以下のコードは赤のバンド(1)と緑のバンド(2)を入れ替えます:

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

ラスタの視覚化に必要なバンドが1つだけの場合は、グレーレベルまたは擬似カラーによる単一バンドの描画を選択できます。

マップを更新して結果を見るには triggerRepaint() を使わなければなりません:

rlayer_multi.triggerRepaint()

5.3. 値の検索

ラスタ値は QgsRasterDataProvider クラスの sample() メソッドを使って問い合わせることができます。QgsPointXY と問い合わせたいラスタレイヤのバンド番号を指定する必要があります。メソッドはその値と、結果に応じて True または False をタプルで返します:

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

ラスタの値を問い合わせるもう一つの方法は、QgsRasterIdentifyResult オブジェクトを返す identify() メソッドを使うことです。

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

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

この場合、 results() メソッドは、バンドのインデックスをキー、バンドの値を値とする辞書を返します。例えば、 {1: 323.0} のようになります

5.4. ラスタデータを編集する

ラスタレイヤは QgsRasterBlock クラスを使って作成することができます。例えば、1ピクセルあたり1バイトの2x2のラスターブロックを作成するには:

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

ラスタのピクセルは writeBlock() メソッドによって上書きすることができます。0,0の位置にある既存のラスタデータを2x2のブロックで上書きするには:

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