各セルが海までの距離を記録するラスターを作成していますか?


10

25メートル×25メートルの解像度でラスターを作成します。各セルには、セルの中心から計算した最も近い海岸線までの距離が含まれています。これを行うには、ニュージーランドの海岸線のシェープファイルだけです

私はRでそれを行うためのDominic Royeのチュートリアルを試してみました... それは約1 km×1 kmの解像度まで問題ありませんが、RAMをさらに高くしようとすると、必要なRAMは私のPC(約70 GBのRAMが必要)または私がアクセスできる他のRAMで利用可能なRAM容量をはるかに超えます。とは言っても、これはRの制限だと思います。QGISがこのラスターを作成する計算効率の高い方法を持っているのではないかと思いますが、私はそれに慣れていないため、その方法を完全に理解できません。

QGISを使用してフィーチャまでの距離を持つラスターの作成を試してみましたか?QGISでそれを作成するが、それはこのエラーを返します:

_core.QgsProcessingException:INPUTのソースレイヤーを読み込めませんでした:C:/..../ Coastline / nz-coastlines-and-islands-polygons-topo-150k.shpが見つかりません

理由はわかりません。

誰かが何がうまくいかないのか、これを行う別の方法について何か提案はありますか?

編集:

私が作成することを望んでいるラスターは、約59684行と40827列を持ち、LINZの年間水不足ラスターと重複します。生成されるラスターが年間の水不足のラスターよりも大きい場合、Rで切り取ることができますが...

NZの海岸線のシェープファイルには、島の間に大量の海があり、これらのセルの海岸までの距離の計算には興味がありません。土地の一部を含むセルの値のみを計算したいのですが。これを行う方法、またはそれが実際に問題であるかどうかはわかりません。


1
これを行うスクリプトを実行していますか?それともQGISのツールを使用していますか?確認する必要があるように見えますが、確認する必要があります。ファイルが実際に存在する場所に存在することを確認してください。また、その特定のフォルダに対する読み取りおよび書き込みアクセス権があることを確認してください。
Keagan Allan

現在ツールを使用していますが、どこから始めればよいかわからないため、スクリプトを習得したいと思っています。.shpファイルをQGISにロードし、画像としてポップアップ表示したので、ファイルが存在することを確認しています。私はマシンの管理者であり、それは私のドロップボックスにあるので、私も読み取り/書き込みアクセス権を持っている必要があります。
André.B

Dropboxからローカルドライブに移動してみてください。QGISがパスを拒否する原因となっているパスに問題がある可能性があります。あなたがしようとしていることは、QGISではかなり単純でなければなりません。QGISのどのバージョンを使用していますか?
Keagan Allan

1
では、ポリラインをラスターに変換してみてください。QGISの近接ツールにはラスター入力が必要です。ツールのヘルプに従って設定を試してください:docs.qgis.org/2.8/en/docs/user_manual/processing_algs/gdalogr/…。注意してください、それはまだ集中的なプロセスです、私は今楽しみのためにそれをテストしています、そしてそれは30分間走っていて、そしてまだ続いています...
Keagan Allan

1
作成しようとしている行と列の観点から、出力ラスターのサイズを教えてください。作成したら、実際にそのラスターで作業できるようになりますか?全体のファイルサイズに問題がある場合は、小さいタイルを作成できますか。これは、速度を上げるためにクラスターまたはクラウドで並列に実行できるものでもあります。
Spacedman

回答:


9

PyQGISGDAL Pythonライブラリそれを行うことは非常に難しいことではありません。結果のラスタ​​ーを作成するには、地理変換パラメーター(左上x、xピクセル解像度、回転、左上y、回転、nsピクセル解像度)および行と列の数が必要です。最も近い海岸線までの距離を計算するには、海岸線を表すためのベクターレイヤーが必要です。

PyQGIS、セルの中心として各ラスタ点が計算され、海岸線までの距離がから「closestSegmentWithContext」メソッドを使用して測定されるQgsGeometryのクラス。GDAL Pythonライブラリは、行x列の配列にこれらの距離値を持つラスターを生成するために使用されます。

次のコードを使用して、ポイント(397106.7689872353、4499634.06675821)から始まる距離ラスター(25 m×25 mの解像度と1000行x 1000列)を作成しました。アメリカの西海岸線の近く。

