Tải đầy đủ raster vào một mảng numpy?


26

Tôi đã cố gắng kiểm tra các bộ lọc của mình trên DEM raster để nhận dạng mẫu và nó luôn dẫn đến thiếu các hàng và cột cuối cùng (như..20) . Tôi đã thử với thư viện PIL, tải hình ảnh. Sau đó với numpy. Đầu ra là như nhau.

Tôi nghĩ, có điều gì đó không ổn với các vòng lặp của tôi, khi kiểm tra các giá trị trong mảng (chỉ chọn các pixel bằng Nhận dạng trong ArcCatalog) tôi nhận ra rằng các giá trị pixel không được tải vào một mảng.

Vì vậy, chỉ cần mở, đưa vào mảng và lưu hình ảnh từ mảng:

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

Kết quả trong việc cắt đi các hàng và cột cuối cùng. Xin lỗi, không thể đăng hình ảnh

Bất cứ ai cũng có thể giúp để hiểu tại sao? Và tư vấn giải pháp nào?

CHỈNH SỬA:

Vì vậy, tôi đã thành công trong việc tải các trình quét nhỏ vào mảng gọn gàng với sự giúp đỡ của các chàng trai, nhưng khi có một hình ảnh lớn hơn, tôi bắt đầu gặp lỗi. Tôi cho rằng đó là về các giới hạn của mảng numpy, và vì vậy mảng được tự động định hình lại hoặc smth như thế ... Vì vậy, ví dụ:

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

Vấn đề là tôi không muốn đọc từng khối vì tôi cần lọc, nhiều lần với các bộ lọc khác nhau, kích cỡ khác nhau .. Có công việc nào xung quanh không hoặc tôi phải học cách phát xạ theo khối: O

Câu trả lời:


42

nếu bạn có các ràng buộc python-gdal:

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

Và bạn đã hoàn thành:

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)

Vâng, với gdal Tôi đoán rằng tôi không gặp vấn đề gì, nhưng tôi đang cố gắng sử dụng ít thư viện hơn ... Và numpy dường như rất phổ biến cho điều đó 'trong khi googling'. Bất kỳ ý tưởng, thực sự, tại sao numpy / PIL ngừng tải ???
najuste

Tôi không biết. PIL phải đủ mạnh để nó được vận chuyển bằng trăn. Nhưng imho geotiff không chỉ là hình ảnh - ví dụ, chúng mang rất nhiều siêu dữ liệu - và PIL không phải (lại là imho) công cụ phù hợp.
biệt danh

Đôi khi tôi chỉ ghét những yêu cầu khác nhau về dấu ngoặc kép và dấu gạch chéo, khi mở dữ liệu .. Nhưng còn việc viết mảng numpy trở lại Raster thì sao? Nó hoạt động với thư viện PIL, nhưng sử dụng outputRaster.GetRasterBand (1) .WriteArray (myarray) tạo ra raster không hợp lệ ..
najuste

đừng quên để dữ liệu vào đĩa, với outBand.FlushCache (). Bạn có thể tìm thấy một số hướng dẫn tại đây: gis.usu.edu/~chrisg/python/2009
biệt danh

1
Kiểm tra " lists.osgeo.org/pipermail/gdal-dev/2010-Janemony/023309.html "- có vẻ như bạn đã hết hoặc ram.
biệt danh

21

Bạn có thể sử dụng rasterio để giao diện với các mảng NumPy. Để đọc một raster đến một mảng:

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]

Điều này sẽ đọc mọi thứ thành một mảng numpy 3D arr, với kích thước [band, row, col].


Dưới đây là một ví dụ nâng cao để đọc, chỉnh sửa pixel, sau đó lưu lại vào 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)

Các raster sẽ được viết và đóng vào cuối câu lệnh "với" .


Tại sao chúng ta không thể thấy tất cả các giá trị khi tôi viết print (mảng). Nó tách biệt các giá trị với điều này ..., ...,?
Mustafa Uçar

@ MustafaUçar đây là cách NumPy in các mảng mà bạn có thể sửa đổi . Hoặc cắt một cửa sổ của mảng để in, trong số nhiều thủ thuật Numpy khác.
Mike T

Một câu hỏi chung. Nếu tôi muốn xuất một mảng duy nhất có nhiều cảnh, là bốn chiều như (cảnh, chiều cao, chiều rộng, dải), tôi nên sửa đổi đoạn mã này như thế nào?
Ricardo Barros Lourenço

@ RicardoBarrosLourenço Tôi đoán kích thước thứ tư của bạn (cảnh?) Được lưu trữ trong mỗi tệp. Trước tiên tôi sẽ điền vào một mảng numpy 4D trống, sau đó lặp qua từng tệp (cảnh) và chèn phần 3D của mỗi tệp. Bạn có thể cần arr.transpose((1, 2, 0))lấy (chiều cao, chiều rộng, băng tần) từ mỗi tệp.
Mike T

@MikeT dân số này sẽ như np.append()thế nào?
Ricardo Barros Lourenço

3

Cấp cho tôi đang đọc một hình ảnh png cũ đơn giản, nhưng điều này hoạt động bằng cách sử dụng scipy ( imsavemặc dù sử dụng 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 kết quả của tôi cũng là 81 x 90 pixel.


Cảm ơn, nhưng tôi đang cố gắng sử dụng ít thư viện hơn .. Và bây giờ tôi có thể tạo nó với gdal + numpy ... (hy vọng không có PIL).
najuste

1
@najuste Hệ điều hành nào trên? Mac và hầu hết các hương vị Linux đi kèm scipynumpy.
Chad Cooper

Rõ ràng ... Tôi đang ở trên Windows, các phiên bản khác nhau của Win. : /
najuste

2

Giải pháp của tôi sử dụng gdal trông như thế này. Tôi nghĩ rằng nó rất có thể tái sử dụng.

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

tôi đang sử dụng một hình ảnh siêu phổ với 158 băng tần. Tôi muốn tính toán raster. nhưng tôi hiểu

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)

đối với print(data1)tôi chỉ có một số "1", nhưng giá trị thực là một số float

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

Giá trị pixel 0,139200

Xin vui lòng giúp đỡ để tìm ra sai lầm

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.