我无法阻止ReadAsArray()方法返回None。我不明白为什么,因为我用完全相同的方式编写了另一个脚本,但效果很好。

我想早点指出我确实启用了gdal.UseExceptions()。

这在搜索中似乎是一个常见的问题,但是我还没有找到能够使其工作的解决方案,很奇怪我在一个可以找到的现有脚本中执行了完全相同的操作。我在其他脚本中使用了此文件,因此我知道它没有损坏。同样,将另一个图像加载到其中也会导致相同的问题。

有人知道发生了什么吗?

这是当前的脚本:

import gdal
from gdal import Open, GetDriverByName

def qa_mask(in_qa_band, in_cols, in_rows, in_geotransform, mask_tiff):

    qa_np = in_qa_band.ReadAsArray(0, 0, in_cols, in_rows)
    print(qa_np)
    qa_np_str = qa_np.astype('str')

    mask = qa_np_str[(qa_np_str[0:2] == '10')] = -99

    geotiff = GetDriverByName('GTiff')

    output = geotiff.Create(mask_tiff, in_cols, in_rows, 1, gdal.GDT_Byte)
    output_band = output.GetRasterBand(1)
    output_band.WriteArray(mask)
    output.SetGeoTransform(in_geotransform)

    return None

gdal.UseExceptions()
tiff = Open(r'D:\landsat_data\20160710_landsat8qa_test\LC80410222016190LGN00_BQA.TIF')
band = tiff.GetRasterBand(1)

rows, cols, geotransform = tiff.RasterYSize, tiff.RasterXSize, tiff.GetGeoTransform()

qa_mask(band, rows, cols, geotransform, 'D:\landsat_data\20160710_landsat8qa_test\cloudmask.TIF')


我总是得到错误:

Traceback (most recent call last):
  File "D:/gis_image/landsat8qa_gdal.py", line 27, in <module>
    qa_mask(band, rows, cols, geotransform, 'D:\landsat_data\20160710_landsat8qa_test\cloudmask.TIF')
  File "D:/gis_image/landsat8qa_gdal.py", line 8, in qa_mask
    qa_np_str = qa_np.astype('str')
AttributeError: 'NoneType' object has no attribute 'astype'


但是,此脚本可以正常工作:

import numpy as np
from numpy import subtract, add, divide, multiply
import gdal
from gdal import GetDriverByName

def ndvi(in_nir_band, in_colour_band, in_rows, in_cols, in_geotransform, out_tiff, data_type=gdal.GDT_Float32):

    """
    Performs an NDVI calculation given two input bands, as well as other information that can be retrieved from the
    original image.
    @param in_nir_band A GDAL band object representing the near-infrared image data.
    @type in_nir_band GDALRasterBand
    @param in_colour_band A GDAL band object representing the colour image data.
    @type: in_colour_band GDALRasterBand
    @param in_rows The number of rows in both input bands.
    @type: in_rows int
    @param in_cols The number of columns in both input bands.
    @type: in_cols int
    @param in_geotransform The geographic transformation to be applied to the output image.
    @type in_geotransform Tuple (as returned by GetGeoTransform())
    @param out_tiff Path to the desired output .tif file.
    @type: out_tiff String (should end in ".tif")
    @param data_type Data type of output image.  Valid values are gdal.UInt16 and gdal.Float32.  Default is
                      gdal.Float32
    @type data_type GDALDataType
    @return None
    """

    # Read the input bands as numpy arrays.
    np_nir = in_nir_band.ReadAsArray(0, 0, in_cols, in_rows)
    np_colour = in_colour_band.ReadAsArray(0, 0, in_cols, in_rows)

    # Convert the np arrays to 32-bit floating point to make sure division will occur properly.
    np_nir_as32 = np_nir.astype(np.float32)
    np_colour_as32 = np_colour.astype(np.float32)

    # Calculate the NDVI formula.
    numerator = subtract(np_nir_as32, np_colour_as32)
    denominator = add(np_nir_as32, np_colour_as32)
    result = divide(numerator, denominator)

    # Remove any out-of-bounds areas
    result[result == -0] = -99

    # Initialize a geotiff driver.
    geotiff = GetDriverByName('GTiff')

    # If the desired output is an int16, map the domain [-1,1] to [0,255], create an int16 geotiff with one band and
    # write the contents of the int16 NDVI calculation to it.  Otherwise, create a float32 geotiff with one band and
    # write the contents of the float32 NDVI calculation to it.
    if data_type == gdal.GDT_UInt16:
        ndvi_int8 = multiply((result + 1), (2**7 - 1))
        output = geotiff.Create(out_tiff, in_cols, in_rows, 1, gdal.GDT_Byte)
        output_band = output.GetRasterBand(1)
        output_band.SetNoDataValue(-99)
        output_band.WriteArray(ndvi_int8)
    elif data_type == gdal.GDT_Float32:
        output = geotiff.Create(out_tiff, in_cols, in_rows, 1, gdal.GDT_Float32)
        output_band = output.GetRasterBand(1)
        output_band.SetNoDataValue(-99)
        output_band.WriteArray(result)
    else:
        raise ValueError('Invalid output data type.  Valid types are gdal.UInt16 or gdal.Float32.')

    # Set the geographic transformation as the input.
    output.SetGeoTransform(in_geotransform)

    return None

# Open NIR image and get its only band.
nir_tiff = Open(r'D:\landsat_data\20160621_fort_mac\nir.tif')
nir_band = nir_tiff.GetRasterBand(1)

# Open red image and get its only band.
red_tiff = Open(r'D:\landsat_data\20160621_fort_mac\red.tif')
red_band = red_tiff.GetRasterBand(1)

# Get the rows and cols from one of the images (both should always be the same)
rows, cols, geotransform = nir_tiff.RasterYSize, nir_tiff.RasterXSize, nir_tiff.GetGeoTransform()
#print(geotransform)

# Set an output for a 16-bit unsigned integer (0-255)
#out_tiff_int16 = r'NDVI_INT16.tif'

# Set the output for a 32-bit floating point (-1 to 1)
out_tiff_float32 = r'D:\landsat_data\20160621_fort_mac\out3.tif'

# Run the function for unsigned 16-bit integer
#ndvi(nir_band, red_band, rows, cols, geotransform, out_tiff_int16, gdal.GDT_UInt16)

# Run the function for 32-bit floating point
ndvi(nir_band, red_band, rows, cols, geotransform, out_tiff_float32, gdal.GDT_Float32)

print('done')


这两个脚本都接受栅格带作为输入,并尝试将它们读取为numpy数组

最佳答案

好吧,我不觉得傻...

该函数定义为:

def qa_mask(in_qa_band, in_cols, in_rows, in_geotransform, mask_tiff):


而我称它为:

qa_mask(band, rows, cols, geotransform, 'D:\landsat_data\20160710_landsat8qa_test\cloudmask.TIF')


因此,这里要吸取的教训是,显然GDAL不会告诉您交换行/列是否存在问题。它不会定义numpy数组...

关于python - GDAL ReadAsArray()不断返回None,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38425399/

10-15 02:58