Python地理データ処理12:ラスターデータの読み取りと書き込み


1. GDAL

  GDAL(Geospatial Data Abstraction Library)は、非常に人気があり強力なラスターファイルの読み取りおよび書き込みライブラリです。GDALライブラリはオープンソースですが、ライセンスが緩いため、多くの商用ソフトウェアパッケージで使用されています。商用ソフトウェアのArcGIS、ENVI、オープンソースソフトウェアのGRASS、QGISのいずれであっても、既存のGISまたはリモートセンシングプラットフォームのほとんどは、基盤となる構築ライブラリとしてGDALを使用します。
  GDALライブラリは、さまざまな形式の読み取りと書き込みができることでよく知られていますが、近接分析などのデータ処理機能も含まれています。NumPyモジュールは、大きな行列データの処理に特化しており、GDALを使用してデータをNumPy配列に直接読み込むことができます。データを操作した後、NumPyまたは他のモジュールを使用してこれらの行列を処理し、配列をラスターデータセットとしてディスクに書き戻すことができます。GDALラスタードライバーを
  表示できます

ここに画像の説明を挿入します
  各ドライバーは、特定のデータ形式を読み書きします。GDALのデータ構造は、ラスターデータセットとほぼ一致します。各データセットには、1つ以上のバンドが含まれています、各バンドには、ピクセルデータと可能な概要が含まれています。すべてのバンドが同じ地理参照情報を使用するため、地理参照情報がデータセットに含まれます。

ここに画像の説明を挿入します
  LANDSATシリーズの衛星は、米国航空宇宙局(NASA)と米国地質調査所(USGS)が共同で管理しています。1972年以来、8つのLANDSATシリーズ衛星が打ち上げられました(6回目の打ち上げは失敗しました)。Landsat1-5は現在廃止されています。Landsat7には、2003年6月以降のセンサーのスキャンラインコレクター(SLC)の障害に起因するデータギャップデータがありますが、まだ実行中です。Landsat8は、2013年2月11日に打ち上げられ、100日間のテスト運用後に画像の取得を開始しましたが、現在も運用されています。
  米国地質調査所は、Landsat画像をGeoTIFF画像コレクションに処理します。バンド6(熱赤外線)とバンド8(パンクロマティック)を除いて、各バンドの解像度は30メートルです。これは、同じランドサットシーンからのものであり、同じサイズであるためです。バンドは、変更せずに直接積み重ねることができます。

  1.独立したラスターバンドを1つの画像に結合します。

# Script to stack three 1-band rasters into a a single 3-band image.
import os
from osgeo import gdal

os.chdir(r'E:\Google chrome\Download\gis with python\Landsat\Washington')
band1_fn = 'p047r027_7t20000730_z10_nn10.tif'
band2_fn = 'p047r027_7t20000730_z10_nn20.tif'
band3_fn = 'p047r027_7t20000730_z10_nn30.tif'

# 打开GeoTIFF波段1,索引为1
# 波段索引从1开始,而不是0
in_ds = gdal.Open(band1_fn)
in_band = in_ds.GetRasterBand(1)

# 利用和波段1相同的属性创建三波段GeoTIFF
gtiff_driver = gdal.GetDriverByName('GTiff')  # 使用驱动对象创建新的数据集
out_ds = gtiff_driver.Create('nat_color.tif',
    in_band.XSize, in_band.YSize, 3, in_band.DataType)
out_ds.SetProjection(in_ds.GetProjection())
out_ds.SetGeoTransform(in_ds.GetGeoTransform())

# 从输入波段复制像素到输出波段3
in_data = in_band.ReadAsArray()
out_band = out_ds.GetRasterBand(3)
out_band.WriteArray(in_data)

# 从数据集,而不是波段复制像素
in_ds = gdal.Open(band2_fn)
out_band = out_ds.GetRasterBand(2)
out_band.WriteArray(in_ds.ReadAsArray())

# 为每个波段计算统计值
out_ds.GetRasterBand(1).WriteArray(
    gdal.Open(band3_fn).ReadAsArray())

