Полностью загрузить растр в массив Numpy?

26

Я пытался проверить мои фильтры на растре DEM для распознавания образов, и это всегда приводит к отсутствию последних строк и столбцов (например, 20) . Я пытался с библиотекой PIL, загрузка изображения. Тогда с NumPy. Выход такой же.

Я подумал, что что-то не так с моими циклами, при проверке значений в массиве (просто выбирая пиксели с помощью Identification в ArcCatalog) я понял, что значения пикселей не загружаются в массив.

Итак, просто открываем, помещаем в массив и сохраняем изображение из массива:

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

Результатом является вырезание последних строк и столбцов. Извините, не могу опубликовать изображение

Кто-нибудь может помочь понять, почему? И посоветуете какое-нибудь решение?

РЕДАКТИРОВАТЬ:

Итак, мне удалось загрузить небольшие растры в массив с помощью парней, но при увеличении изображения я начинаю получать ошибки. Я предполагаю, что речь идет о пределах ограниченного массива, поэтому массив автоматически преобразуется или что-то в этом роде ... Итак, 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

Дело в том, что я не хочу читать блок за блоком, так как мне нужна фильтрация, несколько раз с разными фильтрами, с разными размерами. Есть ли обходной путь или я должен научиться бродить по блокам: O

najuste
источник

Ответы:

42

если у вас есть привязки python-gdal:

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

И вы сделали:

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
источник
Да, с gdal, я думаю, у меня не было проблем, но я пытаюсь использовать как можно меньше библиотек ... И numpy выглядел настолько популярным для этого, «в то время как поиск в Google». Любая идея, действительно, почему numpy / PIL перестает загружаться ???
najuste
Я не знаю. PIL должен быть достаточно надежным, чтобы поставляться с питоном. Но imho geotiff - это больше, чем изображения - например, они содержат много метаданных - и PIL (опять же imho) не является подходящим инструментом.
nickves
Я просто иногда ненавижу эти требования к разным цитатам и слешам при открытии данных. Но как насчет записи массива обратно в Raster? Он работает с библиотекой PIL, но использование outputRaster.GetRasterBand (1) .WriteArray (myarray) создает недопустимый растр ..
najuste
не забудьте сбросить данные на диск с помощью outBand.FlushCache (). Вы можете найти некоторые учебные пособия здесь: gis.usu.edu/~chrisg/python/2009
nickves
1
Проверьте " lists.osgeo.org/pipermail/gdal-dev/2010-January/023309.html " - кажется, что вы закончили или баран.
nickves
21

Вы можете использовать растерио для взаимодействия с массивами NumPy. Чтобы прочитать растр в массив:

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]

Это будет читать все в трехмерный массив arrс размерами [band, row, col].


Вот расширенный пример для чтения, редактирования пикселя и его сохранения в растре:

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)

Растр будет записан и закрыт в конце оператора with .

Майк Т
источник
Почему мы не видим все значения, когда пишу print (arr). Это разделяет значения с этим ..., ...,?
Мустафа Учар
@ MustafaUçar - так NumPy печатает массивы, которые вы можете изменять . Или нарезать окно массива для печати, среди многих других приемов Numpy.
Майк Т
Общий вопрос. Если я хочу вывести один массив с несколькими сценами, имеющими четыре измерения, такие как (сцена, высота, ширина, полосы), как мне изменить этот фрагмент?
Рикардо Баррос Лоуренсо
@ RicardoBarrosLourenço Я предполагаю, что ваше четвертое измерение (сцена?) Хранится в каждом файле. Сначала я заполнил пустой массив 4D, затем перебрал бы каждый файл (сцену) и вставил трехмерную часть каждого. Вам может понадобиться arr.transpose((1, 2, 0))получить (высота, ширина, полосы) из каждого файла.
Майк Т
@MikeT это население будет таким как np.append()?
Рикардо Баррос Лоуренсо
3

Конечно, я читаю простое старое изображение png, но это работает с использованием scipy ( imsaveхотя использует 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)

Мой результирующий PNG также 81 х 90 пикселей.

Чед Купер
источник
Спасибо, но я пытаюсь использовать как можно меньше библиотек .. А пока я могу сделать это с помощью gdal + numpy ... (надеюсь, без PIL).
najuste
1
@najuste Какая ОС работает? Mac и большинство версий Linux поставляются с scipyи numpy.
Чед Купер
Видимо ... У меня на Windows разные версии Win. : /
najuste
2

Мое решение с использованием gdal выглядит следующим образом. Я думаю, что это очень многоразово.

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
источник
0

Я использую гиперспектральное изображение с 158 полосами. Я хочу рассчитать растр. но я получаю

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)

для print(data1)я получил только некоторые "1", но реальные значения являются некоторые поплавки

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

Значение пикселя 0,139200

Плз помогите найти ошибку

Кайс Тоунси
источник