NDVI

求大影像的NDVI

# -*- coding: utf-8 -*-
import os, sys, time
import numpy as np
from osgeo import ogr
from osgeo import gdal
from osgeo import gdal_array as ga

def stretch_n(bands, img_min, img_max, lower_percent=0, higher_percent=100):
    out = np.zeros_like(bands).astype(np.float32)
    a = img_min
    b = img_max
    c = np.percentile(bands[:, :], lower_percent)
    d = np.percentile(bands[:, :], higher_percent)
    t = a + (bands[:, :] - c) * (b - a) / (d - c)
    t[t < a] = a
    t[t > b] = b
    out[:, :] = t
    return out

def readTif(infile):
    dataset = gdal.Open(infile)
    if dataset == None:
        print(infile+"掩膜失败,文件无法打开")
        return
    
    im_data = dataset.ReadAsArray(0,0,1,1)
    if 'int8' in im_data.dtype.name:
        datatype = gdal.GDT_Byte
    elif 'int16' in im_data.dtype.name:
        datatype = gdal.GDT_UInt16
    else:
        datatype = gdal.GDT_Float32
    
    im_width = dataset.RasterXSize
    im_height = dataset.RasterYSize
    im_geotrans = dataset.GetGeoTransform()
    im_proj = dataset.GetProjection()

    band1 = dataset.GetRasterBand(1)
    band2 = dataset.GetRasterBand(2)
    band3 = dataset.GetRasterBand(3)
    band4 = dataset.GetRasterBand(4)
    r = band1.ReadAsArray(0,0,im_width,im_height).astype(np.float32)
    g = band2.ReadAsArray(0,0,im_width,im_height).astype(np.float32)
    b = band3.ReadAsArray(0,0,im_width,im_height).astype(np.float32)
    nir = band4.ReadAsArray(0,0,im_width,im_height).astype(np.float32)
    return im_geotrans, im_proj, r, g, b, nir, im_width, im_height

def ndvi(im_geotrans,im_proj, im_redBand, im_nirBand, im_width, im_height, outfile):
    driver = gdal.GetDriverByName("GTiff")
    dataset = driver.Create(outfile, im_width, im_height, 1, gdal.GDT_Int16)
    dataset.SetGeoTransform(im_geotrans)
    dataset.SetProjection(im_proj)
    ga.numpy.seterr(all = 'ignore')
    ndvi = ((im_nirBand - im_redBand) * 1.0)/((im_nirBand + im_redBand) * 1.0)
    ndvi = ndvi.astype(np.float32)
    img_min = 0
    img_max = 255
    ndvi = stretch_n(ndvi, img_min, img_max)
    ndvi = ndvi.astype(np.uint8)
    dataset.GetRasterBand(1).WriteArray(ndvi)
    dataset.GetRasterBand(1).SetNoDataValue(0)
    return ndvi

def read_img(filename):
    dataset=gdal.Open(filename)

    im_width = dataset.RasterXSize
    im_height = dataset.RasterYSize

    im_geotrans = dataset.GetGeoTransform()
    im_proj = dataset.GetProjection()
    im_data = dataset.ReadAsArray(0,0,im_width,im_height)

    del dataset 
    return im_proj,im_geotrans,im_width, im_height,im_data


def write_img(filename, im_proj, im_geotrans, im_data):
    if 'int8' in im_data.dtype.name:
        datatype = gdal.GDT_Byte
    elif 'int16' in im_data.dtype.name:
        datatype = gdal.GDT_UInt16
    else:
        datatype = gdal.GDT_Float32

    if len(im_data.shape) == 3:
        im_bands, im_height, im_width = im_data.shape
    else:
        im_bands, (im_height, im_width) = 1,im_data.shape 

    driver = gdal.GetDriverByName("GTiff")
    dataset = driver.Create(filename, im_width, im_height, im_bands, datatype)

    dataset.SetGeoTransform(im_geotrans)
    dataset.SetProjection(im_proj)

    if im_bands == 1:
        dataset.GetRasterBand(1).WriteArray(im_data)
    else:
        for i in range(im_bands):
            dataset.GetRasterBand(i+1).WriteArray(im_data[i])

    del dataset

def getTifSize(tif):
    dataSet = gdal.Open(tif)
    width = dataSet.RasterXSize
    height = dataSet.RasterYSize
    bands = dataSet.RasterCount
    geoTrans = dataSet.GetGeoTransform()
    proj = dataSet.GetProjection()
    return width,height,bands,geoTrans,proj