out_ds.FlushCache()
for i in range(1, 4):
    out_ds.GetRasterBand(i).ComputeStatistics(False)

# 创建概视图或金字塔图层
out_ds.BuildOverviews('average', [2, 4, 8, 16, 32])

del out_ds

  RGB画像:

ここに画像の説明を挿入します
  driver.Create(filename、xsize、ysize、[bands]、[data_type]、[options]):

  1. ファイル名:作成されたデータセットのパス
  2. ysize:新しいデータセットの列数
  3. バンド:新しいデータセットのバンド数。デフォルト値は1です。
  4. data_type:新しいデータセットに格納されるデータ型。デフォルトはGDT_Byteです。
  5. option:オプション文字列のリストを作成します。値は、作成されたデータセットのタイプに基づいています。

  GDALデータ型:

絶え間ない データの種類
GDT_Unknown わからない
GDT_Byte 符号なし8ビット整数(バイト)
GDT_UInt16 符号なし16ビット整数
GDT_Int16 符号付き16ビット整数
GDT_UInt32 符号なし32ビット整数
GDT_Int32 符号付き32ビット整数
GDT_Float32 32ビット浮動小数点
GDT_Float64 64ビット浮動小数点
GDT_CInt16 16ビット複素整数
GDT_CInt32 32ビット複素整数
GDT_CFloat32 32ビットの複素浮動小数点
GDT_CFloat64 64ビットの複素数浮動小数点
GDT_TypeCount 利用可能なデータ型の数

  この情報は入力帯域から取得されますが、これらの画像はGDT_Byteのデフォルトタイプを使用します。

  1.空の3バンドデータセットのSRSを表示します。

out_ds.SetProjection(in_ds.GetProjection())
out_ds.SetGeoTransform(in_ds.GetGeoTransform())

  入力データセットからSRSを取得し、それを新しいデータセットにコピーしてから、geotransformで同じ操作実行します。geotransformは、元の座標とピクセルサイズ、および回転値を提供して、画像の上部を北に向けます。データセットを正しいスペースに配置する必要がある場合、データセットとピクセルサイズは非常に重要なパラメータです。

  2.データセットを作成した、ピクセル値を追加し、バンド1の読み取られたピクセル値をNumPy配列に読み込みますReadasarray()関数にパラメーター指定しないと、すべてのピクセル値がグリッドと同じサイズの2次元配列で返されます。in_data変数は、ピクセル値の2次元配列を保持します。

in_data = in_band.ReadAsArray()

  3.バンド1は青いバンドであるため、RGBバンドの順序を取得するには、出力レイヤーの3番目のバンド位置に配置する必要があります。
  次に、out_dataから3番目のEbertonを取得し、WriteArray()関数を使用して、in_data配列のピクセル値を新しいデータセットの3番目のバンドにコピーします。

out_band = out_ds.GetRasterBand(3)
out_band.WriteArray(in_data)

  4.赤と緑のバンドをデータセットに追加し、バンド2のGeoTIFFをオンにします。データセットから直接ピクセルデータを読み取ります。

in_ds = gdal.Open(band2_fn)
out_band = out_ds.GetRasterBand(2)
out_band.WriteArray(in_ds.ReadAsArray())

  データセットでReadAsArray関数が呼び出されたときに、読み取られているデータセットに複数のバンドがある場合、3次元配列が取得されます。Landsatファイルにはバンドが1つしかないため、2次元配列を返します。

  5.赤いピクセル値についても同じことを行いますが、より少ないコードに圧縮します。

out_ds.GetRasterBand(1).WriteArray(gdal.Open(band3_fn).ReadAsArray())

  6.データセット内の各バンドの統計データを計算します。これにより、ソフトウェアの表示が容易になります。統計データには、バンドの平均、最小、最大、および標準のチェックが含まれます。これにより、GISソフトウェアはこの情報を使用して画面データを拡大し、見栄えを良くすることができます。
  統計データの前に、データがディスクに書き込まれていることを確認し、各バンドの統計データを計算する必要があります。この関数にFalseを渡して、推定ではなく、必要な実際の統計を伝えます。これは、概要またはサンプリングされたピクセルのサブセットから取得される可能性があるためです。推定値が許容できる場合は、関数にTrueを渡します。これにより、すべてのピクセルをチェックする必要がないため、計算が高速になります。

