copper 53bd8c22e9 add history
change table layer
2022-11-10 14:23:31 +08:00

187 lines
7.0 KiB
Python

from rscder.utils.geomath import geo2imageRC, imageRC2geo
from rscder.utils.project import Project, PairLayer
from rscder.utils.icons import IconInstance
from misc import Register, AlgFrontend
from osgeo import gdal
import os
import math
import numpy as np
from PyQt5.QtGui import QIntValidator
from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QLineEdit, QHBoxLayout, QVBoxLayout
from . import VEG_CD
@VEG_CD.register
class VFCCD(AlgFrontend):
@staticmethod
def get_name():
return '植被覆盖度变化'
@staticmethod
def get_icon():
return IconInstance().ARITHMETIC2
@staticmethod
def get_widget(parent=None):
widget = QWidget(parent)
layout = QVBoxLayout()
redlabel = QLabel('红波段:')
redinput = QLineEdit()
redinput.setValidator(QIntValidator(redinput))
redinput.setObjectName('redinput')
redlayout = QHBoxLayout()
redlayout.addWidget(redlabel)
redlayout.addWidget(redinput)
nirlabel = QLabel('近红外:')
nirinput = QLineEdit()
nirinput.setValidator(QIntValidator(0, 100, nirinput))
nirinput.setObjectName('nirinput')
nirlayout = QHBoxLayout()
nirlayout.addWidget(nirlabel)
nirlayout.addWidget(nirinput)
layout.addLayout(redlayout)
layout.addLayout(nirlayout)
widget.setLayout(layout)
return widget
@staticmethod
def get_params(widget:QWidget=None):
if widget is None:
return dict(nir=3, red=0)
redinput = widget.findChild(QLineEdit, 'redinput')
nirinput = widget.findChild(QLineEdit, 'nirinput')
if redinput is None or nirinput is None:
return dict(nir=3, red=0)
nir = int(nirinput.text())
red = int(redinput.text())
return dict(red=red, nir=nir)
@staticmethod
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer, red=0, nir=3, send_message = None,*args, **kargs):
ds1:gdal.Dataset=gdal.Open(pth1)
ds2:gdal.Dataset=gdal.Open(pth2)
if ds1.RasterCount <= 2:
if send_message is not None:
send_message.emit('至少包含两个波段')
return
if ds1.RasterCount < (max(red, nir) + 1):
if send_message is not None:
send_message.emit(f'{max(nir, red)}超过波段数量')
return
cell_size = layer_parent.cell_size
xsize = layer_parent.size[0]
ysize = layer_parent.size[1]
band = ds1.RasterCount
yblocks = ysize // cell_size[1]
driver = gdal.GetDriverByName('GTiff')
out_tif = os.path.join(Project().other_path, 'temp.tif')
out_ds = driver.Create(out_tif, xsize, ysize, 1, gdal.GDT_Float32)
geo=layer_parent.grid.geo
proj=layer_parent.grid.proj
out_ds.SetGeoTransform(geo)
out_ds.SetProjection(proj)
max_diff = 0
min_diff = math.inf
# print('xxxxxxxxx')
start1x,start1y=geo2imageRC(ds1.GetGeoTransform(),layer_parent.mask.xy[0],layer_parent.mask.xy[1])
end1x,end1y=geo2imageRC(ds1.GetGeoTransform(),layer_parent.mask.xy[2],layer_parent.mask.xy[3])
start2x,start2y=geo2imageRC(ds2.GetGeoTransform(),layer_parent.mask.xy[0],layer_parent.mask.xy[1])
end2x,end2y=geo2imageRC(ds2.GetGeoTransform(),layer_parent.mask.xy[2],layer_parent.mask.xy[3])
for j in range(yblocks + 1):#该改这里了
if send_message is not None:
send_message.emit(f'计算{j}/{yblocks}')
block_xy1 = (start1x, start1y+j * cell_size[1])
block_xy2 = (start2x,start2y+j*cell_size[1])
block_xy=(0,j * cell_size[1])
if block_xy1[1] > end1y or block_xy2[1] > end2y:
break
block_size=(xsize, cell_size[1])
block_size1 = (xsize, cell_size[1])
block_size2 = (xsize,cell_size[1])
if block_xy[1] + block_size[1] > ysize:
block_size = (xsize, ysize - block_xy[1])
if block_xy1[1] + block_size1[1] > end1y:
block_size1 = (xsize,end1y - block_xy1[1])
if block_xy2[1] + block_size2[1] > end2y:
block_size2 = (xsize, end2y - block_xy2[1])
if block_size1[0] * block_size1[1] == 0 or block_size2[0] * block_size2[1] == 0:
continue
block_data1 = ds1.ReadAsArray(*block_xy1, *block_size1)
block_data2 = ds2.ReadAsArray(*block_xy2, *block_size2)
ndvi1 = (block_data1[nir] - block_data1[red])/((block_data1[nir] + block_data1[red]) + 1e-6)
ndvi2 = (block_data2[nir] - block_data2[red])/((block_data2[nir] + block_data2[red]) + 1e-6)
ndvi1[ndvi1 < 0] = 0
ndvi1[ndvi1 > 1] = 1
ndvi2[ndvi2 > 1] = 1
ndvi2[ndvi2 < 0] = 0
# pdb.set_trace()
block_diff = ndvi1 - ndvi2
block_diff = block_diff.astype(np.float32)
block_diff = np.abs(block_diff)
min_diff = min(min_diff, block_diff[block_diff > 0].min())
max_diff = max(max_diff, block_diff[block_diff <= 1].max())
out_ds.GetRasterBand(1).WriteArray(block_diff, *block_xy)
if send_message is not None:
send_message.emit(f'完成{j}/{yblocks}')
del ds2
del ds1
out_ds.FlushCache()
del out_ds
if send_message is not None:
send_message.emit('归一化概率中...')
send_message.emit(f'max pixel {max_diff}')
send_message.emit(f'min pixel {min_diff}')
temp_in_ds = gdal.Open(out_tif)
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
out_normal_ds = driver.Create(out_normal_tif, xsize, ysize, 1, gdal.GDT_Byte)
out_normal_ds.SetGeoTransform(geo)
out_normal_ds.SetProjection(proj)
# hist = np.zeros(256, dtype=np.int32)
for j in range(yblocks+1):
block_xy = (0, j * cell_size[1])
if block_xy[1] > ysize:
break
block_size = (xsize, cell_size[1])
if block_xy[1] + block_size[1] > ysize:
block_size = (xsize, ysize - block_xy[1])
block_data = temp_in_ds.ReadAsArray(*block_xy, *block_size)
block_data = (block_data - min_diff) / (max_diff - min_diff) * 255
block_data = block_data.astype(np.uint8)
out_normal_ds.GetRasterBand(1).WriteArray(block_data, *block_xy)
# hist_t, _ = np.histogram(block_data, bins=256, range=(0, 256))
# hist += hist_t
# print(hist)
del temp_in_ds
del out_normal_ds
try:
os.remove(out_tif)
except:
pass
if send_message is not None:
send_message.emit('差分法计算完成')
return out_normal_tif