래스터 파일에 numpy 배열 쓰기


30

저는 GIS를 처음 사용합니다.

화성의 적외선 이미지를 열 관성 맵으로 변환 한 다음 2D numpy 배열로 저장되는 코드가 있습니다. 이 맵을 hdf5 파일로 저장했지만 QGIS에서 처리 할 수 ​​있도록 래스터 이미지로 저장하고 싶습니다. 이 작업을 수행하는 방법을 찾기 위해 여러 번 검색했지만 운이 없었습니다. 튜토리얼 http://www.gis.usu.edu/~chrisg/python/ 의 지침을 따르려고 시도했지만 예제 코드를 사용하여 생성 한 파일은 QGIS로 가져올 때 회색 상자로 열립니다. 누군가가 내가하고 싶은 일의 간단한 예에 가장 간단한 절차를 제안 할 수 있다면 어떤 진전을 보일 수 있다고 생각합니다. 나는 QGIS와 GDAL을 가지고 있으며, 누군가가 추천 할 수있는 다른 프레임 워크를 설치하게되어 매우 기쁩니다. Mac OS 10.7을 사용합니다.

예를 들어 열 관성이 numpy 배열이면 다음과 같습니다.

TI = ( (0.1, 0.2, 0.3, 0.4),
       (0.2, 0.3, 0.4, 0.5),
       (0.3, 0.4, 0.5, 0.6),
       (0.4, 0.5, 0.6, 0.7) )

그리고 각 픽셀마다 위도와 경도가 있습니다.

lat = ( (10.0, 10.0, 10.0, 10.0),
        ( 9.5,  9.5,  9.5,  9.5),
        ( 9.0,  9.0,  9.0,  9.0),
        ( 8.5,  8.5,  8.5,  8.5) )
lon = ( (20.0, 20.5, 21.0, 21.5),
        (20.0, 20.5, 21.0, 21.5),
        (20.0, 20.5, 21.0, 21.5),
        (20.0, 20.5, 21.0, 21.5) ) 

이 데이터를 QGIS에서 열 수있는 래스터 파일로 변환하는 것이 어떤 절차입니까?


튜토리얼에서 어떤 슬라이드를 참조하고 있습니까?
RK

답변:


23

문제에 대한 한 가지 가능한 해결책 : ASCII Raster 로 변환 하십시오 . 이것은 파이썬으로하기가 상당히 쉽습니다.

위의 예제 데이터를 사용하면 .asc 파일에서 다음과 같이 끝납니다.

ncols 4
nrows 4
xllcorner 20
yllcorner 8.5
cellsize 0.5
nodata_value -9999
0.1 0.2 0.3 0.4
0.2 0.3 0.4 0.5
0.3 0.4 0.5 0.6
0.4 0.5 0.6 0.7

이것은 QGIS와 ArcGIS에 성공적으로 추가되고 ArcGIS로 양식화됩니다. 위의 래스터 버전

부록 : 언급 한대로 QGIS에 추가 할 수는 있지만 속성을 사용하여 스타일을 지정하려고하면 QGIS 1.8.0이 중단됩니다. 나는 그것을 버그로보고하려고합니다. 이것이 당신에게도 일어난다면, 다른 많은 무료 GIS가 있습니다.


정말 환상적입니다. 감사합니다. 그리고 배열을 ASCII 파일로 작성하면 미리 작성된 변환 기능을 사용하여 이진 형식으로 변환 할 수 있다고 생각합니다.
EddyTheB

참고로, QGIS와 관련하여 문제가 없었으며 버전 1.8.0도 있습니다.
EddyTheB

31

아래는 numpy 및 gdal Python 모듈을 활용하는 워크샵을 위해 작성한 예제입니다. 하나의 .tif 파일에서 numpy 배열로 데이터를 읽고 배열의 값을 다시 클래스 화 한 다음 다시 .tif에 씁니다.

당신의 설명에서, 당신이 유효한 파일을 작성하는 데 성공한 것 같지만 QGIS에서 상징화하면됩니다. 올바르게 기억한다면 처음 래스터를 추가 할 때 기존 색상 맵이없는 경우 종종 하나의 색상이 모두 표시됩니다.

import numpy, sys
from osgeo import gdal
from osgeo.gdalconst import *


# register all of the GDAL drivers
gdal.AllRegister()

# open the image
inDs = gdal.Open("c:/workshop/examples/raster_reclass/data/cropland_40.tif")
if inDs is None:
  print 'Could not open image file'
  sys.exit(1)