out_ds.FlushCache()
for i in range(1, 4):
    out_ds.GetRasterBand(i).ComputeStatistics(False)

  7.データセットの概要を作成します

out_ds.BuildOverviews('average', [2, 4, 8, 16, 32])

  これはrasterioで表示できます。このモジュールはGDALに依存しています。GDALは基本的にGDALを使用してデータの読み取りと書き込みを行いますが、rasterioモジュールはラスターデータの処理を容易にしようとします。
  imageioモジュールはGDALに依存しません。これは、純粋にPythonで記述されたモジュールであり、地理空間データに焦点を当てていません。ビデオ形式を含むさまざまなラスター形式の読み取りと書き込みが可能です。

2.データセットの一部を読み取ります

  画像全体にアクセスするのではなく、サブセットにアクセスします。ReadAsAsrray()関数にはいくつかのオプションのパラメーターがあり、データセットとバンドのどちらを使用しているかによって異なります。
  band.ReadAsArray([xoff]、[yoff]、[win_xsize]、[win_ysize]、[buf_xsize]、[buf_ysize]、[buf_obj])

  1. xoff:列読み取りの開始点。デフォルト値は0です。
  2. yoff:ライン読み取りの開始点。デフォルト値は0です。
  3. win_xsize:読み取られる列の数。デフォルトではすべての列が読み取られます
  4. win_ysize:読み取られる行数。デフォルトではすべての行が読み取られます
  5. buf_xsize:出力配列の列数。デフォルトはwin_xsizeの値です。値がwin_xsizeと異なる場合、データはリサンプリングされます。
  6. buf_ysize:出力配列の行数。デフォルトはwin_xsizeの値です。値がwin_ysizeと異なる場合、データはリサンプリングされます。
  7. buf_obj:配列を作成する代わりに配列を格納するために使用されるNumPy配列。必要に応じて、データは配列に合うようにリサンプリングされます。値はこのタイプの配列に変換されます。

  xoffパラメーターとyoffパラメーターは、それぞれ読み取りを開始する列と行のオフセット値を指定するために使用されます。デフォルトは、最初の行と最初の列から始まります。
  win_xsizeパラメーターとwin_ysizeパラメーターは、読み取られた行と列の数を表示するために使用されます。すべての行と列
  がデフォルトで読み取られます。指定されたbuf_xsizeとbuf_ysizeが配列のサイズと一致しない場合、エラーが発生しますが、 buf_xsizeとbuf_ysizeを指定する必要はありません。これは配列自体によって決定されるため、の値です。

  1.6000行目と1400列目から始まる3行6列のデータを読み取ります。

import os
import numpy as np
from osgeo import gdal


data_dir = r'E:\Google chrome\Download\gis with python'

# 打开Landsat波段
os.chdir(os.path.join(data_dir, 'Landsat', 'Washington'))
ds = gdal.Open('p047r027_7t20000730_z10_nn10.tif')
band = ds.GetRasterBand(1)

# 读取指定范围数据
data = band.ReadAsArray(1400, 6000, 6, 3)
print(data)

ここに画像の説明を挿入します
ここに画像の説明を挿入します
  2.データ型変換:

# 使用numpy将数据转换为浮点数
data = band.ReadAsArray(1400, 6000, 6, 3).astype(float)
print(data)

ここに画像の説明を挿入します
  3.データを読み取るときは、GDALを使用して変換します。
  最初に浮動小数点配列を作成し、次にそれをbuf_objパラメーターとしてreadasarrayに渡します。その一方で、作成された配列のサイズが読み取られるデータと同じであることを確認します。

# 通过将它们读入浮点数组,来转换为浮点数
import numpy as np

