Charger complètement le raster dans un tableau numpy?

26

J'ai essayé de vérifier mes filtres sur le raster DEM pour la reconnaissance des formes et il en résulte toujours des dernières lignes et colonnes manquantes (comme..20) . J'ai essayé avec la bibliothèque PIL, la charge d'image. Puis avec numpy. La sortie est la même.

Je pensais que quelque chose ne va pas avec mes boucles, lors de la vérification des valeurs dans le tableau (juste en sélectionnant les pixels avec Identification dans ArcCatalog), j'ai réalisé que les valeurs des pixels n'étaient pas chargées dans un tableau.

Donc, il suffit d'ouvrir, de mettre en tableau et d'enregistrer l'image à partir du tableau:

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

Résultats en supprimant les dernières lignes et colonnes. Désolé, je ne peux pas poster l'image

N'importe qui pourrait aider à comprendre pourquoi? Et conseiller une solution?

MODIFIER:

J'ai donc réussi à charger de petits rasters dans un tableau numpy avec l'aide de gars, mais lorsque j'ai une image plus grande, je commence à avoir des erreurs. Je suppose que cela concerne les limites du tableau numpy, et donc le tableau est automatiquement remodelé ou smth comme ça ... Donc ex:

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

Le fait est que je ne veux pas lire bloc par bloc car j'ai besoin de filtrage, plusieurs fois avec des filtres différents, des tailles différentes.

najuste
la source

Réponses:

42

si vous avez des liaisons python-gdal:

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

Et tu as fini:

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
la source
Ouais, avec gdal, je suppose que je n'ai pas eu de problème, mais j'essaie d'utiliser moins de bibliothèques ... Et numpy semblait si populaire pour ça 'pendant la recherche sur Google'. Une idée, en effet, pourquoi numpy / PIL arrête le chargement ???
najuste
Je ne sais pas. PIL devrait être suffisamment robuste pour être livré avec python. Mais le géotiff à mon humble avis est plus que des images - ils contiennent de nombreuses métadonnées par exemple - et PIL n'est pas (encore une fois à mon humble avis) le bon outil.
nickves
Je déteste parfois ces exigences de citation diff et de barre oblique, lors de l'ouverture des données .. Mais qu'en est-il de la réécriture du tableau numpy dans Raster? Il fonctionne avec la bibliothèque PIL, mais en utilisant outputRaster.GetRasterBand (1) .WriteArray (myarray) produit un raster invalide ..
najuste
n'oubliez pas de vider les données sur le disque, avec outBand.FlushCache (). Vous pouvez trouver des tutoriels ici: gis.usu.edu/~chrisg/python/2009
nickves
1
Vérifiez " lists.osgeo.org/pipermail/gdal-dev/2010-January/023309.html " - il semble que vous ayez manqué de mémoire ou que vous avez ramé .
nickves
21

Vous pouvez utiliser rasterio pour interfacer avec les tableaux NumPy. Pour lire un raster dans un tableau:

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]

Cela lira tout dans un tableau numpy 3D arr, avec des dimensions [band, row, col].


Voici un exemple avancé pour lire, modifier un pixel, puis l'enregistrer de nouveau dans le raster:

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)

Le raster sera écrit et fermé à la fin de l' instruction "with" .

Mike T
la source
Pourquoi ne pouvons-nous pas voir toutes les valeurs lorsque j'écris print (arr). Il sépare les valeurs de ceci ..., ...,?
Mustafa Uçar
@ MustafaUçar c'est ainsi que NumPy imprime les tableaux, que vous pouvez modifier . Ou découpez une fenêtre du tableau à imprimer, parmi de nombreuses autres astuces Numpy.
Mike T
Une question générale. Si je veux générer un seul tableau avec plusieurs scènes, ayant quatre dimensions telles que (scène, hauteur, largeur, bandes), comment dois-je modifier cet extrait?
Ricardo Barros Lourenço
@ RicardoBarrosLourenço Je suppose que votre quatrième dimension (scène?) Est stockée dans chaque fichier. Je voudrais d'abord remplir un tableau numpy 4D vide, puis parcourir chaque fichier (scène) et insérer la partie 3D de chacun. Vous devrez peut-être arr.transpose((1, 2, 0))obtenir (hauteur, largeur, bandes) de chaque fichier.
Mike T
@MikeT cette population serait telle que np.append()?
Ricardo Barros Lourenço
3

Certes, je lis une vieille image png simple, mais cela fonctionne en utilisant scipy ( imsaveutilise cependant 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)

Mon png résultant est également de 81 x 90 pixels.

Chad Cooper
la source
Merci, mais j'essaie d'utiliser moins de bibliothèques .. Et pour l'instant je peux le faire avec gdal + numpy ... (j'espère sans PIL).
najuste
1
@najuste Quels sont les systèmes d'exploitation? Mac et la plupart des versions Linux sont fournies avec scipyet numpy.
Chad Cooper
Apparemment ... je suis sous Windows, différentes versions de Win. : /
najuste
2

Ma solution en utilisant gdal ressemble à ceci. Je pense que c'est très réutilisable.

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
la source
0

j'utilise une image hyperspectrale avec 158 bandes. Je veux calculer le raster. mais je reçois

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)

pour le print(data1)je n'ai que quelques "1", mais les valeurs réelles sont des flotteurs

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

Valeur de pixel 0,139200

Aidez Plz à trouver l'erreur

Kais Tounsi
la source