W pełni załaduj raster do tablicy numpy?

26

Próbowałem sprawdzić filtry w rastrze DEM pod kątem rozpoznawania wzorców i zawsze powoduje to brak ostatnich wierszy i kolumn (np ...20) . Próbowałem z biblioteką PIL, ładowanie obrazu. Następnie z numpy. Dane wyjściowe są takie same.

Myślałem, że coś jest nie tak z moimi pętlami, podczas sprawdzania wartości w tablicy (tylko wybieranie pikseli z Identyfikacja w ArcCatalog) zdałem sobie sprawę, że wartości pikseli nie zostały załadowane do tablicy.

Wystarczy po prostu otworzyć, włożyć do tablicy i zapisać obraz z tablicy:

a=numpy.array(Image.open(inraster)) #raster is .tif Float32, size 561x253
newIm=Image.new(Im.mode, Im.size)
Image.fromarray(a).save(outraster)

Powoduje odcięcie ostatnich wierszy i kolumn. Przepraszamy, nie można opublikować obrazu

Ktoś może pomóc zrozumieć, dlaczego? I doradzić jakieś rozwiązanie?

EDYTOWAĆ:

Tak więc udało mi się załadować małe rastry do tablicy numpy z pomocą facetów, ale kiedy mam większy obraz, zaczynam dostawać błędy. Przypuszczam, że dotyczy limitów tablicy numpy, więc tablica jest automatycznie przekształcana lub tak dalej ... Więc np .:

Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    ima=numpy.array(inDs.GetRasterBand(1).ReadAsArray())
  File "C:\Python25\lib\site-packages\osgeo\gdal.py", line 835, in ReadAsArray
    buf_xsize, buf_ysize, buf_obj )
  File "C:\Python25\lib\site-packages\osgeo\gdal_array.py", line 140, in BandReadAsArray
    ar = numpy.reshape(ar, [buf_ysize,buf_xsize])
  File "C:\Python25\lib\site-packages\numpy\core\fromnumeric.py", line 108, in reshape
    return reshape(newshape, order=order)
ValueError: total size of new array must be unchanged

Chodzi o to, że nie chcę czytać blok po bloku, ponieważ potrzebuję filtrowania, kilka razy z różnymi filtrami, różnymi rozmiarami .. Czy jest jakieś obejście lub muszę nauczyć się radowania według bloków: O

najuste
źródło

Odpowiedzi:

42

jeśli masz powiązania python-gdal:

import numpy as np
from osgeo import gdal
ds = gdal.Open("mypic.tif")
myarray = np.array(ds.GetRasterBand(1).ReadAsArray())

I jesteś skończony:

myarray.shape
(2610,4583)
myarray.size
11961630
myarray
array([[        nan,         nan,         nan, ...,  0.38068664,
     0.37952521,  0.14506227],
   [        nan,         nan,         nan, ...,  0.39791253,
            nan,         nan],
   [        nan,         nan,         nan, ...,         nan,
            nan,         nan],
   ..., 
   [ 0.33243281,  0.33221543,  0.33273876, ...,         nan,
            nan,         nan],
   [ 0.33308044,  0.3337177 ,  0.33416209, ...,         nan,
            nan,         nan],
   [ 0.09213851,  0.09242494,  0.09267616, ...,         nan,
            nan,         nan]], dtype=float32)
nickves
źródło
Tak, z gdalem chyba nie miałem problemu, ale staram się używać jako mniej bibliotek ... A numpy wydawało się tak popularne z tego powodu „podczas googlowania”. Jakiś pomysł, dlaczego numpy / PIL przestaje się ładować ???
najuste
Nie wiem PIL powinien być wystarczająco solidny, aby był dostarczany z pythonem. Ale geotiff imho to coś więcej niż obrazy - na przykład zawierają wiele metadanych - a PIL nie jest (ponownie imho) właściwym narzędziem.
nickves
Po prostu czasami nienawidzę tych wymagań dotyczących cytowania i ukośników podczas otwierania danych. Ale co z zapisaniem tablicy numpy z powrotem do Rastra? Działa z biblioteką PIL, ale przy użyciu outputRaster.GetRasterBand (1) .WriteArray (myarray) produkuje nieprawidłowy raster ..
najuste
nie zapomnij opróżnić danych na dysk za pomocą outBand.FlushCache (). Niektóre samouczki można znaleźć tutaj: gis.usu.edu/~chrisg/python/2009
nickves
1
Zaznacz „ lists.osgeo.org/pipermail/gdal-dev/2010-J January/023309.html ” - wygląda na to, że skończyłeś się lub RAM.
nickves
21

Możesz użyć rasterio do połączenia z tablicami NumPy. Aby odczytać raster do tablicy:

import rasterio

with rasterio.open('/path/to/raster.tif', 'r') as ds:
    arr = ds.read()  # read all raster values

print(arr.shape)  # this is a 3D numpy array, with dimensions [band, row, col]

Spowoduje to odczytanie wszystkiego do trójwymiarowej tablicy 3D arro wymiarach [band, row, col].


Oto zaawansowany przykład czytania, edytowania piksela, a następnie zapisywania go z powrotem do rastra:

