Her hücrenin denize olan mesafeyi kaydettiği raster oluşturuluyor mu?


10

Her bir hücrenin, hücrenin merkezinden hesaplandığı gibi en yakın kıyı şeridine olan uzaklığı içerdiği 25 metre × 25 metre çözünürlüğe sahip bir tarama oluşturmak istiyorum. Bunu yapmak için, elimde olan tek şey Yeni Zelanda kıyı şeridinin bir şekil dosyası .

Dominic Roye'nin çalışmasını takip eden R'de yapmayı denedim . Yaklaşık 1 km × 1 km çözünürlüğe kadar iyidir, ancak daha yüksek bir rakama gitmeye çalışırsam, bilgisayarımdaki (~ 70 gb RAM gereklidir) veya erişimim olan diğerlerini de aşar. Bunu söylerken, bunun R'nin bir sınırlaması olduğunu düşünüyorum ve QGIS'in bu raster oluşturmanın daha hesaplamalı olarak etkili bir yoluna sahip olabileceğinden şüpheleniyorum, ancak ben onun için yeniyim ve bunu nasıl yapacağımı tam olarak anlayamıyorum.

QGIS kullanarak özelliğe uzaklık ile raster oluşturma izledim mi? QGIS'de oluşturmak için bu hatayı döndürür:

_core.QgsProcessingException: INPUT için kaynak katman yüklenemedi: C: /..../ Sahil Şeridi / nz-kıyı çizgileri-ve-adalar-çokgenler-topo-150k.shp bulunamadı

ve neden olduğundan emin değilim.

Neyin yanlış gidebileceğine dair herhangi bir öneri veya bunu yapmanın alternatif bir yolu var mı?

Düzenle:

Üretmeyi umduğum raster yaklaşık 59684 sıra ve 40827 sütuna sahip olacak, böylece LINZ'in yıllık su açığı rasteriyle çakışacak . Üretilen raster yıllık su eksikliği rasterinden daha büyükse, R'de snip yapabilirim ...

Potansiyel bir sorun olabileceğini düşündüğüm bir şey, NZ'nin kıyı şeridinin şekil dosyasının adalar arasında çok miktarda denizi olması ve bu hücreler için kıyıya olan mesafeyi hesaplamakla ilgilenmiyorum. Gerçekten sadece bir parça toprak içeren hücrelerin değerlerini hesaplamak istiyorum. Bunu nasıl yapacağımdan emin değilim ya da aslında bir sorun olsa.


1
Bunu yapmak için bir komut dosyası mı kullanıyorsunuz? Yoksa QGIS'deki araçları mı kullanıyorsunuz? Kontrol edilmesi gereken bir şey, olması gerektiği gibi görünse de - dosyanın gerçekten söylediğiniz yerde var olduğunu kontrol edin ... ayrıca belirli bir klasöre okuma ve yazma erişiminiz olup olmadığını kontrol edin.
Keagan Allan

Şu anda araçları kullanarak ama senaryoyu öğrenmek için oldukça hevesliyim, nereden başlayacağınızdan emin değilim. QGIS içine .shp dosyasını yükledim ve bir görüntü olarak açılır dosya var eminim. Makinede yönetici olduğum için ve okuma / yazma erişimim de olmalı ve sadece dropbox'ımda.
André.B

Dropbox'tan yerel bir sürücüye taşımayı deneyin. QGIS'in onu reddetmesine neden olan yolla ilgili bir sorun olabilir. QGIS'de yapmak istediğiniz şey oldukça basit olmalı. Hangi QGIS sürümünü kullanıyorsunuz?
Keagan Allan

1
Tamam, çoklu hattı bir raster dönüştürmeye çalışın. QGIS içindeki Yakınlık aracının raster girişine ihtiyacı vardır. Aracın yardımına göre ayarlarla oynayın: docs.qgis.org/2.8/en/docs/user_manual/processing_algs/gdalogr/… . Dikkat edin, hala yoğun bir süreç, şimdi eğlenmek için test ediyorum ve 30 dakika çalışıyor ve hala gidiyor ...
Keagan Allan

1
Satırlar ve sütunlar açısından hangi boyutta çıktı raster oluşturmaya çalışıyorsunuz? Aslında yarattıktan sonra bu tarama ile çalışabilecek misin? Her şeyin dosya boyutu bir sorunsa, daha küçük karolar oluşturabilir misiniz, bu da hız için bir kümede veya bulutta paralel olarak yapabileceğiniz bir şeydir.
Spacedman

Yanıtlar:


9

İle PyQGIS ve GDAL piton kütüphanesine bunu çok zor değildir. Sonuçta raster oluşturmak için coğrafi dönüşüm parametrelerine (sol üst x, x piksel çözünürlüğü, döndürme, sol üst y, döndürme, ns piksel çözünürlüğü) ve satır ve sütun numarasına ihtiyacınız vardır. En yakın sahil şeridine olan mesafeyi hesaplamak için sahil şeridini temsil etmek için bir vektör katmanı gereklidir.

İle PyQGIS , hücrenin merkezi olarak her raster noktası hesaplanır ve kıyı şeridi uzaklığı den 'closestSegmentWithContext' yöntemi kullanarak ölçülür QgsGeometry sınıfı. GDAL python kitaplığı, satır x sütun dizisinde bu mesafe değerlerine sahip bir tarama oluşturmak için kullanılır.