data = np.empty((3, 6), dtype=float)  # dtype参数用来指定数组的数据类型
band.ReadAsArray(1400, 6000, 6, 3, buf_obj=data)
print(data)

ここに画像の説明を挿入します
  4.データ配列を他のデータセットの指定された位置に書き込み、オフセット値を関数に渡します。指定されたオフセット値から開始し、WriteArray()関数に渡された配列にすべてのデータを書き込みます。

band2.WriteArray(data, 1400, 6000)

  5.メモリサイズを超える大きなデータセットの処理:一度に1ブロックのみ。
  注:ラスターデータはディスク上のブロックに保存されるため、これらのブロックでの画像の処理は非常に効率的です。写真が示すように:

ここに画像の説明を挿入します
  DEMの標高をメートル法からフィート法に変換します(一度に1つのみ)。

import os
import numpy as np
from osgeo import gdal

os.chdir(r'E:\Google chrome\Download\gis with python\osgeopy data\Washington\dem')

# 打开输入光栅并获得其尺寸
in_ds = gdal.Open('gt30w140n90.tif')
in_band = in_ds.GetRasterBand(1)
xsize = in_band.XSize
ysize = in_band.YSize

# 获取块大小和NoData值
block_xsize, block_ysize = in_band.GetBlockSize()
nodata = in_band.GetNoDataValue()

# 创建具有相同维度和数据类型的输出文件
out_ds = in_ds.GetDriver().Create(
    'dem_feet.tif', xsize, ysize, 1, in_band.DataType)
out_ds.SetProjection(in_ds.GetProjection())
out_ds.SetGeoTransform(in_ds.GetGeoTransform())
out_band = out_ds.GetRasterBand(1)

# 在x方向循环这些块
for x in range(0, xsize, block_xsize):

    # 获取要读取的列数
    if x + block_xsize < xsize:
        cols = block_xsize
    else:
        cols = xsize - x

    # 在y方向循环blocks
    for y in range(0, ysize, block_ysize):

        # 获取要读取的行数
        if y + block_ysize < ysize:
            rows = block_ysize
        else:
            rows = ysize - y

        # 读取一个块的数据值,将其转换为英尺
        # 然后将结果写入输出中相同的块位置
        data = in_band.ReadAsArray(x, y, cols, rows)
        data = np.where(data == nodata, nodata, data * 3.28084)
        out_band.WriteArray(data, x, y)

# 刷新缓存
# 设置NoData值后进行统计
out_band.FlushCache()
out_band.SetNoDataValue(nodata)
out_band.ComputeStatistics(False)
out_ds.BuildOverviews('average', [2, 4, 8, 16, 32])
del out_ds

  この方法は、バンド全体を一度に読み取るよりも複雑ですが、メモリを節約します。
ここに画像の説明を挿入します
ここに画像の説明を挿入します

2.1実世界の座標を使用する

  必要なデータ:座標原点、ピクセルサイズ、回転値はすべて、データセットからコピーされたジオトランスフォームに保存されます地理的変換は、6つの値を含むタプルです。

インデックス 説明
0 原点のx座標
1 ピクセル幅
2 xピクセル回転(画像が北を向いている場合は0°)
3 原点のy座標
4 yピクセル回転(北向き0°)
5 ピクセルの高さ(負の値)

アフィン変換を実行するためにGDALによって提供されるApplyGeoTransform関数には、geotransform、x値、y値の3つのパラメーターが必要です。データセットのジオトランスフォーム変換を使用する場合、この関数は画像座標(オフセット)を実世界の座標に変換できます。
別の考え方(データセットの逆変換)があります。

# 现在得到逆变换
# 原始文件可用于将偏移量转换为真实世界的坐标
# 而逆文件可用于将真实世界的坐标转换为偏移量

# GDAL 1.x: 你会得到一个成功标志和地理变换
success, inv_gt = gdal.InvGeoTransform(gt)
print(success, inv_gt)

成功した場合は1を返し、失敗した場合は0を返します。

おすすめ

転載: blog.csdn.net/amyniez/article/details/113745573