# read in the crop data and get info about it
band1 = inDs.GetRasterBand(1)
rows = inDs.RasterYSize
cols = inDs.RasterXSize

cropData = band1.ReadAsArray(0,0,cols,rows)

listAg = [1,5,6,22,23,24,41,42,28,37]
listNotAg = [111,195,141,181,121,122,190,62]

# create the output image
driver = inDs.GetDriver()
#print driver
outDs = driver.Create("c:/workshop/examples/raster_reclass/output/reclass_40.tif", cols, rows, 1, GDT_Int32)
if outDs is None:
    print 'Could not create reclass_40.tif'
    sys.exit(1)

outBand = outDs.GetRasterBand(1)
outData = numpy.zeros((rows,cols), numpy.int16)


for i in range(0, rows):
    for j in range(0, cols):

    if cropData[i,j] in listAg:
        outData[i,j] = 100
    elif cropData[i,j] in listNotAg:
        outData[i,j] = -100
    else:
        outData[i,j] = 0


# write the data
outBand.WriteArray(outData, 0, 0)

# flush data to disk, set the NoData value and calculate stats
outBand.FlushCache()
outBand.SetNoDataValue(-99)

# georeference the image and set the projection
outDs.SetGeoTransform(inDs.GetGeoTransform())
outDs.SetProjection(inDs.GetProjection())

del outData

1
플러싱 +1-물건을 '저장'하는 방법을 알아 내려고 벽에 머리를 부딪쳤다!
badgley

outDs = None저장하기 위해 추가 해야했습니다
JaakL

23