from osgeo import gdal, osr
import numpy as np
from math import sqrt

registry = QgsProject.instance()

line = registry.mapLayersByName('shoreline_10N')

crs = line[0].crs()

wkt = crs.toWkt()

feats_line = [ feat for feat in line[0].getFeatures()]

pt = QgsPoint(397106.7689872353, 4499634.06675821)

xSize = 25
ySize = 25

rows = 1000
cols = 1000

raster = [ [] for i in range(cols) ]

x =   xSize/2
y = - ySize/2

for i in range(rows):
    for j in range(cols):
        point = QgsPointXY(pt.x() + x, pt.y() + y)
        tupla = feats_line[0].geometry().closestSegmentWithContext(point)
        raster[i].append(sqrt(tupla[0]))

        x += xSize
    x =  xSize/2
    y -= ySize

data = np.array(raster)

# Create gtif file 
driver = gdal.GetDriverByName("GTiff")

output_file = "/home/zeito/pyqgis_data/distance_raster.tif"

dst_ds = driver.Create(output_file, 
                       cols, 
                       rows, 
                       1, 
                       gdal.GDT_Float32)

#writting output raster
dst_ds.GetRasterBand(1).WriteArray( data )

transform = (pt.x(), xSize, 0, pt.y(), 0, -ySize)

#setting extension of output raster
# top left x, w-e pixel resolution, rotation, top left y, rotation, n-s pixel resolution
dst_ds.SetGeoTransform(transform)

# setting spatial reference of output raster 
srs = osr.SpatialReference()
srs.ImportFromWkt(wkt)
dst_ds.SetProjection( srs.ExportToWkt() )

dst_ds = None

上記のコードを実行した後、結果のラスタ​​ーはQGISにロードされ、次の画像のようになります(5つのクラスとスペクトルランプを含む疑似カラー)。投影はUTM 10 N(EPSG:32610)

ここに画像の説明を入力してください


これは問題ではないかもしれませんが、私が少し心配していることの1つは、ポリゴンがニュージーランドとその周辺の島々であることです。私はコードを理解しようとしていますが、あなたの例では、海のすべてのセルの値をNAに設定できますか?私は本当に陸上の点から海までの距離にのみ興味があります。
André.B

これが馬鹿げた質問である場合は、事前に謝罪しますが、州の座標を設定する方法でニュージーランドの新しい出発点を選択するにはどうすればよいですか?また、EPSG:2193に保存するにはどうすればよいですか?
André.B

7

試すための解決策かもしれません:

  1. グリッドを生成(タイプ「ポイント」、アルゴリズム「グリッドの作成」)
  2. アルゴリズム「属性を最近接で結合」を使用して、ポイント(グリッド)とライン(海岸)の間の最短距離を計算します。最大1つの最近傍のみを選択するように注意してください。

これで、この例のように、海岸までの距離を持つ新しいポイントレイヤーができました。 ここに画像の説明を入力してください

  1. 必要に応じて、新しいポイントレイヤーをラスターに変換できます(アルゴリズムは「ラスター化」)。

ここに画像の説明を入力してください


2

QGIS内で、GRASSプラグインを試すことができます。私の知る限り、それはRよりもメモリを適切に管理し、他のソリューションは大きな領域で失敗することを期待しています。

GRASSコマンドはr.grow.distanceと呼ばれ、処理ツールバーにあります。最初にラインをラスターに変換する必要があることに注意してください。

ここに画像の説明を入力してください

問題の1つは出力のサイズである可能性があるため、(tifファイルの)BIGTIFF = YES、TILED = YES、COMPRESS = LZW、PREDICTOR = 3などのいくつかの便利な作成オプションを追加できます。


サイズ/計算時間を短縮するために海域を削除できる方法はありますか?
André.B

理論的には、海岸線からではなく、シー(すべて同じ値のピクセル、つまりポリゴン)からの距離を使用する場合、計算時間を節約する必要があります。ラスターの非圧縮サイズは同じである必要がありますが、圧縮の方が効率的であるため、最終的なサイズも小さくする必要があります。
radouxju

0