with rasterio.open('/path/to/raster.tif', 'r+') as ds:
    arr = ds.read()  # read all raster values
    arr[0, 10, 20] = 3  # change a pixel value on band 1, row 11, column 21
    ds.write(arr)

Raster zostanie zapisany i zamknięty na końcu instrukcji „with” .

Mike T.
źródło
Dlaczego nie widzimy wszystkich wartości, kiedy piszę print (arr). Oddziela wartości tym ..., ...,?
Mustafa Uçar
@ MustafaUçar w ten sposób NumPy drukuje tablice, które można modyfikować . Lub wytnij okno tablicy do wydrukowania, wśród wielu innych sztuczek Numpy.
Mike T
Ogólne pytanie. Jeśli chcę wyprowadzić pojedynczą tablicę z wieloma scenami, składającymi się z czterech wymiarów, takich jak (scena, wysokość, szerokość, pasma), jak mam zmodyfikować ten fragment?
Ricardo Barros Lourenço,
@ RicardoBarrosLourenço Chyba czwarty wymiar (scena?) Jest zapisany w każdym pliku. Najpierw zapełnię pustą tablicę liczb 4D, następnie przejdę przez każdy plik (scenę) i wstawię część 3D każdego z nich. Konieczne może być arr.transpose((1, 2, 0))pobranie (wysokość, szerokość, pasma) z każdego pliku.
Mike T
@MikeT ta populacja byłaby taka jak np.append()?
Ricardo Barros Lourenço,
3

To prawda, że ​​czytam zwykły stary obraz png, ale działa to przy użyciu scipy ( imsaveużywa PIL):

>>> import scipy
>>> import numpy
>>> img = scipy.misc.imread("/home/chad/logo.png")
>>> img.shape
(81, 90, 4)
>>> array = numpy.array(img)
>>> len(array)
81
>>> scipy.misc.imsave('/home/chad/logo.png', array)

Mój wynikowy png to również 81 x 90 pikseli.

Chad Cooper
źródło
Dzięki, ale staram się używać jako mniej bibliotek ... A na razie mogę to zrobić za pomocą gdal + numpy ... (mam nadzieję, że bez PIL).
najuste
1
@najuste Na jakim systemie operacyjnym są? Mac i większość wersji Linuksa są dostarczane z scipyi numpy.
Chad Cooper
Najwyraźniej ... Jestem na Windowsie, różne wersje Win. : /
najuste
2

Moje rozwiązanie wykorzystujące gdal wygląda tak. Myślę, że jest bardzo wielokrotnego użytku.

import gdal
import osgeo.gdalnumeric as gdn

def img_to_array(input_file, dim_ordering="channels_last", dtype='float32'):
    file  = gdal.Open(input_file)
    bands = [file.GetRasterBand(i) for i in range(1, file.RasterCount + 1)]
    arr = np.array([gdn.BandReadAsArray(band) for band in bands]).astype(dtype)
    if dim_ordering=="channels_last":
        arr = np.transpose(arr, [1, 2, 0])  # Reorders dimensions, so that channels are last
    return arr
MonsterMax
źródło
0

Używam obrazu hiperspektralnego ze 158 pasmami. Chcę obliczyć raster. ale rozumiem

import gdal # Import GDAL library bindings
from osgeo.gdalnumeric import *
from osgeo.gdalconst import *
import pylab as plt
import numpy as np
import xlrd
# The file that we shall be using
# Needs to be on current directory
filename = ('C:/Users/KIFF/Desktop/These/data/Hyperion/10th_bandmathref')
outFile = ('C:/Users/KIFF/Desktop/These/data/Hyperion/Math')
XLS=('C:/Users/KIFF/Desktop/These/data/Coef/bcoef.xlsx')
wb = xlrd.open_workbook(XLS)
sheet = wb.sheet_by_index(0)
sheet.cell_value(0, 0)


g = gdal.Open(filename, GA_ReadOnly)

# g should now be a GDAL dataset, but if the file isn't found
# g will be none. Let's test this:
if g is None:
    print ("Problem opening file %s!" % filename)
else:
    print ("File %s opened fine" % filename )

#band_array = g.ReadAsArray()
#print(band_array)
print ("[ RASTER BAND COUNT ]: ", g.RasterCount)

for band in range( g.RasterCount ):
    print (band)
    band += 1
    outFile = ('C:/Users/KIFF/Desktop/These/data/Results/Temp/Math_1_sur_value'+str(band)+'.tiff')
    #print ("[ GETTING BAND ]: ", band )
    srcband = g.GetRasterBand(band)
    if srcband is None:
        continue
    data1 = BandReadAsArray(srcband).astype(np.float)
    print(data1)
   # for i in range(3,sheet.nrows):
    b=sheet.cell_value(band+2,1)
    #print(b)
    dataOut = (1/data1)
    driver = gdal.GetDriverByName("ENVI")
    dsOut = driver.Create(outFile, g.RasterXSize, g.RasterYSize, 1)
    CopyDatasetInfo(g,dsOut)
    bandOut=dsOut.GetRasterBand(1)
    BandWriteArray(bandOut, dataOut)

dla print(data1)mam tylko trochę „1”, ale rzeczywiste wartości to niektóre zmiennoprzecinkowe

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. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]]
2

Wartość w pikselach 0,139200

Proszę o pomoc w znalezieniu błędu

Kais Tounsi
źródło