나는이 토론에서 얻은이 솔루션에 마침내 도달했습니다 ( http://osgeo-org.1560.n6.nabble.com/gdal-dev-numpy-array-to-raster-td4354924.html ). 나는 numpy 배열에서 tif 래스터 파일로 바로 갈 수 있기 때문에 좋아합니다. 솔루션을 개선 할 수있는 의견에 매우 감사드립니다. 다른 사람이 비슷한 답변을 검색 할 수 있도록 여기에 게시하겠습니다.

import numpy as np
from osgeo import gdal
from osgeo import gdal_array
from osgeo import osr
import matplotlib.pylab as plt

array = np.array(( (0.1, 0.2, 0.3, 0.4),
                   (0.2, 0.3, 0.4, 0.5),
                   (0.3, 0.4, 0.5, 0.6),
                   (0.4, 0.5, 0.6, 0.7),
                   (0.5, 0.6, 0.7, 0.8) ))
# My image array      
lat = np.array(( (10.0, 10.0, 10.0, 10.0),
                 ( 9.5,  9.5,  9.5,  9.5),
                 ( 9.0,  9.0,  9.0,  9.0),
                 ( 8.5,  8.5,  8.5,  8.5),
                 ( 8.0,  8.0,  8.0,  8.0) ))
lon = np.array(( (20.0, 20.5, 21.0, 21.5),
                 (20.0, 20.5, 21.0, 21.5),
                 (20.0, 20.5, 21.0, 21.5),
                 (20.0, 20.5, 21.0, 21.5),
                 (20.0, 20.5, 21.0, 21.5) ))
# For each pixel I know it's latitude and longitude.
# As you'll see below you only really need the coordinates of
# one corner, and the resolution of the file.

xmin,ymin,xmax,ymax = [lon.min(),lat.min(),lon.max(),lat.max()]
nrows,ncols = np.shape(array)
xres = (xmax-xmin)/float(ncols)
yres = (ymax-ymin)/float(nrows)
geotransform=(xmin,xres,0,ymax,0, -yres)   
# That's (top left x, w-e pixel resolution, rotation (0 if North is up), 
#         top left y, rotation (0 if North is up), n-s pixel resolution)
# I don't know why rotation is in twice???

output_raster = gdal.GetDriverByName('GTiff').Create('myraster.tif',ncols, nrows, 1 ,gdal.GDT_Float32)  # Open the file
output_raster.SetGeoTransform(geotransform)  # Specify its coordinates
srs = osr.SpatialReference()                 # Establish its coordinate encoding
srs.ImportFromEPSG(4326)                     # This one specifies WGS84 lat long.
                                             # Anyone know how to specify the 
                                             # IAU2000:49900 Mars encoding?
output_raster.SetProjection( srs.ExportToWkt() )   # Exports the coordinate system 
                                                   # to the file
output_raster.GetRasterBand(1).WriteArray(array)   # Writes my array to the raster

output_raster.FlushCache()

3
"회전은 두 번이다"는 x에 y의 회전 된 비트와 y에 x의 회전 된 비트의 영향을 설명합니다. "rotation"매개 변수 사이의 상호 관계를 설명하는 list.osgeo.org/pipermail/gdal-dev/2011-July/029449.html 을 참조하십시오 .
Dave X

이 게시물은 정말 유용합니다. 감사합니다. 그러나 필자의 경우 ArcGIS 외부의 이미지로 열면 완전히 검은 색인 tif 파일이 나타납니다. 내 공간 참조는 영국 내셔널 그리드 (EPSG = 27700)이며 단위는 미터입니다.
FaCoffee

여기에 질문을 게시했습니다 : gis.stackexchange.com/questions/232301/…
FaCoffee

IAU2000 : 49900 Mars 인코딩을 설정하는 방법을 찾았습니까?
K.-Michael Aye

4

공식 GDAL / OGR Cookbook for Python 에도 훌륭한 솔루션 이 있습니다 .

이 레시피는 배열에서 래스터를 만듭니다

import gdal, ogr, os, osr
import numpy as np


def array2raster(newRasterfn,rasterOrigin,pixelWidth,pixelHeight,array):

    cols = array.shape[1]
    rows = array.shape[0]
    originX = rasterOrigin[0]
    originY = rasterOrigin[1]

    driver = gdal.GetDriverByName('GTiff')
    outRaster = driver.Create(newRasterfn, cols, rows, 1, gdal.GDT_Byte)
    outRaster.SetGeoTransform((originX, pixelWidth, 0, originY, 0, pixelHeight))
    outband = outRaster.GetRasterBand(1)
    outband.WriteArray(array)
    outRasterSRS = osr.SpatialReference()
    outRasterSRS.ImportFromEPSG(4326)
    outRaster.SetProjection(outRasterSRS.ExportToWkt())
    outband.FlushCache()


def main(newRasterfn,rasterOrigin,pixelWidth,pixelHeight,array):
    reversed_arr = array[::-1] # reverse array so the tif looks like the array
    array2raster(newRasterfn,rasterOrigin,pixelWidth,pixelHeight,reversed_arr) # convert array to raster


if __name__ == "__main__":
    rasterOrigin = (-123.25745,45.43013)
    pixelWidth = 10
    pixelHeight = 10
    newRasterfn = 'test.tif'
    array = np.array([[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                      [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                      [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1],
                      [ 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1],
                      [ 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1],
                      [ 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1],
                      [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1],
                      [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                      [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                      [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])


    main(newRasterfn,rasterOrigin,pixelWidth,pixelHeight,array)

이 레시피는 좋지만 최종 tiff 파일에 문제가 있습니다. 픽셀의 위도 값이 올바르지 않습니다.
Shubham_geo

ESRI WKT와 OGC WKT간에 이상한 비 호환성이 나타날 수 있습니다. gis.stackexchange.com/questions/129764/…
Adam Erickson

내가 만난 한 가지는, 당신이 언급 한 방식으로 배열을 래스터로 쉽게 바꿀 것입니다. 그러나 gdal_translate을 사용하여 왼쪽 상단과 오른쪽 하단이 조정 된이 래스터를 지리 참조해야합니다. 이를 수행하는 한 가지 방법은 다음 두 단계를 따르는 것입니다. 1) 먼저 gdalinfo를 통해 왼쪽 상단 및 오른쪽 하단 위도 값을 찾으십시오. 2) 그런 다음 gdal_translate를 통해 geotiff를 사용하십시오 (위에서 언급 한 배열을 래스터로 변환하는 방법으로 생성 됨) 왼쪽 상단 및 오른쪽 하단 위도 좌표로 지리 참조하십시오.
Shubham_geo

0

다른 답변에서 제안 된 접근 방식의 대안은 rasterio패키지 를 사용하는 것 입니다. 나는 이것을 사용하여 생성하는 데 문제가 있었고이 사이트 가 유용하다는 gdal것을 알았습니다 .

이 파일과 동일한 해상도와 범위 를 가진 다른 tif 파일 ( other_file.tif)과 numpy 배열 ( numpy_array)이 있다고 가정하면 이것은 나를 위해 일한 접근법입니다.

import rasterio as rio    

with rio.open('other_file.tif') as src:
    ras_data = src.read()
    ras_meta = src.profile

# make any necessary changes to raster properties, e.g.:
ras_meta['dtype'] = "int32"
ras_meta['nodata'] = -99

with rio.open('outname.tif', 'w', **ras_meta) as dst:
    dst.write(numpy_array, 1)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.