def partDivisionForBoundary(tif1,divisionSize,tempPath):
    width,height,bands,geoTrans,proj = getTifSize(tif1)
    partWidth = partHeight = divisionSize

    if width % partWidth > 0 :
        widthNum = width // partWidth + 1
    else:
        widthNum =  width // partWidth
    if height % partHeight > 0:
        heightNum = height // partHeight +1
    else:
        heightNum = height // partHeight

    realName = os.path.split(tif1)[1].split(".")[0]

    tif1 = gdal.Open(tif1)
    for i in range(heightNum):
        for j in range(widthNum):

            startX = partWidth * j
            startY = partHeight * i

            if startX+partWidth<= width and startY+partHeight<=height:
                realPartWidth = partWidth
                realPartHeight = partHeight
            elif startX + partWidth > width and startY+partHeight<=height:
                realPartWidth = width - startX
                realPartHeight = partHeight
            elif startX+partWidth <= width  and startY+partHeight > height:
                realPartWidth = partWidth
                realPartHeight = height - startY
            elif startX + partWidth > width and startY+partHeight > height:
                realPartWidth = width - startX
                realPartHeight = height - startY

            outName = realName + str(i)+str(j)+".tif"
            outPath = os.path.join(tempPath,outName)

            if not os.path.exists(outPath):

                driver = gdal.GetDriverByName("GTiff")
                outTif = driver.Create(outPath,realPartWidth,realPartHeight,1,gdal.GDT_Float32)
                outTif.SetGeoTransform(geoTrans)
                outTif.SetProjection(proj)
                data1 = tif1.ReadAsArray(startX,startY,realPartWidth,realPartHeight)
                print(data1.shape)
                ga.numpy.seterr(all = 'ignore')
                ndvi = ((data1[0] - data1[3]))/((data1[0] + data1[3] + 1.0) * 1.0)
                ndvi = ndvi.astype(np.float32)
                img_min = 0
                img_max = 255
                ndvi = stretch_n(ndvi, img_min, img_max)
                ndvi = ndvi.astype(np.uint8)
                ndvi = np.around(ndvi)
                outTif.GetRasterBand(1).WriteArray(ndvi)
                outTif.GetRasterBand(1).SetNoDataValue(0)
    return 1

def partStretch(tif1,divisionSize,outStratchPath,tempPath):

    width,height,bands,geoTrans,proj = getTifSize(tif1)
    # bands = 1
    partWidth = partHeight = divisionSize

    if width % partWidth > 0 :
        widthNum = width // partWidth + 1
    else:
        widthNum =  width // partWidth
    if height % partHeight > 0:
        heightNum = height // partHeight +1
    else:
        heightNum = height // partHeight

    realName = os.path.split(tif1)[1].split(".")[0]

    driver = gdal.GetDriverByName("GTiff")
    outTif = driver.Create(outStratchPath,width,height,1,gdal.GDT_Byte)
    if outTif!= None:
        outTif.SetGeoTransform(geoTrans)
        outTif.SetProjection(proj)
    for i in range(heightNum):
        for j in range(widthNum):

            startX = partWidth * j
            startY = partHeight * i

            if startX+partWidth<= width and startY+partHeight<=height:
                realPartWidth = partWidth
                realPartHeight = partHeight
            elif startX + partWidth > width and startY+partHeight<=height:
                realPartWidth = width - startX
                realPartHeight = partHeight
            elif startX+partWidth <= width  and startY+partHeight > height:
                realPartWidth = partWidth
                realPartHeight = height - startY
            elif startX + partWidth > width and startY+partHeight > height:
                realPartWidth = width - startX
                realPartHeight = height - startY

            partTifName = realName+str(i)+str(j)+".tif"
            partTifPath = os.path.join(tempPath,partTifName)
            divisionImg = gdal.Open(partTifPath)
            for k in range(1):
                data1 = divisionImg.GetRasterBand(k+1).ReadAsArray(0,0,realPartWidth,realPartHeight)
                outPartBand = outTif.GetRasterBand(k+1)
                outPartBand.WriteArray(data1,startX,startY)

if __name__ == "__main__":
    tif_path = "E:/abg_data/mos1/abaga_old.TIF"
    temp_path = "E:/abg_data/mos1/temp/"
    result_path = "E:/abg_data/mos1/result/abaga_ndvi.tif"

    partDivisionForBoundary(tif_path,20000,temp_path)
    partStretch(tif_path,20000,result_path,temp_path)

猜你喜欢

转载自blog.csdn.net/qq_20373723/article/details/106372658