Повністю завантажити растр у масивний рядок?


26

Я намагався перевірити свої фільтри на DEM- растрі на предмет розпізнавання шаблонів, і це завжди призводить до відсутності останніх рядків і стовпців (наприклад, 20) . Я спробував з бібліотекою PIL, завантаженням зображення. Потім з нумером. Вихід той самий.

Я подумав, що з моїми циклами щось не так, під час перевірки значень у масиві (лише підбір пікселів з ідентифікацією в 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)

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

Хто-небудь міг допомогти зрозуміти, чому? І порадити якесь рішення?

Редагувати:

Отже, мені вдалося завантажити маленькі растри в numpy масив за допомогою хлопців, але коли я маю більше зображення, я починаю отримувати помилки. Я припускаю, що мова йде про межі масиву numpy, і тому масив автоматично переробляється чи розмірується так ... Так наприклад:

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

Відповіді:


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)

Так, з gdal, мабуть, у мене не було проблем, але я намагаюся використовувати як меншу кількість бібліотек ... І numpy здався таким популярним для того, що "під час гуглінгу". Дійсно, будь-яка ідея, чому numpy / PIL припиняє завантажувати ???
найкраще

Не знаю. PIL повинен бути досить надійним, щоб його постачали з пітоном. Але imho geotiff - це більше, ніж зображення - вони, наприклад, несуть багато метаданих, і PIL не є (знову ж таки імхо) правильним інструментом.
ніки

Я просто інколи ненавиджу ці вимоги до різної котирування та косої риси, коли відкриваються дані. А як же записати нумерований масив назад до Raster? Він працює з бібліотекою PIL, але з використанням outputRaster.GetRasterBand (1) .WriteArray (MyArray) виробляє неприпустимий растр ..
najuste

не забудьте передати дані на диск, за допомогою outBand.FlushCache (). Ви можете знайти підручники тут: gis.usu.edu/~chrisg/python/2009
nickves

1
Поставте прапорець " liste.osgeo.org/pipermail/gdal-dev/2010-January/023309.html " - здається, ви закінчилися чи протаранили.
ники

21

Ви можете використовувати rasterio для взаємодії з 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)

Растр буде записаний і закритий в кінці висловлювання "з" .


Чому ми не можемо побачити всі значення, коли я пишу print (arr). Це розділяє значення за допомогою цього ..., ...,?
Мустафа Учар

@ MustafaUçar ось так NumPy друкує масиви, які ви можете змінювати . Або наріжте вікно масиву для друку серед багатьох інших хитрощів.
Майк Т

Загальне питання. Якщо я хочу вивести один масив з кількома сценами, що мають чотири розміри, такі як (сцена, висота, ширина, смуги), як я можу змінити цей фрагмент?
Рікардо Баррос Луренцо

@ RicardoBarrosLourenço Я здогадуюсь, що ваш четвертий вимір (сцена?) Зберігається у кожному файлі. Спочатку я заповнюю порожній 4D масивний масив, потім перебираю кожен файл (сцену) і вставляю 3D-частину кожного. Можливо, вам знадобиться 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).
Найсте

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

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

Plz допомогти знайти помилку

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.