私は他の方法で試します。NZのポリゴンを使用している場合は、ポリゴンエッジをラインに変換します。その後、境界から25メートルの距離ごとに境界にバッファーを作成します(おそらく、中心点は停止するタイミングの決定に役立つ場合があります)。次に、バッファをポリゴンで切り取り、そのポリゴンをラスターに変換します。これが機能するかどうかはわかりませんが、RAMが少なくて済みます。そして、PostGiSはパフォーマンスの問題があるときに最適です。

それが少なくとも少し役立つかもしれないことを願っています:)


0

私はもともと自分の質問に答えるつもりはありませんでしたが、私の同僚(このサイトを使用していません)が、私が求めていることを実行するための一連のPythonコードを書いてくれました。陸域セルのみを沿岸までの距離を持つようにセルを制限し、海ベースのセルをNAとして残します。次のコードは、どのPythonコンソールからでも実行でき、変更が必要なものは次のとおりです。

1)スクリプトファイルを目的のシェイプファイルと同じフォルダーに配置します。

2)Pythonスクリプト内のシェープファイルの名前を、シェープファイルの名前が何であるかに変更します。

3)必要な解像度を設定します。

4)他のラスターと一致するように範囲を変更します。

私が使用しているものよりも大きいシェープファイルは大量のRAMを必要としますが、それ以外の場合、スクリプトの実行は高速です(50m解像度のラスターを生成するには約3分、25m解像度のラスターを生成するには10分)。

#------------------------------------------------------------------------------

from osgeo import gdal, ogr
import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt
import time

startTime = time.perf_counter()

#------------------------------------------------------------------------------

# Define spatial footprint for new raster
cellSize = 50 # ANDRE CHANGE THIS!!
noData = -9999
xMin, xMax, yMin, yMax = [1089000, 2092000, 4747000, 6224000]
nCol = int((xMax - xMin) / cellSize)
nRow = int((yMax - yMin) / cellSize)
gdal.AllRegister()
rasterDriver = gdal.GetDriverByName('GTiff')
NZTM = 'PROJCS["NZGD2000 / New Zealand Transverse Mercator 2000",GEOGCS["NZGD2000",DATUM["New_Zealand_Geodetic_Datum_2000",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6167"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4167"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",173],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",1600000],PARAMETER["false_northing",10000000],AUTHORITY["EPSG","2193"],AXIS["Easting",EAST],AXIS["Northing",NORTH]]'

#------------------------------------------------------------------------------ 

inFile = "new_zealand.shp" # CHANGE THIS!!

# Import vector file and extract information
vectorData = ogr.Open(inFile)
vectorLayer = vectorData.GetLayer()
vectorSRS = vectorLayer.GetSpatialRef()
x_min, x_max, y_min, y_max = vectorLayer.GetExtent()

# Create raster file and write information
rasterFile = 'nz.tif'
rasterData = rasterDriver.Create(rasterFile, nCol, nRow, 1, gdal.GDT_Int32, options=['COMPRESS=LZW'])
rasterData.SetGeoTransform((xMin, cellSize, 0, yMax, 0, -cellSize))
rasterData.SetProjection(vectorSRS.ExportToWkt())
band = rasterData.GetRasterBand(1)
band.WriteArray(np.zeros((nRow, nCol)))
band.SetNoDataValue(noData)
gdal.RasterizeLayer(rasterData, [1], vectorLayer, burn_values=[1])
array = band.ReadAsArray()
del(rasterData)

#------------------------------------------------------------------------------

distance = ndimage.distance_transform_edt(array)
distance = distance * cellSize
np.place(distance, array==0, noData)

# Create raster file and write information
rasterFile = 'nz-coast-distance.tif'
rasterData = rasterDriver.Create(rasterFile, nCol, nRow, 1, gdal.GDT_Float32, options=['COMPRESS=LZW'])
rasterData.SetGeoTransform((xMin, cellSize, 0, yMax, 0, -cellSize))
rasterData.SetProjection(vectorSRS.ExportToWkt())
band = rasterData.GetRasterBand(1)
band.WriteArray(distance)
band.SetNoDataValue(noData)
del(rasterData)

#------------------------------------------------------------------------------

endTime = time.perf_counter()

processTime = endTime - startTime

print(processTime)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.