求大影像的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)