Aşağıdaki kod (397106.7689872353, 4499634.06675821) 'de başlayan bir mesafe tarama (25 mx 25 m çözünürlük ve 1000 sıra x 1000 sütun) oluşturmak için kullanıldı; ABD'nin batı sahil şeridine yakın.

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

Kodun üzerinde çalıştıktan sonra, elde edilen raster QGIS'e yüklendi ve aşağıdaki görüntüdeki gibi görünüyor (5 sınıflı sahte renk ve Spektral rampa). Projeksiyon UTM 10 N'dir (EPSG: 32610)

resim açıklamasını buraya girin


Bu bir sorun olmayabilir, ancak biraz endişelendiğim bir şey, çokgenin Yeni Zelanda ve çevresindeki adalar olması, yani çevredeki denizin büyük bir kısmını içerdiği anlamına geliyor. Ben başımı kod etrafında almaya çalışıyorum, ama örnek ile ben NA denizdeki tüm hücrelerin değerini ayarlamak mümkün olacak? Gerçekten sadece karadaki noktalardan denize olan mesafeyle ilgileniyorum.
André.B

Bu aptalca bir soru ise şimdiden özür dilerim ama eyaletler için koordinatları belirleme biçiminde Yeni Zelanda'da nasıl yeni bir başlangıç ​​noktası seçerim? Ayrıca EPSG: 2193'te nasıl saklayabilirim?
André.B

7

Denemek için bir çözüm olabilir:

  1. Izgara oluşturma ("Nokta" yazın, "Izgara oluştur" algoritması)
  2. "Özniteliğe en yakın şekilde katıl" algoritmasıyla noktalarınız (ızgara) ile çizginiz (sahil) arasındaki en yakın mesafeyi hesaplayın. En fazla 1 yakın komşu seçmeye dikkat edin.

Şimdi bu örnekteki gibi kıyıya olan mesafeyle yeni bir nokta katmanınız olmalı resim açıklamasını buraya girin

  1. Gerekirse, yeni nokta katmanınızı raster haline getirebilirsiniz ("rasterleştir" algoritması)

resim açıklamasını buraya girin


2

QGIS içinde GRASS eklentisini deneyebilirsiniz. Bildiğim kadarıyla belleği R'den daha iyi yönetiyor ve diğer çözümün geniş alanlarda başarısız olmasını bekliyorum.

GRASS komutuna, işleme araç çubuğunda bulabileceğiniz r.grow.distance denir. İlk önce hattınızı raster dönüştürmeniz gerektiğini unutmayın.

resim açıklamasını buraya girin

Sorununuzdan biri çıktının boyutu olabilir, bu nedenle (bir tif dosyası için) BIGTIFF = EVET, TILED = EVET, COMPRESS = LZW, PREDICTOR = 3 gibi bazı yararlı oluşturma seçenekleri ekleyebilirsiniz.


Boyutu / hesaplama süresini azaltmak için herhangi bir deniz alanını ortadan kaldırabileceğim bir yol var mı?
André.B

teoride, sahil şeridinden ziyade görmekle olan mesafeyi (hepsi aynı değere sahip pikselleri, yani bir çokgeni görür) kullanırsanız, hesaplama zamanından tasarruf etmelisiniz. Rasterin sıkıştırılmamış boyutu aynı olmalıdır, ancak sıkıştırma daha verimli olacaktır, bu nedenle son boyutu da azaltmalısınız.
radouxju

0

Başka bir yol denemek istiyorum. NZ poligonu kullanıyorsanız, poligon kenarlarını çizgiye dönüştürün. Bundan sonra, sınırdan her 25 metrelik mesafe için sınırda tampon oluşturun (belki de sentorid ne zaman duracağınızı belirlemeye yardımcı olabilir). Sonra tamponları çokgen ile kesin ve çokgenleri raster haline getirin. Bunun işe yarayacağından emin değilim ama kesinlikle daha az RAM'e ihtiyacınız olacak. Performans sorunlarınız olduğunda PostGiS mükemmeldir.

Umarım en azından biraz yardımcı olabilir :)


0

Aslında kendi soruma cevap vermeyecektim ama bir meslektaşım (bu siteyi kullanmayan), bana ne olduğumu yapmak için bir sürü python kodu yazdı; sadece karasal hücreler için kıyıya olan mesafeyi sınırlamak ve deniz bazlı hücreleri NA olarak bırakmak. Aşağıdaki kod, değişiklik gerektiren tek şey olan herhangi bir python konsolundan çalışabilmelidir:

1) Komut dosyasını ilgili şekil dosyasıyla aynı klasöre koyun;

2) python betiğindeki şekil dosyasının adını şekil dosyanızın adı ne olursa olsun değiştirin;

3) istenen çözünürlüğü ayarlayın ve;

4) diğer rasterlerle eşleşecek şekilde kapsamı değiştirin.

Kullandığımdan daha büyük şekil dosyaları büyük miktarlarda RAM gerektirir, ancak komut dosyasının çalışması hızlıdır (50m çözünürlüklü bir raster üretmek için yaklaşık üç dakika ve 25m çözünürlüklü raster için on dakika).

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

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.