Merge branch 'dev-pyramid'
This commit is contained in:
commit
7380f5d94a
3
ECD.py
3
ECD.py
@ -1,13 +1,10 @@
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'libs'))
|
||||
os.environ['PROJ_LIB'] = os.path.join(os.path.dirname(__file__), 'share/proj')
|
||||
os.environ['GDAL_DATA'] = os.path.join(os.path.dirname(__file__), 'share')
|
||||
os.environ['ECD_BASEDIR'] = os.path.dirname(__file__)
|
||||
BASE_DIR = os.path.dirname(__file__)
|
||||
import distutils
|
||||
import distutils.version
|
||||
from rscder import MulStart
|
||||
import logging
|
||||
|
||||
|
32
conda.yaml
32
conda.yaml
@ -4,62 +4,30 @@ channels:
|
||||
- defaults
|
||||
dependencies:
|
||||
- cryptography=3.4.7=py37h20c650d_0
|
||||
- curl=7.79.0=h789b8ee_0
|
||||
- cycler=0.10.0=py_2
|
||||
- cytoolz=0.11.0=py37hcc03f2d_3
|
||||
- dask-core=2021.9.1=pyhd8ed1ab_0
|
||||
- decorator=5.1.0=pyhd8ed1ab_0
|
||||
- future=0.18.2=py37h03978a9_3
|
||||
- gdal=3.3.1=py37hb11e9a8_2
|
||||
- geos=3.9.1=h39d44d4_2
|
||||
- geotiff=1.6.0=ha8a8a2d_6
|
||||
- gettext=0.19.8.1=ha2e2712_1006
|
||||
- giflib=5.2.1=h8d14728_2
|
||||
- gsl=2.7=hdfb1a43_0
|
||||
- m2w64-gcc-libgfortran=5.3.0=6
|
||||
- m2w64-gcc-libs=5.3.0=7
|
||||
- m2w64-gcc-libs-core=5.3.0=7
|
||||
- m2w64-gmp=6.1.0=2
|
||||
- m2w64-libwinpthread-git=5.0.0.4634.697f757=2
|
||||
- markupsafe=2.0.1=py37hcc03f2d_0
|
||||
- numpy=1.21.2=py37h940b05c_0
|
||||
- opencv=4.5.3=py37h03978a9_1
|
||||
- pip=21.2.4=pyhd8ed1ab_0
|
||||
- proj=8.0.1=h1cfcee9_0
|
||||
- psycopg2=2.9.1=py37hd8e9650_0
|
||||
- py-opencv=4.5.3=py37h4038f58_1
|
||||
- pycodestyle=2.7.0=pyhd8ed1ab_0
|
||||
- pycparser=2.20=pyh9f0ad1d_2
|
||||
- pygments=2.10.0=pyhd8ed1ab_0
|
||||
- pylint=2.11.1=pyhd8ed1ab_0
|
||||
- pyproj=3.2.1=py37h9f67652_0
|
||||
- pyqt=5.12.3=py37h03978a9_7
|
||||
- pysnooper=0.5.0=pyhd8ed1ab_0
|
||||
- pysocks=1.7.1=py37h03978a9_3
|
||||
- python=3.7.10=h7840368_101_cpython
|
||||
- python-dateutil=2.8.2=pyhd8ed1ab_0
|
||||
- python_abi=3.7=2_cp37m
|
||||
- pytz=2021.1=pyhd8ed1ab_0
|
||||
- pywavelets=1.1.1=py37hec80d1f_3
|
||||
- pywin32=301=py37hcc03f2d_0
|
||||
- pyyaml=5.4.1=py37hcc03f2d_1
|
||||
- qgis=3.18.3=py37h3dc7164_2
|
||||
- qt=5.12.9=h5909a2a_4
|
||||
- qtkeychain=0.12.0=h552f0f6_0
|
||||
- qtlocation=5.12.9=ha925a31_0
|
||||
- qtpy=1.11.1=pyhd8ed1ab_0
|
||||
- scikit-image=0.18.3=py37h9386db6_0
|
||||
- scipy=1.7.1=py37hb6553fb_0
|
||||
- setuptools=58.0.4=py37h03978a9_1
|
||||
- six=1.16.0=pyh6c4a22f_0
|
||||
- snappy=1.1.8=ha925a31_3
|
||||
- sqlite=3.36.0=h8ffe710_1
|
||||
- tenacity=8.0.1=pyhd8ed1ab_0
|
||||
- typed-ast=1.4.3=py37hcc03f2d_0
|
||||
- typing-extensions=3.10.0.2=hd8ed1ab_0
|
||||
- typing_extensions=3.10.0.2=pyha770c72_0
|
||||
- ucrt=10.0.20348.0=h57928b3_0
|
||||
- urllib3=1.26.6=pyhd8ed1ab_0
|
||||
- yaml=0.2.5=he774522_0
|
||||
- pip:
|
||||
- attrs==21.4.0
|
||||
|
@ -1 +1 @@
|
||||
IieXktda+1nRK9zLwe87uPPn2VpCwmUrEOPfyenaW/Sek70/CqqbCr7nangL1+pVXSkzDELia7Qq8e+pDMuHCXzxyJOALRj4j3bhFVExwqSTLuXwdev1e26nr7vnECl7H0SCVynr8To7ciwcnmK6HJXre6i+mBdTjACmKseTMlWp480XOt7uHysltORbTA3J
|
||||
vd4FiYncytyziGH9GNCAA8hGGr1/79Xmphtc5+PHPJDpxvqj1hP7+985QMojYO4M5Qn/aqEAvFgeDN3CA8x1YAK8SdCgSXSBJpRBK8wqPQjBY1ak96QfdPCrTLunr+xuPxK3Gxe772adTTsee2+ot7WePYUsC4y4NcS5+rlP1if87xtYqVeSwx3c64cOmAGP
|
@ -1 +1 @@
|
||||
pGZJMmJtule8fwDCz4mnyHoQa7N6pl5GRdLqfoXREBqG4Xb1jbvgf7RmC8f1+sNpiCFSIt7NgvU362tKhB5UBXn/vUAadG1lOGC70dUhprGzBoqJN7VkAHkNGg0XjoE8H0SCVynr8To7ciwcnmK6HJXre6i+mBdTjACmKseTMlWp480XOt7uHysltORbTA3J
|
||||
vd4FiYncytyziGH9GNCAA8hGGr1/79Xmphtc5+PHPJDpxvqj1hP7+985QMojYO4M5Qn/aqEAvFgeDN3CA8x1YAK8SdCgSXSBJpRBK8wqPQjBY1ak96QfdPCrTLunr+xuPxK3Gxe772adTTsee2+ot7WePYUsC4y4NcS5+rlP1if87xtYqVeSwx3c64cOmAGP
|
@ -1 +0,0 @@
|
||||
from In_one.main import *
|
@ -1,503 +0,0 @@
|
||||
from asyncio.windows_events import NULL
|
||||
from concurrent.futures import thread
|
||||
from email.policy import default
|
||||
import os
|
||||
import pdb
|
||||
from threading import Thread
|
||||
import numpy as np
|
||||
# from plugins.basic_change.main import MyDialog
|
||||
from rscder.gui.actions import ActionManager
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
from PyQt5.QtWidgets import QAction, QDialog, QHBoxLayout, QVBoxLayout, QPushButton,QWidget,QLabel,QLineEdit,QPushButton,QComboBox
|
||||
from PyQt5.QtGui import QIcon,QPixmap
|
||||
from PyQt5.QtCore import Qt
|
||||
from rscder.gui.layercombox import LayerCombox,PairLayerCombox
|
||||
from rscder.utils.icons import IconInstance
|
||||
from rscder.utils.project import Project, RasterLayer, SingleBandRasterLayer,ResultPointLayer
|
||||
from In_one.otsu import OTSU
|
||||
from osgeo import gdal
|
||||
from plugins.In_one import pic
|
||||
import math
|
||||
from skimage.filters import rank
|
||||
from skimage.morphology import disk, rectangle
|
||||
class LockerButton(QPushButton):
|
||||
def __init__(self,parent=NULL):
|
||||
super(LockerButton,self).__init__(parent)
|
||||
m_imageLabel = QLabel(self)
|
||||
m_imageLabel.setFixedWidth(20)
|
||||
m_imageLabel.setScaledContents(True)
|
||||
m_imageLabel.setStyleSheet("QLabel{background-color:transparent;}")
|
||||
m_textLabel = QLabel(self)
|
||||
m_textLabel.setStyleSheet("QLabel{background-color:transparent;}")
|
||||
self.m_imageLabel=m_imageLabel
|
||||
self.m_textLabel=m_textLabel
|
||||
self.hide_=1
|
||||
mainLayout = QHBoxLayout()
|
||||
|
||||
mainLayout.addWidget(self.m_imageLabel)
|
||||
mainLayout.addWidget(self.m_textLabel)
|
||||
mainLayout.setContentsMargins(0,0,0,0)
|
||||
mainLayout.setSpacing(0)
|
||||
self.setLayout(mainLayout)
|
||||
def SetImageLabel(self, pixmap:QPixmap):
|
||||
self.m_imageLabel.setPixmap(pixmap)
|
||||
def SetTextLabel(self, text):
|
||||
self.m_textLabel.setText(text)
|
||||
|
||||
class selectCombox(QComboBox):
|
||||
def __init__(self, parent,list:list,default='--') :
|
||||
super(selectCombox,self).__init__(parent)
|
||||
self.choose=None
|
||||
self.list=list
|
||||
self.default=default
|
||||
self.addItem(default, None)
|
||||
self.addItems(list)
|
||||
self.currentIndexChanged.connect(self.on_change)
|
||||
|
||||
def on_change(self,index):
|
||||
if index == 0:
|
||||
self.choose=self.default
|
||||
else:
|
||||
self.choose=self.list[index-1]
|
||||
# print(self.choose)
|
||||
|
||||
class AllInOne(QDialog):
|
||||
def __init__(self, pre,cd,threshold,parent=None):
|
||||
super(AllInOne, self).__init__(parent)
|
||||
self.setWindowTitle('变化检测')
|
||||
self.setWindowIcon(IconInstance().LOGO)
|
||||
self.pre=pre#['均值滤波','test滤波']
|
||||
self.cd=cd#['差分法','test法']
|
||||
self.threshold=threshold#['OTSU']
|
||||
self.initUI()
|
||||
|
||||
def initUI(self):
|
||||
#图层
|
||||
self.layer_combox = PairLayerCombox(self)
|
||||
layerbox = QHBoxLayout()
|
||||
layerbox.addWidget(self.layer_combox)
|
||||
|
||||
#预处理
|
||||
filterWeight=QWidget(self)
|
||||
filterlayout=QVBoxLayout()
|
||||
filerButton =LockerButton(filterWeight)
|
||||
filerButton.setObjectName("filerButton")
|
||||
filerButton.SetTextLabel("预处理")
|
||||
filerButton.SetImageLabel(QPixmap('plugins/In_one/pic/箭头_列表展开.png'))
|
||||
filerButton.setStyleSheet("#filerButton{background-color:transparent;border:none;}"
|
||||
"#filerButton:hover{background-color:rgba(195,195,195,0.4);border:none;}")
|
||||
self.pre_select=selectCombox(self,self.pre)
|
||||
|
||||
x_size_input = QLineEdit(self)
|
||||
x_size_input.setText('3')
|
||||
y_size_input = QLineEdit(self)
|
||||
y_size_input.setText('3')
|
||||
size_label = QLabel(self)
|
||||
size_label.setText('窗口大小:')
|
||||
time_label = QLabel(self)
|
||||
time_label.setText('X')
|
||||
self.x_size_input = x_size_input
|
||||
self.y_size_input = y_size_input
|
||||
hlayout1 = QHBoxLayout()
|
||||
hlayout1.addWidget(size_label)
|
||||
hlayout1.addWidget(x_size_input)
|
||||
hlayout1.addWidget(time_label)
|
||||
hlayout1.addWidget(y_size_input)
|
||||
vlayout = QVBoxLayout()
|
||||
vlayout.addWidget(self.pre_select)
|
||||
vlayout.addLayout(hlayout1)
|
||||
filterWeight.setLayout(vlayout)
|
||||
filterlayout.addWidget(filerButton)
|
||||
filterlayout.addWidget(filterWeight)
|
||||
#变化检测
|
||||
changelayout=QVBoxLayout()
|
||||
changeWeight=QWidget(self)
|
||||
changeButton =LockerButton(changeWeight)
|
||||
changeButton.setObjectName("changeButton")
|
||||
changeButton.SetTextLabel("变化检测")
|
||||
changeButton.SetImageLabel(QPixmap('plugins/In_one/pic/箭头_列表展开.png'))
|
||||
changeButton.setStyleSheet("#changeButton{background-color:transparent;border:none;}"
|
||||
"#changeButton:hover{background-color:rgba(195,195,195,0.4);border:none;}")
|
||||
changeWeightlayout=QVBoxLayout()
|
||||
self.cd_select=selectCombox(self,self.cd)
|
||||
changeWeightlayout.addWidget(self.cd_select)
|
||||
changeWeight.setLayout(changeWeightlayout)
|
||||
changelayout.addWidget(changeButton)
|
||||
changelayout.addWidget(changeWeight)
|
||||
|
||||
#阈值处理
|
||||
thresholdlayout=QVBoxLayout()
|
||||
thresholdWeight=QWidget(self)
|
||||
thresholdButton =LockerButton(thresholdWeight)
|
||||
thresholdButton.setObjectName("thresholdButton")
|
||||
thresholdButton.SetTextLabel("阈值处理")
|
||||
thresholdButton.SetImageLabel(QPixmap('plugins/In_one/pic/箭头_列表展开.png'))
|
||||
thresholdButton.setStyleSheet("#thresholdButton{background-color:transparent;border:none;}"
|
||||
"#thresholdButton:hover{background-color:rgba(195,195,195,0.4);border:none;}")
|
||||
self.threshold_select=selectCombox(self,self.threshold,default='手动阈值')
|
||||
self.threshold_input=QLineEdit(self)
|
||||
self.threshold_input.setText('0.5')
|
||||
self.threshold_select.currentIndexChanged.connect(lambda index:self.hide_(self.threshold_input,index==0))
|
||||
thresholdWeightlayout=QVBoxLayout()
|
||||
thresholdWeightlayout.addWidget(self.threshold_select)
|
||||
thresholdWeightlayout.addWidget(self.threshold_input)
|
||||
|
||||
thresholdWeight.setLayout(thresholdWeightlayout)
|
||||
thresholdlayout.addWidget(thresholdButton)
|
||||
thresholdlayout.addWidget(thresholdWeight)
|
||||
|
||||
#确认
|
||||
oklayout=QHBoxLayout()
|
||||
self.ok_button = QPushButton('确定', self)
|
||||
self.ok_button.setIcon(IconInstance().OK)
|
||||
self.ok_button.clicked.connect(self.accept)
|
||||
|
||||
self.cancel_button = QPushButton('取消', self)
|
||||
self.cancel_button.setIcon(IconInstance().CANCEL)
|
||||
self.cancel_button.clicked.connect(self.reject)
|
||||
oklayout.addWidget(self.ok_button)
|
||||
oklayout.addWidget(self.cancel_button)
|
||||
|
||||
totalvlayout=QVBoxLayout()
|
||||
totalvlayout.addLayout(layerbox)
|
||||
totalvlayout.addLayout(filterlayout)
|
||||
totalvlayout.addLayout(changelayout)
|
||||
totalvlayout.addLayout(thresholdlayout)
|
||||
totalvlayout.addLayout(oklayout)
|
||||
totalvlayout.addStretch()
|
||||
|
||||
self.setLayout(totalvlayout)
|
||||
|
||||
|
||||
filerButton.clicked.connect(lambda: self.hide(filerButton,filterWeight))
|
||||
changeButton.clicked.connect(lambda: self.hide(changeButton,changeWeight))
|
||||
thresholdButton.clicked.connect(lambda: self.hide(thresholdButton,thresholdWeight))
|
||||
|
||||
|
||||
|
||||
def hide(self,button:LockerButton,weight:QWidget):
|
||||
if ((button.hide_)%2)==1:
|
||||
weight.setVisible(False)
|
||||
button.SetImageLabel(QPixmap('plugins/In_one/pic/箭头_列表向右.png'))
|
||||
else:
|
||||
weight.setVisible(True)
|
||||
button.SetImageLabel(QPixmap('plugins/In_one/pic/箭头_列表展开.png'))
|
||||
button.hide_=(button.hide_)%2+1
|
||||
def hide_(self,widget:QWidget,h:bool):
|
||||
if h:
|
||||
widget.setVisible(True)
|
||||
else:
|
||||
widget.setVisible(False)
|
||||
def hideWidget(self,widget:QWidget):
|
||||
if widget.isVisible:
|
||||
widget.setVisible(False)
|
||||
else:
|
||||
widget.setVisible(True)
|
||||
class InOnePlugin(BasicPlugin):
|
||||
pre=['均值滤波']
|
||||
cd=['差分法']
|
||||
threshold=['OTSU阈值']
|
||||
|
||||
|
||||
@staticmethod
|
||||
def info():
|
||||
return {
|
||||
'name': 'AllinOne',
|
||||
'description': 'AllinOne',
|
||||
'author': 'RSCDER',
|
||||
'version': '1.0.0',
|
||||
}
|
||||
|
||||
def set_action(self):
|
||||
|
||||
basic_diff_method_in_one = QAction('差分法')
|
||||
# ActionManager().change_detection_menu.addAction(basic_diff_method_in_one)
|
||||
ActionManager().unsupervised_menu.addAction(basic_diff_method_in_one)
|
||||
self.basic_diff_method_in_one = basic_diff_method_in_one
|
||||
basic_diff_method_in_one.triggered.connect(self.run)
|
||||
|
||||
|
||||
def run(self):
|
||||
myDialog=AllInOne(self.pre,self.cd,self.threshold,self.mainwindow)
|
||||
myDialog.show()
|
||||
if myDialog.exec_()==QDialog.Accepted:
|
||||
t=Thread(target=self.run_alg,args=(myDialog,))
|
||||
t.start()
|
||||
|
||||
def run_alg(self,w:AllInOne):
|
||||
dict={}
|
||||
layer1=w.layer_combox.layer1
|
||||
layer2=w.layer_combox.layer2
|
||||
if not layer1.compare(layer2):
|
||||
self.send_message.emit('两个图层的尺寸不同')
|
||||
return
|
||||
pth1 = w.layer_combox.layer1.path
|
||||
pth2 = w.layer_combox.layer2.path
|
||||
name=layer1.layer_parent.name
|
||||
if w.pre_select.choose==self.pre[0]:
|
||||
|
||||
pth1=Meanfilter(w.x_size_input.text(),w.y_size_input.text(),w.layer_combox.layer1)
|
||||
self.send_message.emit('均值滤波图像{}'.format(w.layer_combox.layer1.name))
|
||||
pth2=Meanfilter(w.x_size_input.text(),w.y_size_input.text(),w.layer_combox.layer2)
|
||||
self.send_message.emit('均值滤波图像{}'.format(w.layer_combox.layer2.name))
|
||||
name=name+'_mean_filter'
|
||||
dict['预处理']=['均值滤波','|'.format(pth1,pth2)]
|
||||
else:
|
||||
pass
|
||||
|
||||
cdpth=None
|
||||
if w.cd_select.choose==self.cd[0]:
|
||||
cdpth=basic_cd(pth1,pth2,w.layer_combox.layer1.layer_parent,self.send_message)
|
||||
name += '_basic_cd'
|
||||
dict['变化检测算法']=['差分法',cdpth]
|
||||
else:
|
||||
pass
|
||||
|
||||
thpth=None
|
||||
if w.threshold_select.choose==self.threshold[0]:
|
||||
thpth,gap=otsu(cdpth,w.layer_combox.layer1.layer_parent.name,self.send_message)
|
||||
name+='_otsu'
|
||||
dict['后处理']=['OTSU阈值',gap,cdpth]
|
||||
elif w.threshold_select.choose=='手动阈值':
|
||||
thpth=thresh(cdpth,float(w.threshold_input.text()),w.layer_combox.layer1.layer_parent.name,self.send_message)
|
||||
dict['后处理']=['手动阈值',[float(w.threshold_input.text())],thpth]
|
||||
else:
|
||||
pass
|
||||
|
||||
table_layer(thpth,layer1,name,self.send_message,dict)
|
||||
|
||||
def Meanfilter(x_size,y_size,layer:RasterLayer):
|
||||
x_size = int(x_size)
|
||||
y_size = int(y_size)
|
||||
pth = layer.path
|
||||
if pth is None:
|
||||
return
|
||||
|
||||
ds = gdal.Open(pth)
|
||||
band_count = ds.RasterCount
|
||||
out_path = os.path.join(Project().other_path, '{}_mean_filter.tif'.format(layer.name))
|
||||
out_ds = gdal.GetDriverByName('GTiff').Create(out_path, ds.RasterXSize, ds.RasterYSize, band_count, ds.GetRasterBand(1).DataType)
|
||||
out_ds.SetProjection(ds.GetProjection())
|
||||
out_ds.SetGeoTransform(ds.GetGeoTransform())
|
||||
|
||||
for i in range(band_count):
|
||||
band = ds.GetRasterBand(i+1)
|
||||
data = band.ReadAsArray()
|
||||
|
||||
data = rank.mean(data, rectangle(y_size, x_size))
|
||||
|
||||
out_band = out_ds.GetRasterBand(i+1)
|
||||
out_band.WriteArray(data)
|
||||
|
||||
out_ds.FlushCache()
|
||||
del out_ds
|
||||
del ds
|
||||
return out_path
|
||||
|
||||
def basic_cd(pth1,pth2,layer_parent,send_message):
|
||||
|
||||
ds1 = gdal.Open(pth1)
|
||||
ds2 = gdal.Open(pth2)
|
||||
cell_size = layer_parent.cell_size
|
||||
xsize = ds1.RasterXSize
|
||||
ysize = ds1.RasterYSize
|
||||
band = ds1.RasterCount
|
||||
yblocks = ysize // cell_size[1]
|
||||
|
||||
driver = gdal.GetDriverByName('GTiff')
|
||||
out_tif = os.path.join(Project().cmi_path, 'temp.tif')
|
||||
out_ds = driver.Create(out_tif, xsize, ysize, 1, gdal.GDT_Float32)
|
||||
out_ds.SetGeoTransform(ds1.GetGeoTransform())
|
||||
out_ds.SetProjection(ds1.GetProjection())
|
||||
max_diff = 0
|
||||
min_diff = math.inf
|
||||
for j in range(yblocks + 1):
|
||||
|
||||
send_message.emit(f'计算{j}/{yblocks}')
|
||||
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_data1 = ds1.ReadAsArray(*block_xy, *block_size)
|
||||
block_data2 = ds2.ReadAsArray(*block_xy, *block_size)
|
||||
|
||||
if band == 1:
|
||||
block_data1 = block_data1[None, ...]
|
||||
block_data2 = block_data2[None, ...]
|
||||
# pdb.set_trace()
|
||||
block_diff = block_data1.sum(0) - block_data2.sum(0)
|
||||
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.max())
|
||||
out_ds.GetRasterBand(1).WriteArray(block_diff, *block_xy)
|
||||
|
||||
send_message.emit(f'完成{j}/{yblocks}')
|
||||
|
||||
out_ds.FlushCache()
|
||||
del out_ds
|
||||
send_message.emit('归一化概率中...')
|
||||
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(ds1.GetGeoTransform())
|
||||
out_normal_ds.SetProjection(ds1.GetProjection())
|
||||
# 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
|
||||
|
||||
# raster_result_layer = SingleBandRasterLayer(None, True, out_normal_tif, BasicLayer.BOATH_VIEW)
|
||||
|
||||
# layer1.layer_parent.add_result_layer(point_result_lalyer)
|
||||
# layer1.layer_parent.add_result_layer(raster_result_layer)
|
||||
|
||||
# self.send_message.emit('完成计算变化表格')
|
||||
|
||||
send_message.emit('差分法计算完成')
|
||||
return out_normal_tif
|
||||
|
||||
def otsu(pth,name,send_message):
|
||||
ds = gdal.Open(pth)
|
||||
band = ds.GetRasterBand(1)
|
||||
# band_count = ds.RasterCount
|
||||
|
||||
hist = np.zeros(256, dtype=np.int)
|
||||
xsize = ds.RasterXSize
|
||||
ysize = ds.RasterYSize
|
||||
|
||||
max_pixels = 1e7
|
||||
max_rows = max_pixels // xsize
|
||||
if max_rows < 1:
|
||||
max_rows = 1
|
||||
if max_rows > ysize:
|
||||
max_rows = ysize
|
||||
block_count = ysize // max_rows + 1
|
||||
for i in range(block_count):
|
||||
start_row = i * max_rows
|
||||
end_row = min((i + 1) * max_rows, ysize)
|
||||
block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
|
||||
hist += np.histogram(block.flatten(), bins=256, range=(0, 255))[0]
|
||||
hist = hist.astype(np.float32)
|
||||
gap = OTSU(hist)
|
||||
send_message.emit('阈值为:{}'.format(gap))
|
||||
|
||||
out_th = os.path.join(Project().bcdm_path, '{}_otsu_bcdm.tif'.format(name))
|
||||
out_ds = gdal.GetDriverByName('GTiff').Create(out_th, xsize, ysize, 1, gdal.GDT_Byte)
|
||||
out_ds.SetGeoTransform(ds.GetGeoTransform())
|
||||
out_ds.SetProjection(ds.GetProjection())
|
||||
out_band = out_ds.GetRasterBand(1)
|
||||
|
||||
for i in range(block_count):
|
||||
start_row = i * max_rows
|
||||
end_row = min((i + 1) * max_rows, ysize)
|
||||
block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
|
||||
out_band.WriteArray(block > gap, 0, start_row)
|
||||
out_band.FlushCache()
|
||||
out_ds = None
|
||||
ds = None
|
||||
send_message.emit('OTSU阈值完成')
|
||||
return out_th,gap
|
||||
#otsu_layer = SingleBandRasterLayer(path = out_th, style_info={})
|
||||
#layer.layer_parent.add_result_layer(otsu_layer)
|
||||
|
||||
def thresh(pth,gap,name,send_message):
|
||||
ds = gdal.Open(pth)
|
||||
band = ds.GetRasterBand(1)
|
||||
# band_count = ds.RasterCount
|
||||
|
||||
|
||||
xsize = ds.RasterXSize
|
||||
ysize = ds.RasterYSize
|
||||
|
||||
max_pixels = 1e7
|
||||
max_rows = max_pixels // xsize
|
||||
if max_rows < 1:
|
||||
max_rows = 1
|
||||
if max_rows > ysize:
|
||||
max_rows = ysize
|
||||
block_count = ysize // max_rows + 1
|
||||
# for i in range(block_count):
|
||||
# start_row = i * max_rows
|
||||
# end_row = min((i + 1) * max_rows, ysize)
|
||||
# block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
|
||||
# hist += np.histogram(block.flatten(), bins=256, range=(0, 255))[0]
|
||||
# hist = hist.astype(np.float32)
|
||||
send_message.emit('阈值为:{}'.format(gap))
|
||||
|
||||
out_th = os.path.join(Project().bcdm_path, '{}_thresh{}_bcdm.tif'.format(name,gap))
|
||||
out_ds = gdal.GetDriverByName('GTiff').Create(out_th, xsize, ysize, 1, gdal.GDT_Byte)
|
||||
out_ds.SetGeoTransform(ds.GetGeoTransform())
|
||||
out_ds.SetProjection(ds.GetProjection())
|
||||
out_band = out_ds.GetRasterBand(1)
|
||||
|
||||
for i in range(block_count):
|
||||
start_row = i * max_rows
|
||||
end_row = min((i + 1) * max_rows, ysize)
|
||||
block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
|
||||
out_band.WriteArray(block > gap, 0, start_row)
|
||||
out_band.FlushCache()
|
||||
out_ds = None
|
||||
ds = None
|
||||
send_message.emit('自定义阈值分割完成')
|
||||
return out_th
|
||||
#otsu_layer = SingleBandRasterLayer(path = out_th, style_info={})
|
||||
#layer.layer_parent.add_result_layer(otsu_layer)
|
||||
|
||||
def table_layer(pth,layer,name,send_message,dict):
|
||||
send_message.emit('正在计算表格结果...')
|
||||
cell_size = layer.layer_parent.cell_size
|
||||
ds = gdal.Open(pth)
|
||||
xsize = ds.RasterXSize
|
||||
ysize = ds.RasterYSize
|
||||
geo = ds.GetGeoTransform()
|
||||
|
||||
out_csv = os.path.join(Project().other_path, f'{name}_table_result.csv')
|
||||
yblocks = ysize // cell_size[1] + 1
|
||||
xblocks = xsize // cell_size[0] + 1
|
||||
with open(out_csv, 'w') as f:
|
||||
f.write('x,y,diff,status\n')
|
||||
for j in range(yblocks):
|
||||
block_xy = (0, j * cell_size[1])
|
||||
block_size = (xsize, cell_size[1])
|
||||
if block_xy[1] + block_size[1] > ysize:
|
||||
block_size = (xsize, ysize - block_xy[1])
|
||||
block_data = ds.ReadAsArray(*block_xy, *block_size)
|
||||
for i in range(xblocks):
|
||||
start_x = i * cell_size[0]
|
||||
end_x = start_x + cell_size[0]
|
||||
if end_x > xsize:
|
||||
end_x = xsize
|
||||
block_data_xy = block_data[:, start_x:end_x]
|
||||
|
||||
center_x = start_x + cell_size[0] // 2
|
||||
center_y = j * cell_size[1] + cell_size[1] // 2
|
||||
center_x = center_x * geo[1] + geo [0]
|
||||
center_y = center_y * geo[5] + geo [3]
|
||||
f.write(f'{center_x},{center_y},{block_data_xy.mean() * 100},{int(block_data_xy.mean() > 0.5)}\n')
|
||||
|
||||
result_layer = ResultPointLayer(out_csv, enable=True, proj=layer.proj, geo=layer.geo,result_path=dict)
|
||||
# print(result_layer.result_path)
|
||||
layer.layer_parent.add_result_layer(result_layer)
|
||||
send_message.emit('计算完成')
|
@ -1,42 +0,0 @@
|
||||
import numpy as np
|
||||
|
||||
def OTSU(hist):
|
||||
|
||||
u1=0.0#背景像素的平均灰度值
|
||||
u2=0.0#前景像素的平均灰度值
|
||||
th=0.0
|
||||
|
||||
#总的像素数目
|
||||
PixSum= np.sum(hist)
|
||||
#各灰度值所占总像素数的比例
|
||||
PixRate=hist / PixSum
|
||||
#统计各个灰度值的像素个数
|
||||
Max_var = 0
|
||||
#确定最大类间方差对应的阈值
|
||||
GrayScale = len(hist)
|
||||
for i in range(1,len(hist)):#从1开始是为了避免w1为0.
|
||||
u1_tem=0.0
|
||||
u2_tem=0.0
|
||||
#背景像素的比列
|
||||
w1=np.sum(PixRate[:i])
|
||||
#前景像素的比例
|
||||
w2=1.0-w1
|
||||
if w1==0 or w2==0:
|
||||
pass
|
||||
else:#背景像素的平均灰度值
|
||||
for m in range(i):
|
||||
u1_tem=u1_tem+PixRate[m]*m
|
||||
u1 = u1_tem * 1.0 / w1
|
||||
#前景像素的平均灰度值
|
||||
for n in range(i,GrayScale):
|
||||
u2_tem = u2_tem + PixRate[n]*n
|
||||
u2 = u2_tem / w2
|
||||
#print(u1)
|
||||
#类间方差公式:G=w1*w2*(u1-u2)**2
|
||||
tem_var=w1*w2*np.power((u1-u2),2)
|
||||
#print(tem_var)
|
||||
#判断当前类间方差是否为最大值。
|
||||
if Max_var<tem_var:
|
||||
Max_var=tem_var#深拷贝,Max_var与tem_var占用不同的内存空间。
|
||||
th=i
|
||||
return th
|
@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1655105353713" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2292" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
|
||||
</style></defs><path d="M517.688889 796.444444c-45.511111 0-85.333333-17.066667-119.466667-51.2L73.955556 381.155556c-22.755556-22.755556-17.066667-56.888889 5.688888-79.644445 22.755556-22.755556 56.888889-17.066667 79.644445 5.688889l329.955555 364.088889c5.688889 5.688889 17.066667 11.377778 28.444445 11.377778s22.755556-5.688889 34.133333-17.066667l312.888889-364.088889c22.755556-22.755556 56.888889-28.444444 79.644445-5.688889 22.755556 22.755556 28.444444 56.888889 5.688888 79.644445L637.155556 739.555556c-28.444444 39.822222-68.266667 56.888889-119.466667 56.888888 5.688889 0 0 0 0 0z" p-id="2293"></path></svg>
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1655105348118" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2137" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
|
||||
</style></defs><path d="M312.888889 995.555556c-17.066667 0-28.444444-5.688889-39.822222-17.066667-22.755556-22.755556-17.066667-56.888889 5.688889-79.644445l364.088888-329.955555c11.377778-11.377778 17.066667-22.755556 17.066667-34.133333 0-11.377778-5.688889-22.755556-17.066667-34.133334L273.066667 187.733333c-22.755556-22.755556-28.444444-56.888889-5.688889-79.644444 22.755556-22.755556 56.888889-28.444444 79.644444-5.688889l364.088889 312.888889c34.133333 28.444444 56.888889 73.955556 56.888889 119.466667s-17.066667 85.333333-51.2 119.466666l-364.088889 329.955556c-11.377778 5.688889-28.444444 11.377778-39.822222 11.377778z" p-id="2138"></path></svg>
|
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
@ -1,9 +1,10 @@
|
||||
import os
|
||||
from pickle import TRUE
|
||||
from threading import Thread
|
||||
from rscder.gui.actions import ActionManager
|
||||
from rscder.gui.layercombox import ResultPointLayerCombox
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
from PyQt5.QtWidgets import QAction, QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton,QSlider,QSpinBox,QSpacerItem
|
||||
from PyQt5.QtWidgets import QAction, QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton,QSlider,QSpinBox,QSpacerItem,QDialogButtonBox
|
||||
from PyQt5.QtCore import pyqtSignal,Qt
|
||||
from PyQt5.QtGui import QIcon
|
||||
from rscder.utils.icons import IconInstance
|
||||
@ -36,19 +37,20 @@ class RateSetdialog(QDialog):
|
||||
self.ok_button = QPushButton('确定', self)
|
||||
self.ok_button.setIcon(IconInstance().OK)
|
||||
self.ok_button.clicked.connect(self.on_ok)
|
||||
|
||||
self.ok_button.setDefault(True)
|
||||
self.cancel_button = QPushButton('取消', self)
|
||||
self.cancel_button.setIcon(IconInstance().CANCEL)
|
||||
self.cancel_button.clicked.connect(self.on_cancel)
|
||||
|
||||
self.button_layout = QHBoxLayout()
|
||||
self.button_layout.addWidget(self.ok_button)
|
||||
self.button_layout.addWidget(self.cancel_button)
|
||||
self.cancel_button.setDefault(False)
|
||||
self.buttonbox=QDialogButtonBox(self)
|
||||
self.buttonbox.addButton(self.ok_button,QDialogButtonBox.NoRole)
|
||||
self.buttonbox.addButton(self.cancel_button,QDialogButtonBox.NoRole)
|
||||
self.buttonbox.setCenterButtons(True)
|
||||
vlayout=QVBoxLayout()
|
||||
vlayout.addLayout(h1)
|
||||
vlayout.addWidget(QLabel('设置阈值'))
|
||||
vlayout.addLayout(h2)
|
||||
vlayout.addLayout(self.button_layout)
|
||||
vlayout.addWidget(self.buttonbox)
|
||||
self.setLayout(vlayout)
|
||||
|
||||
self.old_data = None
|
||||
|
@ -7,7 +7,7 @@ import numpy as np
|
||||
from rscder.gui.actions import ActionManager
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
from rscder.gui.layercombox import RasterLayerCombox,ResultLayercombox, ResultPointLayerCombox
|
||||
from PyQt5.QtWidgets import QAction, QFileDialog, QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton
|
||||
from PyQt5.QtWidgets import QAction, QFileDialog, QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton,QDialogButtonBox
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtCore import Qt
|
||||
from osgeo import gdal
|
||||
@ -49,14 +49,19 @@ class EvalutationDialog(QDialog):
|
||||
self.ok_button = QPushButton('确定', self)
|
||||
self.ok_button.setIcon(IconInstance().OK)
|
||||
self.ok_button.clicked.connect(self.on_ok)
|
||||
|
||||
self.ok_button.setDefault(True)
|
||||
self.cancel_button = QPushButton('取消', self)
|
||||
self.cancel_button.setIcon(IconInstance().CANCEL)
|
||||
self.cancel_button.clicked.connect(self.on_cancel)
|
||||
self.cancel_button.setDefault(False)
|
||||
self.buttonbox=QDialogButtonBox(self)
|
||||
self.buttonbox.addButton(self.ok_button,QDialogButtonBox.NoRole)
|
||||
self.buttonbox.addButton(self.cancel_button,QDialogButtonBox.NoRole)
|
||||
self.buttonbox.setCenterButtons(True)
|
||||
|
||||
self.button_layout = QHBoxLayout()
|
||||
self.button_layout.addWidget(self.ok_button)
|
||||
self.button_layout.addWidget(self.cancel_button)
|
||||
self.button_layout.addWidget(self.ok_button,0,alignment=Qt.AlignHCenter)
|
||||
self.button_layout.addLayout(self.cancel_button,0,alignment=Qt.AlignHCenter)
|
||||
|
||||
self.main_layout = QVBoxLayout()
|
||||
self.main_layout.addLayout(hbox1)
|
||||
|
@ -5,6 +5,7 @@ from rscder.utils.project import Project, PairLayer, ResultPointLayer
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
from PyQt5.QtWidgets import QDialog, QHBoxLayout, QFileDialog, QComboBox, QVBoxLayout, QPushButton, QLabel, QLineEdit, QAction
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtCore import Qt
|
||||
class ExportDialog(QDialog):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
@ -60,8 +61,8 @@ class ExportDialog(QDialog):
|
||||
hbox2.addWidget(out_path_btn)
|
||||
|
||||
hbox3 = QHBoxLayout()
|
||||
hbox3.addWidget(ok_btn)
|
||||
hbox3.addWidget(cancel_btn)
|
||||
hbox3.addWidget(ok_btn,0,alignment=Qt.AlignHCenter)
|
||||
hbox3.addWidget(cancel_btn,0,alignment=Qt.AlignHCenter)
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
vbox.addLayout(hbox1)
|
||||
|
5
plugins/filter_collection/__init__.py
Normal file
5
plugins/filter_collection/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
from misc import Register
|
||||
|
||||
FILTER = Register('滤波处理算法')
|
||||
|
||||
from filter_collection.main import *
|
@ -1,3 +1,4 @@
|
||||
from datetime import datetime
|
||||
import os
|
||||
from threading import Thread
|
||||
from PyQt5.QtWidgets import QDialog, QAction
|
||||
@ -10,19 +11,98 @@ from rscder.plugins.basic import BasicPlugin
|
||||
from rscder.gui.layercombox import RasterLayerCombox
|
||||
from osgeo import gdal, gdal_array
|
||||
from skimage.filters import rank
|
||||
from skimage.morphology import disk, rectangle
|
||||
from skimage.morphology import rectangle
|
||||
from filter_collection import FILTER
|
||||
from misc import AlgFrontend
|
||||
|
||||
@FILTER.register
|
||||
class MainFilter(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return '均值滤波'
|
||||
|
||||
@staticmethod
|
||||
def get_widget(parent=None):
|
||||
widget = QtWidgets.QWidget(parent)
|
||||
x_size_input = QtWidgets.QLineEdit(widget)
|
||||
x_size_input.setText('3')
|
||||
x_size_input.setValidator(QtGui.QIntValidator())
|
||||
x_size_input.setObjectName('xinput')
|
||||
y_size_input = QtWidgets.QLineEdit(widget)
|
||||
y_size_input.setValidator(QtGui.QIntValidator())
|
||||
y_size_input.setObjectName('yinput')
|
||||
y_size_input.setText('3')
|
||||
|
||||
size_label = QtWidgets.QLabel(widget)
|
||||
size_label.setText('窗口大小:')
|
||||
|
||||
time_label = QtWidgets.QLabel(widget)
|
||||
time_label.setText('X')
|
||||
|
||||
hlayout1 = QtWidgets.QHBoxLayout()
|
||||
|
||||
hlayout1.addWidget(size_label)
|
||||
hlayout1.addWidget(x_size_input)
|
||||
hlayout1.addWidget(time_label)
|
||||
hlayout1.addWidget(y_size_input)
|
||||
|
||||
widget.setLayout(hlayout1)
|
||||
|
||||
return widget
|
||||
|
||||
@staticmethod
|
||||
def get_params(widget:QtWidgets.QWidget=None):
|
||||
if widget is None:
|
||||
return dict(x_size=3, y_size=3)
|
||||
|
||||
x_input = widget.findChild(QtWidgets.QLineEdit, 'xinput')
|
||||
y_input = widget.findChild(QtWidgets.QLineEdit, 'yinput')
|
||||
|
||||
if x_input is None or y_input is None:
|
||||
return dict(x_size=3, y_size=3)
|
||||
|
||||
x_size = int(x_input.text())
|
||||
y_size = int(y_input.text())
|
||||
|
||||
return dict(x_size=x_size, y_size=y_size)
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth, x_size, y_size, *args, **kargs):
|
||||
x_size = int(x_size)
|
||||
y_size = int(y_size)
|
||||
# pth = layer.path
|
||||
if pth is None:
|
||||
return
|
||||
|
||||
ds = gdal.Open(pth)
|
||||
band_count = ds.RasterCount
|
||||
|
||||
out_path = os.path.join(Project().other_path, 'mean_filter_{}.tif'.format(int(datetime.now().timestamp() * 1000)))
|
||||
out_ds = gdal.GetDriverByName('GTiff').Create(out_path, ds.RasterXSize, ds.RasterYSize, band_count, ds.GetRasterBand(1).DataType)
|
||||
out_ds.SetProjection(ds.GetProjection())
|
||||
out_ds.SetGeoTransform(ds.GetGeoTransform())
|
||||
|
||||
for i in range(band_count):
|
||||
band = ds.GetRasterBand(i+1)
|
||||
data = band.ReadAsArray()
|
||||
|
||||
data = rank.mean(data, rectangle(y_size, x_size))
|
||||
|
||||
out_band = out_ds.GetRasterBand(i+1)
|
||||
out_band.WriteArray(data)
|
||||
|
||||
out_ds.FlushCache()
|
||||
del out_ds
|
||||
del ds
|
||||
return out_path
|
||||
|
||||
class FilterSetting(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super(FilterSetting, self).__init__(parent)
|
||||
self.setWindowTitle('滤波设置')
|
||||
# self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||
# self.setFixedSize(300, 200)
|
||||
# self.setStyleSheet("QDialog{background-color:rgb(255,255,255);}")
|
||||
self.setWindowIcon(IconInstance().FILTER)
|
||||
# self.setWindowIconText('Filter Setting')
|
||||
# self.setWindowModality(Qt.ApplicationModal)
|
||||
self.initUI()
|
||||
# self.show()
|
||||
|
||||
def initUI(self):
|
||||
self.layer_combox = RasterLayerCombox(self)
|
||||
@ -61,8 +141,8 @@ class FilterSetting(QDialog):
|
||||
cancel_button.clicked.connect(self.reject)
|
||||
|
||||
hlayout2 = QtWidgets.QHBoxLayout()
|
||||
hlayout2.addWidget(ok_button)
|
||||
hlayout2.addWidget(cancel_button)
|
||||
hlayout2.addWidget(ok_button,0,alignment=Qt.AlignHCenter)
|
||||
hlayout2.addWidget(cancel_button,0,alignment=Qt.AlignHCenter)
|
||||
|
||||
vlayout = QtWidgets.QVBoxLayout()
|
||||
vlayout.addLayout(hbox)
|
||||
@ -78,10 +158,10 @@ class MainPlugin(BasicPlugin):
|
||||
@staticmethod
|
||||
def info():
|
||||
return {
|
||||
'name': 'mean_filter',
|
||||
'name': 'FilterCollection',
|
||||
'author': 'rscder',
|
||||
'version': '0.0.1',
|
||||
'description': 'Mean Filter'
|
||||
'description': 'Filter Collections'
|
||||
}
|
||||
|
||||
def set_action(self):
|
5
plugins/follow/__init__.py
Normal file
5
plugins/follow/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
from misc import Register
|
||||
|
||||
FOLLOW = Register('流程')
|
||||
|
||||
from follow.main import *
|
165
plugins/follow/main.py
Normal file
165
plugins/follow/main.py
Normal file
@ -0,0 +1,165 @@
|
||||
from functools import partial
|
||||
from threading import Thread
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
from rscder.utils.icons import IconInstance
|
||||
from rscder.gui.actions import ActionManager
|
||||
from PyQt5 import QtWidgets, QtGui
|
||||
from follow import FOLLOW
|
||||
from misc import AlgFrontend
|
||||
|
||||
class FollowDialog(QtWidgets.QDialog):
|
||||
|
||||
def __init__(self, parent=None, alg:AlgFrontend=None) -> None:
|
||||
super().__init__(parent)
|
||||
if alg is None:
|
||||
return
|
||||
self.setMinimumWidth(700)
|
||||
# self.setMinimumHeight(500)
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
|
||||
self.widget = alg.get_widget(self)
|
||||
vbox.addWidget(self.widget)
|
||||
|
||||
self.ok_button = QtWidgets.QPushButton('确定', self)
|
||||
self.ok_button.setIcon(IconInstance().OK)
|
||||
self.ok_button.clicked.connect(self.accept)
|
||||
self.ok_button.setDefault(True)
|
||||
|
||||
self.cancel_button = QtWidgets.QPushButton('取消', self)
|
||||
self.cancel_button.setIcon(IconInstance().CANCEL)
|
||||
self.cancel_button.clicked.connect(self.reject)
|
||||
self.cancel_button.setDefault(False)
|
||||
buttonbox= QtWidgets.QDialogButtonBox()
|
||||
buttonbox.addButton(self.ok_button,QtWidgets.QDialogButtonBox.NoRole)
|
||||
buttonbox.addButton(self.cancel_button,QtWidgets.QDialogButtonBox.NoRole)
|
||||
buttonbox.setCenterButtons(True)
|
||||
|
||||
vbox.addWidget(buttonbox)
|
||||
vbox.addStretch()
|
||||
|
||||
self.setLayout(vbox)
|
||||
|
||||
class FollowPlugin(BasicPlugin):
|
||||
|
||||
@staticmethod
|
||||
def get_info():
|
||||
return {
|
||||
'name': 'Follow',
|
||||
'version': '1.0.0'
|
||||
}
|
||||
|
||||
|
||||
def set_action(self):
|
||||
follow_box:QtWidgets.QWidget = ActionManager().follow_box
|
||||
toolbar = ActionManager().add_toolbar('Follow')
|
||||
vbox = QtWidgets.QVBoxLayout(follow_box)
|
||||
|
||||
combox = QtWidgets.QComboBox(follow_box)
|
||||
|
||||
# print(FOLLOW.keys())
|
||||
for key in FOLLOW.keys():
|
||||
alg:AlgFrontend = FOLLOW[key]
|
||||
if alg.get_name() is None:
|
||||
name = key
|
||||
else:
|
||||
name = alg.get_name()
|
||||
combox.addItem(name, key)
|
||||
|
||||
action = QtWidgets.QAction(alg.get_icon(), name, self.mainwindow)
|
||||
func = partial(self.run_dialog, alg)
|
||||
action.triggered.connect(func)
|
||||
toolbar.addAction(action)
|
||||
|
||||
|
||||
combox.currentIndexChanged.connect(self.on_change)
|
||||
|
||||
vbox.addWidget(combox)
|
||||
|
||||
self.current_widget = None
|
||||
|
||||
|
||||
self.combox = combox
|
||||
self.layout = vbox
|
||||
|
||||
self.ok_button = QtWidgets.QPushButton('运行')
|
||||
self.ok_button.setIcon(IconInstance().OK)
|
||||
self.ok_button.clicked.connect(self.run)
|
||||
self.ok_button.setDefault(True)
|
||||
|
||||
self.cancel_button = QtWidgets.QPushButton('重置')
|
||||
self.cancel_button.setIcon(IconInstance().CANCEL)
|
||||
self.cancel_button.clicked.connect(self.reset)
|
||||
self.cancel_button.setDefault(False)
|
||||
buttonbox= QtWidgets.QDialogButtonBox()
|
||||
buttonbox.addButton(self.ok_button,QtWidgets.QDialogButtonBox.NoRole)
|
||||
buttonbox.addButton(self.cancel_button,QtWidgets.QDialogButtonBox.NoRole)
|
||||
buttonbox.setCenterButtons(True)
|
||||
|
||||
self.btn_box = buttonbox
|
||||
follow_box.setLayout(vbox)
|
||||
# vbox.addStretch()
|
||||
self.on_change(0)
|
||||
|
||||
def on_change(self, index):
|
||||
|
||||
print(self.combox.currentData())
|
||||
if self.current_widget is not None:
|
||||
self.current_widget.setParent(None)
|
||||
self.btn_box.setParent(None)
|
||||
self.layout.removeWidget(self.current_widget)
|
||||
self.layout.removeWidget(self.btn_box)
|
||||
self.current_widget = None
|
||||
|
||||
alg:AlgFrontend = FOLLOW[self.combox.currentData()]
|
||||
|
||||
if alg.get_widget() is None:
|
||||
return
|
||||
|
||||
self.current_widget = alg.get_widget(ActionManager().follow_box)
|
||||
self.layout.addWidget(self.current_widget)
|
||||
self.layout.addWidget(self.btn_box)
|
||||
|
||||
|
||||
def run(self):
|
||||
alg:AlgFrontend = FOLLOW[self.combox.currentData()]
|
||||
|
||||
if alg is None:
|
||||
return
|
||||
|
||||
params = alg.get_params(self.current_widget)
|
||||
|
||||
t = Thread(target=self.run_alg, args=(params,))
|
||||
t.start()
|
||||
|
||||
def run_dialog(self, alg:AlgFrontend):
|
||||
|
||||
dialog = FollowDialog(self.mainwindow, alg)
|
||||
dialog.show()
|
||||
|
||||
if dialog.exec_() == QtWidgets.QDialog.Accepted:
|
||||
|
||||
params = alg.get_params(dialog.widget)
|
||||
|
||||
t = Thread(target=self.run_alg, args = (alg, params,))
|
||||
t.start()
|
||||
|
||||
|
||||
def run_alg(self, alg:AlgFrontend, p):
|
||||
|
||||
alg.run_alg(**p, send_message=self.send_message)
|
||||
|
||||
def reset(self):
|
||||
|
||||
if self.current_widget is None:
|
||||
return
|
||||
self.current_widget.setParent(None)
|
||||
self.btn_box.setParent(None)
|
||||
self.layout.removeWidget(self.current_widget)
|
||||
self.layout.removeWidget(self.btn_box)
|
||||
|
||||
self.current_widget = FOLLOW[self.combox.currentData()].get_widget(ActionManager().follow_box)
|
||||
|
||||
self.layout.addWidget(self.current_widget)
|
||||
self.layout.addLayout(self.btn_box)
|
||||
|
||||
|
3
plugins/misc/__init__.py
Normal file
3
plugins/misc/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from misc.main import *
|
||||
from misc.utils import *
|
||||
from misc.table_layer import *
|
92
plugins/misc/main.py
Normal file
92
plugins/misc/main.py
Normal file
@ -0,0 +1,92 @@
|
||||
from threading import Thread
|
||||
from plugins.misc.utils import Register
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
from PyQt5.QtWidgets import QGroupBox, QWidget, QComboBox, QVBoxLayout
|
||||
|
||||
|
||||
class MISCPlugin(BasicPlugin):
|
||||
|
||||
@staticmethod
|
||||
def info():
|
||||
return {
|
||||
'name': 'MISC Plugin',
|
||||
'description': '基本开发工具',
|
||||
'author': 'Wangtong',
|
||||
'version': '1.0.0',
|
||||
}
|
||||
|
||||
def set_action(self):
|
||||
pass
|
||||
|
||||
|
||||
class AlgFrontend(object):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_icon():
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_widget(parent=None):
|
||||
return QWidget(parent)
|
||||
|
||||
@staticmethod
|
||||
def get_params(widget=None):
|
||||
return dict()
|
||||
|
||||
@staticmethod
|
||||
def run_alg(*args, **kargs):
|
||||
pass
|
||||
|
||||
|
||||
class AlgSelectWidget(QGroupBox):
|
||||
|
||||
def __init__(self, parent= None, registery:Register = None) -> None:
|
||||
super().__init__(parent)
|
||||
self.reg = registery
|
||||
if registery is None:
|
||||
return
|
||||
self.setTitle(registery.name)
|
||||
self.selectbox = QComboBox(self)
|
||||
self.selectbox.addItem('--', None)
|
||||
for key in self.reg.keys():
|
||||
alg:AlgFrontend = self.reg[key]
|
||||
if alg.get_name() is None:
|
||||
name = key
|
||||
else:
|
||||
name = alg.get_name()
|
||||
self.selectbox.addItem(name, key)
|
||||
|
||||
self.vbox = QVBoxLayout(self)
|
||||
self.vbox.addWidget(self.selectbox)
|
||||
|
||||
self.params_widget = QWidget()
|
||||
self.vbox.addWidget(self.params_widget)
|
||||
|
||||
self.selectbox.currentIndexChanged.connect(self.on_changed)
|
||||
|
||||
def on_changed(self, index):
|
||||
if index == 0:
|
||||
self.alg = None
|
||||
self.params_widget.setParent(None)
|
||||
self.vbox.removeWidget(self.params_widget)
|
||||
self.params_widget = QWidget(self)
|
||||
self.vbox.addWidget(self.params_widget)
|
||||
return
|
||||
|
||||
self.alg:AlgFrontend = self.reg[self.selectbox.itemData(index)]
|
||||
self.params_widget.setParent(None)
|
||||
self.vbox.removeWidget(self.params_widget)
|
||||
self.params_widget = self.alg.get_widget(self)
|
||||
self.vbox.addWidget(self.params_widget)
|
||||
|
||||
|
||||
|
||||
def get_alg_and_params(self):
|
||||
if self.selectbox.currentIndex() == 0:
|
||||
return None, None
|
||||
|
||||
return self.alg, self.alg.get_params(self.params_widget)
|
46
plugins/misc/table_layer.py
Normal file
46
plugins/misc/table_layer.py
Normal file
@ -0,0 +1,46 @@
|
||||
from datetime import datetime
|
||||
import math
|
||||
from random import random
|
||||
from osgeo import gdal
|
||||
from rscder.utils.project import Project
|
||||
import os
|
||||
from rscder.utils.project import BasicLayer, ResultPointLayer
|
||||
|
||||
def table_layer(pth:str,layer:BasicLayer, name, send_message = None):
|
||||
if send_message is not None:
|
||||
send_message.emit('正在计算表格结果...')
|
||||
cell_size = layer.layer_parent.cell_size
|
||||
ds = gdal.Open(pth)
|
||||
xsize = ds.RasterXSize
|
||||
ysize = ds.RasterYSize
|
||||
geo = ds.GetGeoTransform()
|
||||
|
||||
out_csv = os.path.join(Project().other_path, f'{name}_table_result_{ int(datetime.now().timestamp() * 1000) }.csv')
|
||||
yblocks = ysize // cell_size[1] + 1
|
||||
xblocks = xsize // cell_size[0] + 1
|
||||
with open(out_csv, 'w') as f:
|
||||
f.write('x,y,diff,status\n')
|
||||
for j in range(yblocks):
|
||||
block_xy = (0, j * cell_size[1])
|
||||
block_size = (xsize, cell_size[1])
|
||||
if block_xy[1] + block_size[1] > ysize:
|
||||
block_size = (xsize, ysize - block_xy[1])
|
||||
block_data = ds.ReadAsArray(*block_xy, *block_size)
|
||||
for i in range(xblocks):
|
||||
start_x = i * cell_size[0]
|
||||
end_x = start_x + cell_size[0]
|
||||
if end_x > xsize:
|
||||
end_x = xsize
|
||||
block_data_xy = block_data[:, start_x:end_x]
|
||||
|
||||
center_x = start_x + cell_size[0] // 2
|
||||
center_y = j * cell_size[1] + cell_size[1] // 2
|
||||
center_x = center_x * geo[1] + geo [0]
|
||||
center_y = center_y * geo[5] + geo [3]
|
||||
f.write(f'{center_x},{center_y},{block_data_xy.mean() * 100},{int(block_data_xy.mean() > 0.5)}\n')
|
||||
|
||||
result_layer = ResultPointLayer(out_csv, enable=True, proj=layer.proj, geo=layer.geo,result_path={})
|
||||
# print(result_layer.result_path)
|
||||
layer.layer_parent.add_result_layer(result_layer)
|
||||
if send_message is not None:
|
||||
send_message.emit('计算完成')
|
46
plugins/misc/utils.py
Normal file
46
plugins/misc/utils.py
Normal file
@ -0,0 +1,46 @@
|
||||
import os
|
||||
import random
|
||||
import logging
|
||||
# def generate_temp_file
|
||||
|
||||
class Register:
|
||||
|
||||
def __init__(self, registry_name):
|
||||
self._dict = {}
|
||||
self._name = registry_name
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if not callable(value):
|
||||
raise Exception(f"Value of a Registry must be a callable!\nValue: {value}")
|
||||
if key is None:
|
||||
key = value.__name__
|
||||
if key in self._dict:
|
||||
logging.warning("Key %s already in registry %s." % (key, self._name))
|
||||
self._dict[key] = value
|
||||
|
||||
def register(self, target):
|
||||
"""Decorator to register a function or class."""
|
||||
|
||||
def add(key, value):
|
||||
self[key] = value
|
||||
return value
|
||||
|
||||
if callable(target):
|
||||
# @reg.register
|
||||
return add(None, target)
|
||||
# @reg.register('alias')
|
||||
return lambda x: add(target, x)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._dict[key]
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self._dict
|
||||
|
||||
def keys(self):
|
||||
"""key"""
|
||||
return self._dict.keys()
|
@ -13,11 +13,11 @@
|
||||
path: ./plugin\export_to
|
||||
version: 1.0.0
|
||||
- author: RSCDER
|
||||
description: MeanFilter
|
||||
description: FilterCollection
|
||||
enabled: true
|
||||
module: some_filter
|
||||
name: MeanFilter
|
||||
path: ./plugin\some_filter
|
||||
module: filter_collection
|
||||
name: FilterCollection
|
||||
path: ./plugin\filter_collection
|
||||
version: 1.0.0
|
||||
- author: RSCDER
|
||||
description: Evaluation
|
||||
@ -27,11 +27,18 @@
|
||||
path: ./plugin\evaluation
|
||||
version: 1.0.0
|
||||
- author: RSCDER
|
||||
description: AllinOne
|
||||
description: UnsupervisedPlugin
|
||||
enabled: true
|
||||
module: In_one
|
||||
name: basic_diff_AllinOne
|
||||
path: ./plugin\In_one
|
||||
module: unsupervised_method
|
||||
name: UnsupervisedPlugin
|
||||
path: ./plugin\unsupervsied_method
|
||||
version: 1.0.0
|
||||
- author: RSCDER
|
||||
description: VegatationPlugin
|
||||
enabled: true
|
||||
module: veg_method
|
||||
name: VegatationPlugin
|
||||
path: ./plugin\veg_method
|
||||
version: 1.0.0
|
||||
- author: RSCDER
|
||||
description: set Change Rate
|
||||
@ -40,3 +47,10 @@
|
||||
name: set_change_rate
|
||||
path: ./plugin\change_rate
|
||||
version: 1.0.0
|
||||
- author: RSCDER
|
||||
description: Follow box
|
||||
enabled: true
|
||||
module: follow
|
||||
name: FollowPlugin
|
||||
path: ./plugin\follow
|
||||
version: 1.0.0
|
@ -1 +0,0 @@
|
||||
from some_filter.main import *
|
5
plugins/thres/__init__.py
Normal file
5
plugins/thres/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
from misc import Register
|
||||
|
||||
THRES = Register('阈值方法')
|
||||
|
||||
from thres.main import *
|
178
plugins/thres/main.py
Normal file
178
plugins/thres/main.py
Normal file
@ -0,0 +1,178 @@
|
||||
from osgeo import gdal, gdalconst
|
||||
from rscder.utils.project import Project
|
||||
import os
|
||||
from misc import AlgFrontend
|
||||
from thres import THRES
|
||||
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QLineEdit
|
||||
from PyQt5.QtGui import QIntValidator, QDoubleValidator
|
||||
|
||||
@THRES.register
|
||||
class ManulGapAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return '手动阈值'
|
||||
|
||||
@staticmethod
|
||||
def get_params(widget:QWidget=None):
|
||||
if widget is None:
|
||||
return dict(gap=125)
|
||||
lineedit:QLineEdit = widget.layout().findChild(QLineEdit, 'lineedit')
|
||||
if lineedit is None:
|
||||
return dict(gap=125)
|
||||
|
||||
gap = int(lineedit.text())
|
||||
|
||||
return dict(gap=gap)
|
||||
@staticmethod
|
||||
def get_widget(parent=None):
|
||||
|
||||
widget = QWidget(parent)
|
||||
lineedit = QLineEdit(widget)
|
||||
lineedit.setObjectName('lineedit')
|
||||
lineedit.setValidator(QIntValidator(1, 254))
|
||||
# lineedit.
|
||||
label = QLabel('阈值:')
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.addWidget(label)
|
||||
layout.addWidget(lineedit)
|
||||
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth,name = '',gap = 125, send_message = None):
|
||||
|
||||
ds = gdal.Open(pth)
|
||||
band = ds.GetRasterBand(1)
|
||||
|
||||
xsize = ds.RasterXSize
|
||||
ysize = ds.RasterYSize
|
||||
|
||||
max_pixels = 1e7
|
||||
max_rows = max_pixels // xsize
|
||||
if max_rows < 1:
|
||||
max_rows = 1
|
||||
if max_rows > ysize:
|
||||
max_rows = ysize
|
||||
block_count = ysize // max_rows + 1
|
||||
|
||||
if send_message is not None:
|
||||
send_message.emit('阈值为:{}'.format(gap))
|
||||
|
||||
out_th = os.path.join(Project().bcdm_path, '{}_thresh{}_bcdm.tif'.format(name,gap))
|
||||
out_ds = gdal.GetDriverByName('GTiff').Create(out_th, xsize, ysize, 1, gdal.GDT_Byte)
|
||||
out_ds.SetGeoTransform(ds.GetGeoTransform())
|
||||
out_ds.SetProjection(ds.GetProjection())
|
||||
out_band = out_ds.GetRasterBand(1)
|
||||
|
||||
for i in range(block_count):
|
||||
start_row = i * max_rows
|
||||
end_row = min((i + 1) * max_rows, ysize)
|
||||
block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
|
||||
out_band.WriteArray(block > gap, 0, start_row)
|
||||
out_band.FlushCache()
|
||||
out_ds = None
|
||||
ds = None
|
||||
if send_message is not None:
|
||||
send_message.emit('自定义阈值分割完成')
|
||||
return out_th
|
||||
|
||||
|
||||
import numpy as np
|
||||
|
||||
def OTSU(hist):
|
||||
|
||||
u1=0.0#背景像素的平均灰度值
|
||||
u2=0.0#前景像素的平均灰度值
|
||||
th=0.0
|
||||
|
||||
#总的像素数目
|
||||
PixSum= np.sum(hist)
|
||||
#各灰度值所占总像素数的比例
|
||||
PixRate=hist / PixSum
|
||||
#统计各个灰度值的像素个数
|
||||
Max_var = 0
|
||||
#确定最大类间方差对应的阈值
|
||||
GrayScale = len(hist)
|
||||
for i in range(1,len(hist)):#从1开始是为了避免w1为0.
|
||||
u1_tem=0.0
|
||||
u2_tem=0.0
|
||||
#背景像素的比列
|
||||
w1=np.sum(PixRate[:i])
|
||||
#前景像素的比例
|
||||
w2=1.0-w1
|
||||
if w1==0 or w2==0:
|
||||
pass
|
||||
else:#背景像素的平均灰度值
|
||||
for m in range(i):
|
||||
u1_tem=u1_tem+PixRate[m]*m
|
||||
u1 = u1_tem * 1.0 / w1
|
||||
#前景像素的平均灰度值
|
||||
for n in range(i,GrayScale):
|
||||
u2_tem = u2_tem + PixRate[n]*n
|
||||
u2 = u2_tem / w2
|
||||
#print(u1)
|
||||
#类间方差公式:G=w1*w2*(u1-u2)**2
|
||||
tem_var=w1*w2*np.power((u1-u2),2)
|
||||
#print(tem_var)
|
||||
#判断当前类间方差是否为最大值。
|
||||
if Max_var<tem_var:
|
||||
Max_var=tem_var#深拷贝,Max_var与tem_var占用不同的内存空间。
|
||||
th=i
|
||||
return th
|
||||
|
||||
@THRES.register
|
||||
class OTSUAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'OTSU阈值'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth,name='',send_message=None):
|
||||
|
||||
ds = gdal.Open(pth)
|
||||
band = ds.GetRasterBand(1)
|
||||
# band_count = ds.RasterCount
|
||||
|
||||
hist = np.zeros(256, dtype=np.int)
|
||||
xsize = ds.RasterXSize
|
||||
ysize = ds.RasterYSize
|
||||
|
||||
max_pixels = 1e7
|
||||
max_rows = max_pixels // xsize
|
||||
if max_rows < 1:
|
||||
max_rows = 1
|
||||
if max_rows > ysize:
|
||||
max_rows = ysize
|
||||
block_count = ysize // max_rows + 1
|
||||
for i in range(block_count):
|
||||
start_row = i * max_rows
|
||||
end_row = min((i + 1) * max_rows, ysize)
|
||||
block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
|
||||
hist += np.histogram(block.flatten(), bins=256, range=(0, 255))[0]
|
||||
hist = hist.astype(np.float32)
|
||||
gap = OTSU(hist)
|
||||
send_message.emit('阈值为:{}'.format(gap))
|
||||
|
||||
out_th = os.path.join(Project().bcdm_path, '{}_otsu_bcdm.tif'.format(name))
|
||||
out_ds = gdal.GetDriverByName('GTiff').Create(out_th, xsize, ysize, 1, gdal.GDT_Byte)
|
||||
out_ds.SetGeoTransform(ds.GetGeoTransform())
|
||||
out_ds.SetProjection(ds.GetProjection())
|
||||
out_band = out_ds.GetRasterBand(1)
|
||||
|
||||
for i in range(block_count):
|
||||
start_row = i * max_rows
|
||||
end_row = min((i + 1) * max_rows, ysize)
|
||||
block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
|
||||
out_band.WriteArray(block > gap, 0, start_row)
|
||||
out_band.FlushCache()
|
||||
out_ds = None
|
||||
ds = None
|
||||
send_message.emit('OTSU阈值完成')
|
||||
|
||||
return out_th
|
||||
# ManulGapAlg.run_alg
|
1
plugins/unsupervised_method/__init__.py
Normal file
1
plugins/unsupervised_method/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from unsupervised_method.main import *
|
227
plugins/unsupervised_method/main.py
Normal file
227
plugins/unsupervised_method/main.py
Normal file
@ -0,0 +1,227 @@
|
||||
from functools import partial
|
||||
from threading import Thread
|
||||
from plugins.misc.main import AlgFrontend
|
||||
from rscder.gui.actions import ActionManager
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
from PyQt5.QtWidgets import QAction, QToolBar, QMenu, QDialog, QHBoxLayout, QVBoxLayout, QPushButton,QWidget,QLabel,QLineEdit,QPushButton,QComboBox,QDialogButtonBox
|
||||
|
||||
from rscder.gui.layercombox import PairLayerCombox
|
||||
from rscder.utils.icons import IconInstance
|
||||
from filter_collection import FILTER
|
||||
from .scripts import UNSUPER_CD
|
||||
from thres import THRES
|
||||
from misc import table_layer, AlgSelectWidget
|
||||
from follow import FOLLOW
|
||||
|
||||
class UnsupervisedCDMethod(QDialog):
|
||||
def __init__(self,parent=None, alg:AlgFrontend=None):
|
||||
super(UnsupervisedCDMethod, self).__init__(parent)
|
||||
self.alg = alg
|
||||
self.setWindowTitle('无监督变化检测:{}'.format(alg.get_name()))
|
||||
self.setWindowIcon(IconInstance().LOGO)
|
||||
self.initUI()
|
||||
self.setMinimumWidth(500)
|
||||
|
||||
def initUI(self):
|
||||
#图层
|
||||
self.layer_combox = PairLayerCombox(self)
|
||||
layerbox = QHBoxLayout()
|
||||
layerbox.addWidget(self.layer_combox)
|
||||
|
||||
self.filter_select = AlgSelectWidget(self, FILTER)
|
||||
self.param_widget = self.alg.get_widget(self)
|
||||
self.unsupervised_menu = self.param_widget
|
||||
self.thres_select = AlgSelectWidget(self, THRES)
|
||||
|
||||
self.ok_button = QPushButton('确定', self)
|
||||
self.ok_button.setIcon(IconInstance().OK)
|
||||
self.ok_button.clicked.connect(self.accept)
|
||||
self.ok_button.setDefault(True)
|
||||
|
||||
self.cancel_button = QPushButton('取消', self)
|
||||
self.cancel_button.setIcon(IconInstance().CANCEL)
|
||||
self.cancel_button.clicked.connect(self.reject)
|
||||
self.cancel_button.setDefault(False)
|
||||
buttonbox=QDialogButtonBox(self)
|
||||
buttonbox.addButton(self.ok_button,QDialogButtonBox.NoRole)
|
||||
buttonbox.addButton(self.cancel_button,QDialogButtonBox.NoRole)
|
||||
buttonbox.setCenterButtons(True)
|
||||
|
||||
totalvlayout=QVBoxLayout()
|
||||
totalvlayout.addLayout(layerbox)
|
||||
totalvlayout.addWidget(self.filter_select)
|
||||
if self.param_widget is not None:
|
||||
totalvlayout.addWidget(self.param_widget)
|
||||
totalvlayout.addWidget(self.thres_select)
|
||||
totalvlayout.addStretch(1)
|
||||
hbox = QHBoxLayout()
|
||||
hbox.addStretch(1)
|
||||
hbox.addWidget(buttonbox)
|
||||
totalvlayout.addLayout(hbox)
|
||||
# totalvlayout.addStretch()
|
||||
|
||||
self.setLayout(totalvlayout)
|
||||
|
||||
@FOLLOW.register
|
||||
class UnsupervisedCDFollow(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return '无监督变化检测'
|
||||
|
||||
@staticmethod
|
||||
def get_icon():
|
||||
return IconInstance().UNSUPERVISED
|
||||
|
||||
@staticmethod
|
||||
def get_widget(parent=None):
|
||||
widget = QWidget(parent)
|
||||
layer_combox = PairLayerCombox(widget)
|
||||
layer_combox.setObjectName('layer_combox')
|
||||
|
||||
filter_select = AlgSelectWidget(widget, FILTER)
|
||||
filter_select.setObjectName('filter_select')
|
||||
unsupervised_select = AlgSelectWidget(widget, UNSUPER_CD)
|
||||
unsupervised_select.setObjectName('unsupervised_select')
|
||||
thres_select = AlgSelectWidget(widget, THRES)
|
||||
thres_select.setObjectName('thres_select')
|
||||
|
||||
totalvlayout=QVBoxLayout()
|
||||
totalvlayout.addWidget(layer_combox)
|
||||
totalvlayout.addWidget(filter_select)
|
||||
totalvlayout.addWidget(unsupervised_select)
|
||||
totalvlayout.addWidget(thres_select)
|
||||
totalvlayout.addStretch()
|
||||
|
||||
widget.setLayout(totalvlayout)
|
||||
|
||||
return widget
|
||||
|
||||
@staticmethod
|
||||
def get_params(widget:QWidget=None):
|
||||
if widget is None:
|
||||
return dict()
|
||||
|
||||
layer_combox = widget.findChild(PairLayerCombox, 'layer_combox')
|
||||
filter_select = widget.findChild(AlgSelectWidget, 'filter_select')
|
||||
unsupervised_select = widget.findChild(AlgSelectWidget, 'unsupervised_select')
|
||||
thres_select = widget.findChild(AlgSelectWidget, 'thres_select')
|
||||
|
||||
layer1=layer_combox.layer1
|
||||
pth1 = layer_combox.layer1.path
|
||||
pth2 = layer_combox.layer2.path
|
||||
|
||||
falg, fparams = filter_select.get_alg_and_params()
|
||||
cdalg, cdparams = unsupervised_select.get_alg_and_params()
|
||||
thalg, thparams = thres_select.get_alg_and_params()
|
||||
|
||||
if cdalg is None or thalg is None:
|
||||
return dict()
|
||||
|
||||
return dict(
|
||||
layer1=layer1,
|
||||
pth1 = pth1,
|
||||
pth2 = pth2,
|
||||
falg = falg,
|
||||
fparams = fparams,
|
||||
cdalg = cdalg,
|
||||
cdparams = cdparams,
|
||||
thalg = thalg,
|
||||
thparams = thparams,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def run_alg(layer1=None,
|
||||
pth1 = None,
|
||||
pth2 = None,
|
||||
falg = None,
|
||||
fparams = None,
|
||||
cdalg = None,
|
||||
cdparams = None,
|
||||
thalg = None,
|
||||
thparams = None,
|
||||
send_message = None):
|
||||
|
||||
if cdalg is None or thalg is None:
|
||||
return
|
||||
|
||||
name = layer1.name
|
||||
|
||||
if falg is not None:
|
||||
pth1 = falg.run_alg(pth1, name=name, send_message= send_message, **fparams)
|
||||
pth2 = falg.run_alg(pth2, name=name, send_message= send_message, **fparams)
|
||||
|
||||
|
||||
cdpth = cdalg.run_alg(pth1, pth2, layer1.layer_parent, send_message= send_message,**cdparams)
|
||||
thpth = thalg.run_alg(cdpth, name=name, send_message= send_message, **thparams)
|
||||
|
||||
table_layer(thpth,layer1,name, send_message)
|
||||
|
||||
|
||||
|
||||
|
||||
class UnsupervisedPlugin(BasicPlugin):
|
||||
|
||||
|
||||
@staticmethod
|
||||
def info():
|
||||
return {
|
||||
'name': 'UnsupervisedPlugin',
|
||||
'description': 'UnsupervisedPlugin',
|
||||
'author': 'RSCDER',
|
||||
'version': '1.0.0',
|
||||
}
|
||||
|
||||
def set_action(self):
|
||||
unsupervised_menu = QMenu('&无监督变化检测', self.mainwindow)
|
||||
unsupervised_menu.setIcon(IconInstance().UNSUPERVISED)
|
||||
ActionManager().change_detection_menu.addMenu(unsupervised_menu)
|
||||
|
||||
for key in UNSUPER_CD.keys():
|
||||
alg:AlgFrontend = UNSUPER_CD[key]
|
||||
if alg.get_name() is None:
|
||||
name = key
|
||||
else:
|
||||
name = alg.get_name()
|
||||
|
||||
action = QAction(name, unsupervised_menu)
|
||||
func = partial(self.run_cd, alg)
|
||||
action.triggered.connect(func)
|
||||
|
||||
unsupervised_menu.addAction(action)
|
||||
|
||||
|
||||
def run_cd(self, alg):
|
||||
print(alg.get_name())
|
||||
dialog = UnsupervisedCDMethod(self.mainwindow, alg)
|
||||
dialog.show()
|
||||
|
||||
if dialog.exec_() == QDialog.Accepted:
|
||||
t = Thread(target=self.run_cd_alg, args=(dialog,))
|
||||
t.start()
|
||||
|
||||
def run_cd_alg(self, w:UnsupervisedCDMethod):
|
||||
|
||||
layer1=w.layer_combox.layer1
|
||||
pth1 = w.layer_combox.layer1.path
|
||||
pth2 = w.layer_combox.layer2.path
|
||||
name = layer1.layer_parent.name
|
||||
|
||||
falg, fparams = w.filter_select.get_alg_and_params()
|
||||
cdalg = w.alg
|
||||
cdparams = w.alg.get_params(w.param_widget)
|
||||
thalg, thparams = w.thres_select.get_alg_and_params()
|
||||
|
||||
if cdalg is None or thalg is None:
|
||||
return
|
||||
|
||||
if falg is not None:
|
||||
pth1 = falg.run_alg(pth1, name=name, send_message=self.send_message, **fparams)
|
||||
pth2 = falg.run_alg(pth2, name=name, send_message=self.send_message, **fparams)
|
||||
|
||||
|
||||
cdpth = cdalg.run_alg(pth1, pth2, layer1.layer_parent, send_message=self.send_message,**cdparams)
|
||||
thpth = thalg.run_alg(cdpth, name=name, send_message=self.send_message, **thparams)
|
||||
|
||||
table_layer(thpth,layer1,name,self.send_message)
|
||||
|
0
plugins/unsupervised_method/readme.md
Normal file
0
plugins/unsupervised_method/readme.md
Normal file
12424
plugins/unsupervised_method/scripts/ACD.py
Normal file
12424
plugins/unsupervised_method/scripts/ACD.py
Normal file
File diff suppressed because it is too large
Load Diff
12424
plugins/unsupervised_method/scripts/AHT.py
Normal file
12424
plugins/unsupervised_method/scripts/AHT.py
Normal file
File diff suppressed because it is too large
Load Diff
12424
plugins/unsupervised_method/scripts/LHBA.py
Normal file
12424
plugins/unsupervised_method/scripts/LHBA.py
Normal file
File diff suppressed because it is too large
Load Diff
12424
plugins/unsupervised_method/scripts/OCD.py
Normal file
12424
plugins/unsupervised_method/scripts/OCD.py
Normal file
File diff suppressed because it is too large
Load Diff
12424
plugins/unsupervised_method/scripts/SH.py
Normal file
12424
plugins/unsupervised_method/scripts/SH.py
Normal file
File diff suppressed because it is too large
Load Diff
690
plugins/unsupervised_method/scripts/__init__.py
Normal file
690
plugins/unsupervised_method/scripts/__init__.py
Normal file
@ -0,0 +1,690 @@
|
||||
from datetime import datetime
|
||||
from osgeo import gdal
|
||||
import math,os
|
||||
import time
|
||||
from PyQt5 import QtWidgets
|
||||
from sklearn.cluster import k_means
|
||||
from rscder.utils.geomath import geo2imageRC, imageRC2geo
|
||||
from rscder.utils.project import Project, PairLayer
|
||||
from misc import Register, AlgFrontend
|
||||
|
||||
UNSUPER_CD = Register('无监督变化检测方法')
|
||||
|
||||
import numpy as np
|
||||
from .ACD import ACD
|
||||
from .AHT import AHT
|
||||
from .OCD import OCD
|
||||
from .LHBA import LHBA
|
||||
from .SH import SH
|
||||
|
||||
def warp(file,ds:gdal.Dataset,srcWin=[0,0,0,0]):
|
||||
driver = gdal.GetDriverByName('GTiff')
|
||||
xsize=ds.RasterXSize
|
||||
ysize=ds.RasterYSize
|
||||
geo=ds.GetGeoTransform()
|
||||
orj=ds.GetProjection()
|
||||
band=ds.RasterCount
|
||||
if os.path.exists(file):
|
||||
os.remove(file)
|
||||
out_ds:gdal.Dataset=driver.Create(file, xsize, ysize, band, gdal.GDT_Byte)
|
||||
out_ds.SetGeoTransform(geo)
|
||||
out_ds.SetProjection(orj)
|
||||
for b in range(1,band+1):
|
||||
out_ds.GetRasterBand(b).WriteArray(ds.ReadAsArray(*srcWin,band_list=[b]),*(0,0))
|
||||
del out_ds
|
||||
|
||||
@UNSUPER_CD.register
|
||||
class BasicCD(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return '差分法'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None,*args, **kargs):
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
|
||||
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
|
||||
|
||||
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])
|
||||
block_data1 = ds1.ReadAsArray(*block_xy1, *block_size1)
|
||||
block_data2 = ds2.ReadAsArray(*block_xy2, *block_size2)
|
||||
|
||||
if band == 1:
|
||||
block_data1 = block_data1[None, ...]
|
||||
block_data2 = block_data2[None, ...]
|
||||
# pdb.set_trace()
|
||||
block_diff = block_data1.sum(0) - block_data2.sum(0)
|
||||
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.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('归一化概率中...')
|
||||
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
|
||||
|
||||
@UNSUPER_CD.register
|
||||
class LSTS(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'LSTS'
|
||||
|
||||
@staticmethod
|
||||
def get_widget(parent=None):
|
||||
|
||||
widget = QtWidgets.QWidget(parent)
|
||||
|
||||
return widget
|
||||
|
||||
@staticmethod
|
||||
def get_params(widget=None):
|
||||
return dict(n=5, w_size=(3,3))
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message=None,n=5,w_size=(3,3), *args, **kws):
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
|
||||
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, '%d.tif'%(int(datetime.now().timestamp() * 1000)))
|
||||
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)
|
||||
pixnum=w_size[0]*w_size[1]
|
||||
# send_message.emit('pixnum:'pixnum)
|
||||
max_diff = 0
|
||||
min_diff = math.inf
|
||||
win_h=w_size[0]//2 #half hight of window
|
||||
win_w=w_size[1]//2 #half width of window
|
||||
a=[[(i+1)**j for j in range(n+1)] for i in range(pixnum)]
|
||||
A=np.array(a).astype(np.float64)#
|
||||
|
||||
k_=np.array(range(1,n+1))
|
||||
df1=np.zeros(pixnum).astype(np.float64)
|
||||
df2=np.zeros(pixnum).astype(np.float64)
|
||||
|
||||
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])
|
||||
block_data1 = ds1.ReadAsArray(*block_xy1, *block_size1)
|
||||
block_data2 = ds2.ReadAsArray(*block_xy2, *block_size2)
|
||||
|
||||
if band == 1:
|
||||
block_data1 = block_data1[None, ...]
|
||||
block_data2 = block_data2[None, ...]
|
||||
# pdb.set_trace()
|
||||
else:
|
||||
block_data1=np.mean(block_data1,0)
|
||||
block_data2=np.mean(block_data2,0)
|
||||
block_diff=np.zeros(block_data1.shape).astype(np.float64)
|
||||
|
||||
for i in range(win_h,block_size1[1]-win_h):
|
||||
for j_ in range(win_w,block_size1[0]-win_w):
|
||||
pix=0
|
||||
|
||||
#get b
|
||||
# b1=block_data[i+win_h:i+win_h] c in range(j_-win_w,j_+win_w+1)
|
||||
b1=block_data1[i-win_h:i+win_h+1,j_-win_w:j_+win_w+1]
|
||||
b2=block_data2[i-win_h:i+win_h+1,j_-win_w:j_+win_w+1]
|
||||
b1=[b if (r+1)//2 else b[::-1] for r,b in enumerate(b1)]
|
||||
b2=[b if (r+1)//2 else b[::-1] for r,b in enumerate(b2)]
|
||||
b1=np.expand_dims(np.concatenate(b1,0),1)
|
||||
b2=np.expand_dims(np.concatenate(b2,0),1)
|
||||
|
||||
x1=np.squeeze(np.linalg.pinv(A).dot(b1))
|
||||
x2=np.squeeze(np.linalg.pinv(A).dot(b2))
|
||||
#df
|
||||
k_=range(1,n+1)
|
||||
for pix in range(1,pixnum+1):
|
||||
df1[pix-1]=x1[1:n+1].dot(np.array([k*(pix**(k-1)) for k in k_]))
|
||||
df2[pix-1]=x2[1:n+1].dot(np.array([k*(pix**(k-1)) for k in k_]))
|
||||
|
||||
#distance 欧式距离
|
||||
block_diff[i][j_]=np.dot(df1-df2,df1-df2)**0.5
|
||||
|
||||
min_diff = min(min_diff, block_diff[block_diff > 0].min())
|
||||
max_diff = max(max_diff, block_diff.max())
|
||||
out_ds.GetRasterBand(1).WriteArray(block_diff, *block_xy)
|
||||
|
||||
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('归一化概率中...')
|
||||
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('LSTS法计算完成')
|
||||
return out_normal_tif
|
||||
|
||||
|
||||
@UNSUPER_CD.register
|
||||
class CVAAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'CVA'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
|
||||
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
|
||||
|
||||
|
||||
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])
|
||||
block_data1 = ds1.ReadAsArray(*block_xy1, *block_size1)
|
||||
block_data2 = ds2.ReadAsArray(*block_xy2, *block_size2)
|
||||
|
||||
if band == 1:
|
||||
block_data1 = block_data1[None, ...]
|
||||
block_data2 = block_data2[None, ...]
|
||||
# pdb.set_trace()
|
||||
block_diff=np.sum((block_data1-block_data2)**2,0)**0.5
|
||||
min_diff = min(min_diff, block_diff[block_diff > 0].min())
|
||||
max_diff = max(max_diff, block_diff.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('归一化概率中...')
|
||||
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
|
||||
|
||||
@UNSUPER_CD.register
|
||||
class ACDAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'ACD'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
# send_message.emit = print
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
|
||||
|
||||
#运算
|
||||
send_message.emit('开始ACD计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
ACD(temp_tif1,temp_tif2,out_normal_tif)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
|
||||
return out_normal_tif
|
||||
|
||||
|
||||
@UNSUPER_CD.register
|
||||
class AHTAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'AHT'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
|
||||
|
||||
#运算
|
||||
send_message.emit('开始AHT计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
AHT(temp_tif1,temp_tif2,out_normal_tif)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
|
||||
return out_normal_tif
|
||||
|
||||
|
||||
@UNSUPER_CD.register
|
||||
class OCDAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'OCD'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
|
||||
|
||||
#运算
|
||||
send_message.emit('开始OCD计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
OCD(temp_tif1,temp_tif2,out_normal_tif,Project().other_path)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
|
||||
return out_normal_tif
|
||||
|
||||
@UNSUPER_CD.register
|
||||
class LHBAAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'LHBA'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
#运算
|
||||
send_message.emit('开始LHBA计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
LHBA(temp_tif1,temp_tif2,out_normal_tif)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
return out_normal_tif
|
||||
|
||||
|
||||
@UNSUPER_CD.register
|
||||
class SHAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'SH'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
|
||||
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
#运算
|
||||
send_message.emit('开始SH计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
SH(temp_tif1,temp_tif2,out_normal_tif)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
return out_normal_tif
|
1
plugins/veg_method/__init__.py
Normal file
1
plugins/veg_method/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from veg_method.main import *
|
226
plugins/veg_method/main.py
Normal file
226
plugins/veg_method/main.py
Normal file
@ -0,0 +1,226 @@
|
||||
from functools import partial
|
||||
from threading import Thread
|
||||
from plugins.misc.main import AlgFrontend
|
||||
from rscder.gui.actions import ActionManager
|
||||
from rscder.plugins.basic import BasicPlugin
|
||||
from PyQt5.QtWidgets import QAction, QToolBar, QMenu, QDialog, QHBoxLayout, QVBoxLayout, QPushButton,QWidget,QLabel,QLineEdit,QPushButton,QComboBox,QDialogButtonBox
|
||||
|
||||
from rscder.gui.layercombox import PairLayerCombox
|
||||
from rscder.utils.icons import IconInstance
|
||||
from filter_collection import FILTER
|
||||
from .scripts import VEG_CD
|
||||
from thres import THRES
|
||||
from misc import table_layer, AlgSelectWidget
|
||||
from follow import FOLLOW
|
||||
|
||||
class VegtationCDMethod(QDialog):
|
||||
def __init__(self,parent=None, alg:AlgFrontend=None):
|
||||
super(VegtationCDMethod, self).__init__(parent)
|
||||
self.alg = alg
|
||||
self.setWindowTitle('植被变化检测:{}'.format(alg.get_name()))
|
||||
self.setWindowIcon(IconInstance().LOGO)
|
||||
self.initUI()
|
||||
self.setMinimumWidth(500)
|
||||
|
||||
def initUI(self):
|
||||
#图层
|
||||
self.layer_combox = PairLayerCombox(self)
|
||||
layerbox = QHBoxLayout()
|
||||
layerbox.addWidget(self.layer_combox)
|
||||
|
||||
self.filter_select = AlgSelectWidget(self, FILTER)
|
||||
self.param_widget = self.alg.get_widget(self)
|
||||
self.unsupervised_menu = self.param_widget
|
||||
self.thres_select = AlgSelectWidget(self, THRES)
|
||||
|
||||
self.ok_button = QPushButton('确定', self)
|
||||
self.ok_button.setIcon(IconInstance().OK)
|
||||
self.ok_button.clicked.connect(self.accept)
|
||||
self.ok_button.setDefault(True)
|
||||
|
||||
self.cancel_button = QPushButton('取消', self)
|
||||
self.cancel_button.setIcon(IconInstance().CANCEL)
|
||||
self.cancel_button.clicked.connect(self.reject)
|
||||
self.cancel_button.setDefault(False)
|
||||
buttonbox=QDialogButtonBox(self)
|
||||
buttonbox.addButton(self.ok_button,QDialogButtonBox.NoRole)
|
||||
buttonbox.addButton(self.cancel_button,QDialogButtonBox.NoRole)
|
||||
buttonbox.setCenterButtons(True)
|
||||
|
||||
totalvlayout=QVBoxLayout()
|
||||
totalvlayout.addLayout(layerbox)
|
||||
totalvlayout.addWidget(self.filter_select)
|
||||
if self.param_widget is not None:
|
||||
totalvlayout.addWidget(self.param_widget)
|
||||
totalvlayout.addWidget(self.thres_select)
|
||||
totalvlayout.addStretch(1)
|
||||
hbox = QHBoxLayout()
|
||||
hbox.addStretch(1)
|
||||
hbox.addWidget(buttonbox)
|
||||
totalvlayout.addLayout(hbox)
|
||||
# totalvlayout.addStretch()
|
||||
|
||||
self.setLayout(totalvlayout)
|
||||
|
||||
@FOLLOW.register
|
||||
class VegetationCDFollow(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return '植被变化检测'
|
||||
|
||||
@staticmethod
|
||||
def get_icon():
|
||||
return IconInstance().UNSUPERVISED
|
||||
|
||||
@staticmethod
|
||||
def get_widget(parent=None):
|
||||
widget = QWidget(parent)
|
||||
layer_combox = PairLayerCombox(widget)
|
||||
layer_combox.setObjectName('layer_combox')
|
||||
|
||||
filter_select = AlgSelectWidget(widget, FILTER)
|
||||
filter_select.setObjectName('filter_select')
|
||||
unsupervised_select = AlgSelectWidget(widget, VEG_CD)
|
||||
unsupervised_select.setObjectName('unsupervised_select')
|
||||
thres_select = AlgSelectWidget(widget, THRES)
|
||||
thres_select.setObjectName('thres_select')
|
||||
|
||||
totalvlayout=QVBoxLayout()
|
||||
totalvlayout.addWidget(layer_combox)
|
||||
totalvlayout.addWidget(filter_select)
|
||||
totalvlayout.addWidget(unsupervised_select)
|
||||
totalvlayout.addWidget(thres_select)
|
||||
totalvlayout.addStretch()
|
||||
|
||||
widget.setLayout(totalvlayout)
|
||||
|
||||
return widget
|
||||
|
||||
@staticmethod
|
||||
def get_params(widget:QWidget=None):
|
||||
if widget is None:
|
||||
return dict()
|
||||
|
||||
layer_combox = widget.findChild(PairLayerCombox, 'layer_combox')
|
||||
filter_select = widget.findChild(AlgSelectWidget, 'filter_select')
|
||||
unsupervised_select = widget.findChild(AlgSelectWidget, 'unsupervised_select')
|
||||
thres_select = widget.findChild(AlgSelectWidget, 'thres_select')
|
||||
|
||||
layer1=layer_combox.layer1
|
||||
pth1 = layer_combox.layer1.path
|
||||
pth2 = layer_combox.layer2.path
|
||||
|
||||
falg, fparams = filter_select.get_alg_and_params()
|
||||
cdalg, cdparams = unsupervised_select.get_alg_and_params()
|
||||
thalg, thparams = thres_select.get_alg_and_params()
|
||||
|
||||
if cdalg is None or thalg is None:
|
||||
return dict()
|
||||
|
||||
return dict(
|
||||
layer1=layer1,
|
||||
pth1 = pth1,
|
||||
pth2 = pth2,
|
||||
falg = falg,
|
||||
fparams = fparams,
|
||||
cdalg = cdalg,
|
||||
cdparams = cdparams,
|
||||
thalg = thalg,
|
||||
thparams = thparams,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def run_alg(layer1=None,
|
||||
pth1 = None,
|
||||
pth2 = None,
|
||||
falg = None,
|
||||
fparams = None,
|
||||
cdalg = None,
|
||||
cdparams = None,
|
||||
thalg = None,
|
||||
thparams = None,
|
||||
send_message = None):
|
||||
|
||||
if cdalg is None or thalg is None:
|
||||
return
|
||||
|
||||
name = layer1.name
|
||||
|
||||
if falg is not None:
|
||||
pth1 = falg.run_alg(pth1, name=name, send_message= send_message, **fparams)
|
||||
pth2 = falg.run_alg(pth2, name=name, send_message= send_message, **fparams)
|
||||
|
||||
|
||||
cdpth = cdalg.run_alg(pth1, pth2, layer1.layer_parent, send_message= send_message,**cdparams)
|
||||
thpth = thalg.run_alg(cdpth, name=name, send_message= send_message, **thparams)
|
||||
|
||||
table_layer(thpth,layer1,name, send_message)
|
||||
|
||||
|
||||
|
||||
|
||||
class VegtationPlugin(BasicPlugin):
|
||||
|
||||
|
||||
@staticmethod
|
||||
def info():
|
||||
return {
|
||||
'name': 'VegtationPlugin',
|
||||
'description': 'VegtationPlugin',
|
||||
'author': 'RSCDER',
|
||||
'version': '1.0.0',
|
||||
}
|
||||
|
||||
def set_action(self):
|
||||
veg_menu = ActionManager().veg_menu
|
||||
# veg_menu.setIcon(IconInstance().UNSUPERVISED)
|
||||
# ActionManager().veg_menu.addMenu(veg_menu)
|
||||
|
||||
for key in VEG_CD.keys():
|
||||
alg:AlgFrontend = VEG_CD[key]
|
||||
if alg.get_name() is None:
|
||||
name = key
|
||||
else:
|
||||
name = alg.get_name()
|
||||
|
||||
action = QAction(name, veg_menu)
|
||||
func = partial(self.run_cd, alg)
|
||||
action.triggered.connect(func)
|
||||
|
||||
veg_menu.addAction(action)
|
||||
|
||||
|
||||
def run_cd(self, alg):
|
||||
dialog = VegtationCDMethod(self.mainwindow, alg)
|
||||
dialog.show()
|
||||
|
||||
if dialog.exec_() == QDialog.Accepted:
|
||||
t = Thread(target=self.run_cd_alg, args=(dialog,))
|
||||
t.start()
|
||||
|
||||
def run_cd_alg(self, w:VegtationCDMethod):
|
||||
|
||||
layer1=w.layer_combox.layer1
|
||||
pth1 = w.layer_combox.layer1.path
|
||||
pth2 = w.layer_combox.layer2.path
|
||||
name = layer1.layer_parent.name
|
||||
|
||||
falg, fparams = w.filter_select.get_alg_and_params()
|
||||
cdalg = w.alg
|
||||
cdparams = w.alg.get_params()
|
||||
thalg, thparams = w.thres_select.get_alg_and_params()
|
||||
|
||||
if cdalg is None or thalg is None:
|
||||
return
|
||||
|
||||
if falg is not None:
|
||||
pth1 = falg.run_alg(pth1, name=name, send_message=self.send_message, **fparams)
|
||||
pth2 = falg.run_alg(pth2, name=name, send_message=self.send_message, **fparams)
|
||||
|
||||
|
||||
cdpth = cdalg.run_alg(pth1, pth2, layer1.layer_parent, send_message=self.send_message,**cdparams)
|
||||
thpth = thalg.run_alg(cdpth, name=name, send_message=self.send_message, **thparams)
|
||||
|
||||
table_layer(thpth,layer1,name,self.send_message)
|
||||
|
455
plugins/veg_method/pic.py
Normal file
455
plugins/veg_method/pic.py
Normal file
@ -0,0 +1,455 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Resource object code
|
||||
#
|
||||
# Created by: The Resource Compiler for PyQt5 (Qt v5.12.9)
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore
|
||||
|
||||
qt_resource_data = b"\
|
||||
\x00\x00\x05\x32\
|
||||
\x3c\
|
||||
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
|
||||
\x30\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\x6e\
|
||||
\x6f\x22\x3f\x3e\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\x20\x73\x76\
|
||||
\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\x57\x33\x43\
|
||||
\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\x2f\x2f\x45\
|
||||
\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
|
||||
\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\x73\x2f\x53\
|
||||
\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\x67\x31\x31\
|
||||
\x2e\x64\x74\x64\x22\x3e\x3c\x73\x76\x67\x20\x74\x3d\x22\x31\x36\
|
||||
\x35\x35\x31\x30\x35\x33\x34\x38\x31\x31\x38\x22\x20\x63\x6c\x61\
|
||||
\x73\x73\x3d\x22\x69\x63\x6f\x6e\x22\x20\x76\x69\x65\x77\x42\x6f\
|
||||
\x78\x3d\x22\x30\x20\x30\x20\x31\x30\x32\x34\x20\x31\x30\x32\x34\
|
||||
\x22\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\
|
||||
\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
|
||||
\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
|
||||
\x67\x22\x20\x70\x2d\x69\x64\x3d\x22\x32\x31\x33\x37\x22\x20\x78\
|
||||
\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\
|
||||
\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
|
||||
\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x77\x69\x64\x74\x68\x3d\
|
||||
\x22\x31\x32\x38\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x31\x32\
|
||||
\x38\x22\x3e\x3c\x64\x65\x66\x73\x3e\x3c\x73\x74\x79\x6c\x65\x20\
|
||||
\x74\x79\x70\x65\x3d\x22\x74\x65\x78\x74\x2f\x63\x73\x73\x22\x3e\
|
||||
\x40\x66\x6f\x6e\x74\x2d\x66\x61\x63\x65\x20\x7b\x20\x66\x6f\x6e\
|
||||
\x74\x2d\x66\x61\x6d\x69\x6c\x79\x3a\x20\x66\x65\x65\x64\x62\x61\
|
||||
\x63\x6b\x2d\x69\x63\x6f\x6e\x66\x6f\x6e\x74\x3b\x20\x73\x72\x63\
|
||||
\x3a\x20\x75\x72\x6c\x28\x22\x2f\x2f\x61\x74\x2e\x61\x6c\x69\x63\
|
||||
\x64\x6e\x2e\x63\x6f\x6d\x2f\x74\x2f\x66\x6f\x6e\x74\x5f\x31\x30\
|
||||
\x33\x31\x31\x35\x38\x5f\x75\x36\x39\x77\x38\x79\x68\x78\x64\x75\
|
||||
\x2e\x77\x6f\x66\x66\x32\x3f\x74\x3d\x31\x36\x33\x30\x30\x33\x33\
|
||||
\x37\x35\x39\x39\x34\x34\x22\x29\x20\x66\x6f\x72\x6d\x61\x74\x28\
|
||||
\x22\x77\x6f\x66\x66\x32\x22\x29\x2c\x20\x75\x72\x6c\x28\x22\x2f\
|
||||
\x2f\x61\x74\x2e\x61\x6c\x69\x63\x64\x6e\x2e\x63\x6f\x6d\x2f\x74\
|
||||
\x2f\x66\x6f\x6e\x74\x5f\x31\x30\x33\x31\x31\x35\x38\x5f\x75\x36\
|
||||
\x39\x77\x38\x79\x68\x78\x64\x75\x2e\x77\x6f\x66\x66\x3f\x74\x3d\
|
||||
\x31\x36\x33\x30\x30\x33\x33\x37\x35\x39\x39\x34\x34\x22\x29\x20\
|
||||
\x66\x6f\x72\x6d\x61\x74\x28\x22\x77\x6f\x66\x66\x22\x29\x2c\x20\
|
||||
\x75\x72\x6c\x28\x22\x2f\x2f\x61\x74\x2e\x61\x6c\x69\x63\x64\x6e\
|
||||
\x2e\x63\x6f\x6d\x2f\x74\x2f\x66\x6f\x6e\x74\x5f\x31\x30\x33\x31\
|
||||
\x31\x35\x38\x5f\x75\x36\x39\x77\x38\x79\x68\x78\x64\x75\x2e\x74\
|
||||
\x74\x66\x3f\x74\x3d\x31\x36\x33\x30\x30\x33\x33\x37\x35\x39\x39\
|
||||
\x34\x34\x22\x29\x20\x66\x6f\x72\x6d\x61\x74\x28\x22\x74\x72\x75\
|
||||
\x65\x74\x79\x70\x65\x22\x29\x3b\x20\x7d\x0a\x3c\x2f\x73\x74\x79\
|
||||
\x6c\x65\x3e\x3c\x2f\x64\x65\x66\x73\x3e\x3c\x70\x61\x74\x68\x20\
|
||||
\x64\x3d\x22\x4d\x33\x31\x32\x2e\x38\x38\x38\x38\x38\x39\x20\x39\
|
||||
\x39\x35\x2e\x35\x35\x35\x35\x35\x36\x63\x2d\x31\x37\x2e\x30\x36\
|
||||
\x36\x36\x36\x37\x20\x30\x2d\x32\x38\x2e\x34\x34\x34\x34\x34\x34\
|
||||
\x2d\x35\x2e\x36\x38\x38\x38\x38\x39\x2d\x33\x39\x2e\x38\x32\x32\
|
||||
\x32\x32\x32\x2d\x31\x37\x2e\x30\x36\x36\x36\x36\x37\x2d\x32\x32\
|
||||
\x2e\x37\x35\x35\x35\x35\x36\x2d\x32\x32\x2e\x37\x35\x35\x35\x35\
|
||||
\x36\x2d\x31\x37\x2e\x30\x36\x36\x36\x36\x37\x2d\x35\x36\x2e\x38\
|
||||
\x38\x38\x38\x38\x39\x20\x35\x2e\x36\x38\x38\x38\x38\x39\x2d\x37\
|
||||
\x39\x2e\x36\x34\x34\x34\x34\x35\x6c\x33\x36\x34\x2e\x30\x38\x38\
|
||||
\x38\x38\x38\x2d\x33\x32\x39\x2e\x39\x35\x35\x35\x35\x35\x63\x31\
|
||||
\x31\x2e\x33\x37\x37\x37\x37\x38\x2d\x31\x31\x2e\x33\x37\x37\x37\
|
||||
\x37\x38\x20\x31\x37\x2e\x30\x36\x36\x36\x36\x37\x2d\x32\x32\x2e\
|
||||
\x37\x35\x35\x35\x35\x36\x20\x31\x37\x2e\x30\x36\x36\x36\x36\x37\
|
||||
\x2d\x33\x34\x2e\x31\x33\x33\x33\x33\x33\x20\x30\x2d\x31\x31\x2e\
|
||||
\x33\x37\x37\x37\x37\x38\x2d\x35\x2e\x36\x38\x38\x38\x38\x39\x2d\
|
||||
\x32\x32\x2e\x37\x35\x35\x35\x35\x36\x2d\x31\x37\x2e\x30\x36\x36\
|
||||
\x36\x36\x37\x2d\x33\x34\x2e\x31\x33\x33\x33\x33\x34\x4c\x32\x37\
|
||||
\x33\x2e\x30\x36\x36\x36\x36\x37\x20\x31\x38\x37\x2e\x37\x33\x33\
|
||||
\x33\x33\x33\x63\x2d\x32\x32\x2e\x37\x35\x35\x35\x35\x36\x2d\x32\
|
||||
\x32\x2e\x37\x35\x35\x35\x35\x36\x2d\x32\x38\x2e\x34\x34\x34\x34\
|
||||
\x34\x34\x2d\x35\x36\x2e\x38\x38\x38\x38\x38\x39\x2d\x35\x2e\x36\
|
||||
\x38\x38\x38\x38\x39\x2d\x37\x39\x2e\x36\x34\x34\x34\x34\x34\x20\
|
||||
\x32\x32\x2e\x37\x35\x35\x35\x35\x36\x2d\x32\x32\x2e\x37\x35\x35\
|
||||
\x35\x35\x36\x20\x35\x36\x2e\x38\x38\x38\x38\x38\x39\x2d\x32\x38\
|
||||
\x2e\x34\x34\x34\x34\x34\x34\x20\x37\x39\x2e\x36\x34\x34\x34\x34\
|
||||
\x34\x2d\x35\x2e\x36\x38\x38\x38\x38\x39\x6c\x33\x36\x34\x2e\x30\
|
||||
\x38\x38\x38\x38\x39\x20\x33\x31\x32\x2e\x38\x38\x38\x38\x38\x39\
|
||||
\x63\x33\x34\x2e\x31\x33\x33\x33\x33\x33\x20\x32\x38\x2e\x34\x34\
|
||||
\x34\x34\x34\x34\x20\x35\x36\x2e\x38\x38\x38\x38\x38\x39\x20\x37\
|
||||
\x33\x2e\x39\x35\x35\x35\x35\x36\x20\x35\x36\x2e\x38\x38\x38\x38\
|
||||
\x38\x39\x20\x31\x31\x39\x2e\x34\x36\x36\x36\x36\x37\x73\x2d\x31\
|
||||
\x37\x2e\x30\x36\x36\x36\x36\x37\x20\x38\x35\x2e\x33\x33\x33\x33\
|
||||
\x33\x33\x2d\x35\x31\x2e\x32\x20\x31\x31\x39\x2e\x34\x36\x36\x36\
|
||||
\x36\x36\x6c\x2d\x33\x36\x34\x2e\x30\x38\x38\x38\x38\x39\x20\x33\
|
||||
\x32\x39\x2e\x39\x35\x35\x35\x35\x36\x63\x2d\x31\x31\x2e\x33\x37\
|
||||
\x37\x37\x37\x38\x20\x35\x2e\x36\x38\x38\x38\x38\x39\x2d\x32\x38\
|
||||
\x2e\x34\x34\x34\x34\x34\x34\x20\x31\x31\x2e\x33\x37\x37\x37\x37\
|
||||
\x38\x2d\x33\x39\x2e\x38\x32\x32\x32\x32\x32\x20\x31\x31\x2e\x33\
|
||||
\x37\x37\x37\x37\x38\x7a\x22\x20\x70\x2d\x69\x64\x3d\x22\x32\x31\
|
||||
\x33\x38\x22\x3e\x3c\x2f\x70\x61\x74\x68\x3e\x3c\x2f\x73\x76\x67\
|
||||
\x3e\
|
||||
\x00\x00\x04\xf8\
|
||||
\x89\
|
||||
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||
\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3\x3e\x61\xcb\
|
||||
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x04\
|
||||
\xb2\x49\x44\x41\x54\x78\x5e\xed\x99\xef\x8e\x15\x45\x10\xc5\xab\
|
||||
\xf7\x71\xf0\x31\xa6\x7b\xdf\x40\xfc\x13\x10\x54\xa2\x04\x95\x68\
|
||||
\x50\x09\x2a\x51\x09\x2a\x41\x45\x09\x2a\x41\x82\x88\x4a\x80\x7d\
|
||||
\x85\xa9\x7e\x0c\x7d\x9c\x5b\x66\xd4\xd5\x05\x2e\x5b\x3b\xe5\x07\
|
||||
\xee\x9c\x3a\xfd\x75\xeb\x64\x73\xce\xf9\xa5\x7a\x66\x6e\x11\x9e\
|
||||
\xd4\x09\x94\xd4\xee\x69\x5e\x08\x40\x72\x08\x08\x00\x01\x48\x9e\
|
||||
\x40\x72\xfb\xdc\x00\x04\x20\x79\x02\xc9\xed\x73\x03\x10\x80\xe4\
|
||||
\x09\x24\xb7\xcf\x0d\x40\x00\x92\x27\x90\xdc\x3e\x37\x00\x01\x48\
|
||||
\x9e\x40\x72\xfb\xdc\x00\x04\x20\x79\x02\xc9\xed\x73\x03\x10\x80\
|
||||
\xe4\x09\x24\xb7\xcf\x0d\x40\x00\x92\x27\x90\xdc\x3e\x37\x00\x01\
|
||||
\x48\x9e\x40\x72\xfb\xdc\x00\x04\x20\x79\x02\xc9\xed\x73\x03\x10\
|
||||
\x80\xe4\x09\x24\xb7\xcf\x0d\x40\x00\x92\x27\x90\xdc\x3e\x37\x00\
|
||||
\x01\x48\x9e\x40\x72\xfb\xdc\x00\x04\x20\x79\x02\xc9\xed\x43\x6f\
|
||||
\x80\x61\x18\x0e\xf5\xde\xff\x48\xde\xf1\xbe\xf6\x61\x01\x98\xca\
|
||||
\xdf\xda\xda\xda\x59\xad\x56\x87\x09\xc1\x93\x19\x80\x04\x60\xb7\
|
||||
\x7c\x33\x7b\xa6\x94\xf2\x3b\x21\x48\x04\xc0\xde\xf2\x77\x6d\x13\
|
||||
\x82\x24\x00\xac\x2b\x9f\x10\xec\xff\x04\x04\x73\x05\xec\x57\x3e\
|
||||
\x21\x00\xdf\x00\x07\x29\x9f\x10\xac\x87\x60\xf1\x1b\x60\x4e\xf9\
|
||||
\x84\xe0\x71\x08\x16\x0d\x40\xa4\x7c\x42\xf0\x30\x04\x8b\x06\x60\
|
||||
\xb2\x42\x08\xfe\xdf\x67\xae\xc5\x03\x40\x08\x08\xc0\x5f\x09\x70\
|
||||
\x13\xc4\x40\x80\xd8\x00\xbb\xd6\x09\xc1\x7c\x08\xa0\x00\xe0\x26\
|
||||
\x20\x00\xbc\x0e\x66\x32\x00\xb7\x01\x78\x1d\xcc\x23\x00\x16\x00\
|
||||
\x5e\x07\x07\x03\x01\x1a\x00\x42\xe0\x43\x00\x0f\x00\x21\x48\xf2\
|
||||
\x6b\xa0\xc7\x3a\x5f\x11\x41\x7f\x0c\xf2\x8a\xdf\xfb\x77\x42\x00\
|
||||
\xf6\x63\xd0\x9c\xf2\xf9\x76\xc0\x0d\xf0\x6f\x02\xdc\x04\xff\xc1\
|
||||
\x90\xe2\x21\x70\x1d\xfb\x84\xe0\xef\x54\xd2\x02\xc0\xb7\x03\x02\
|
||||
\xc0\xcf\xc6\xd9\x37\x00\x1f\x0c\x93\x5f\x01\x7c\x45\x24\x00\x0f\
|
||||
\x3d\x1f\x66\x7c\x30\x4c\xfd\x10\xc8\xb7\x03\x6e\x80\xb5\x5f\x47\
|
||||
\x6a\xad\x1f\x8b\xc8\x27\x91\x0f\x4d\x22\xf2\xa9\xaa\x46\xb5\xc1\
|
||||
\x7f\x19\x97\x71\x03\x3c\x92\xdd\x30\x0c\xe7\x4b\x29\x17\x22\x91\
|
||||
\x9a\xd9\x85\xde\xfb\x04\xcf\x62\x0e\x01\xd8\x53\x55\xad\xf5\x43\
|
||||
\x11\xb9\x18\x6c\xef\xa2\xaa\x9e\x0f\x6a\x9f\x9a\x8c\x00\xfc\x13\
|
||||
\xfd\x30\x0c\xe7\x4a\x29\x9f\x07\x9b\xf8\x4c\x55\x3f\x0a\x6a\x9f\
|
||||
\xaa\x8c\x00\x88\x48\x6b\xed\xac\x99\x5d\x8a\x34\x51\x4a\xf9\x62\
|
||||
\x1c\xc7\x0f\x22\xda\x4d\xd0\xa4\x07\xa0\xd6\xfa\x9e\x88\x5c\x0e\
|
||||
\x96\x71\x49\x55\xcf\x05\xb5\x1b\x21\x4b\x0d\x40\x6b\xed\x8c\x99\
|
||||
\x7d\x15\x69\xc2\xcc\x2e\xf7\xde\xcf\x46\xb4\x9b\xa4\x49\x0b\x40\
|
||||
\xad\xf5\x1d\x11\xb9\x12\x2c\xe3\x4b\x55\x7d\x3f\xa8\xdd\x28\x59\
|
||||
\x4a\x00\x6a\xad\x6f\x8b\xc8\x37\x91\x26\xcc\xec\xeb\xde\xfb\xbb\
|
||||
\x11\xed\x26\x6a\xd2\x01\x30\x0c\xc3\xe9\x52\xca\xd5\x48\x19\xa5\
|
||||
\x94\x2b\xe3\x38\x9e\x89\x68\x37\x55\x93\x0a\x80\x5a\xeb\x9b\x22\
|
||||
\x72\x2d\x58\xc6\xb7\xaa\x3a\x5d\x1b\x50\x27\x0d\x00\xc3\x30\x9c\
|
||||
\x2a\xa5\x7c\x1f\x69\xcf\xcc\xae\xf6\xde\xa7\x6b\x03\xee\xa4\x00\
|
||||
\xa0\xb5\x76\xd2\xcc\xae\x07\xdb\xbb\xa6\xaa\xa7\x83\xda\x8d\x97\
|
||||
\xc1\x03\x50\x6b\x7d\x4d\x44\x6e\x04\x9b\xf8\x4e\x55\xdf\x0a\x6a\
|
||||
\x17\x21\x83\x06\xa0\xb5\x76\xc2\xcc\x6e\x06\x9b\xf8\x41\x55\xdf\
|
||||
\x08\x6a\x17\x23\x83\x05\xa0\xd6\xfa\x8a\x88\xdc\x0a\x36\x71\x5d\
|
||||
\x55\x4f\x05\xb5\x8b\x92\x41\x02\xd0\x5a\x3b\x6e\x66\xb7\x23\x4d\
|
||||
\x98\xd9\x8d\xde\xfb\xc9\x88\x76\x89\x1a\x38\x00\x6a\xad\x2f\x89\
|
||||
\xc8\x9d\x60\x19\x3f\xaa\xea\xeb\x41\xed\x22\x65\x50\x00\xb4\xd6\
|
||||
\x8e\x98\xd9\xaf\xc1\x26\x6e\xaa\xea\xf4\xc0\x98\xea\xc0\x00\x50\
|
||||
\x6b\x7d\x51\x44\xee\x46\xda\x2b\xa5\xdc\x1a\xc7\xf1\x44\x44\xbb\
|
||||
\x74\x0d\x04\x00\xdb\xdb\xdb\xcf\xaf\x56\xab\x7b\xc1\x32\x7e\x52\
|
||||
\xd5\x57\x83\xda\xc5\xcb\x16\x0f\x40\xad\xf5\xb0\x88\x3c\x88\x34\
|
||||
\x61\x66\x3f\xf7\xde\x5f\x8e\x68\x51\x34\x08\x00\xec\x88\xc8\xb3\
|
||||
\x73\x0b\x29\xa5\xdc\x19\xc7\xf1\xf8\x5c\x1d\xda\xfc\xe2\x01\x98\
|
||||
\x0a\xa9\xb5\xce\x85\xe0\x17\x55\x3d\x86\x56\x66\xc4\x0f\x04\x00\
|
||||
\x73\x20\x30\xb3\xdf\x7a\xef\x47\x23\x61\x21\x6a\x60\x00\x38\x20\
|
||||
\x04\x77\x55\xf5\x08\x62\x91\x51\x4f\x50\x00\x38\x10\xdc\x53\xd5\
|
||||
\xe9\x55\x91\x67\x4f\x02\x70\x00\xac\x83\xa0\x94\x72\x7f\x1c\xc7\
|
||||
\x17\xd8\xfc\xe3\x09\x40\x02\xf0\x08\x04\x3b\xaa\xfa\x1c\xcb\x5f\
|
||||
\x9f\x00\x2c\x00\xbb\x10\xa8\xea\xf4\x9d\x80\xe7\x09\x09\x40\x03\
|
||||
\xc0\xd6\xfd\x04\x08\x80\x9f\x11\xf4\x04\x01\x80\xae\xd7\x37\x47\
|
||||
\x00\xfc\x8c\xa0\x27\x08\x00\x74\xbd\xbe\x39\x02\xe0\x67\x04\x3d\
|
||||
\x41\x00\xa0\xeb\xf5\xcd\x11\x00\x3f\x23\xe8\x09\x02\x00\x5d\xaf\
|
||||
\x6f\x8e\x00\xf8\x19\x41\x4f\x10\x00\xe8\x7a\x7d\x73\x04\xc0\xcf\
|
||||
\x08\x7a\x82\x00\x40\xd7\xeb\x9b\x23\x00\x7e\x46\xd0\x13\x04\x00\
|
||||
\xba\x5e\xdf\x1c\x01\xf0\x33\x82\x9e\x20\x00\xd0\xf5\xfa\xe6\x08\
|
||||
\x80\x9f\x11\xf4\x04\x01\x80\xae\xd7\x37\x47\x00\xfc\x8c\xa0\x27\
|
||||
\x08\x00\x74\xbd\xbe\x39\x02\xe0\x67\x04\x3d\x41\x00\xa0\xeb\xf5\
|
||||
\xcd\x11\x00\x3f\x23\xe8\x09\x02\x00\x5d\xaf\x6f\x8e\x00\xf8\x19\
|
||||
\x41\x4f\x10\x00\xe8\x7a\x7d\x73\x04\xc0\xcf\x08\x7a\x82\x00\x40\
|
||||
\xd7\xeb\x9b\x23\x00\x7e\x46\xd0\x13\x04\x00\xba\x5e\xdf\x1c\x01\
|
||||
\xf0\x33\x82\x9e\x20\x00\xd0\xf5\xfa\xe6\x08\x80\x9f\x11\xf4\x04\
|
||||
\x01\x80\xae\xd7\x37\x47\x00\xfc\x8c\xa0\x27\x08\x00\x74\xbd\xbe\
|
||||
\xb9\x3f\x01\xc2\xa1\x1b\x9f\x9b\x5d\x0e\x95\x00\x00\x00\x00\x49\
|
||||
\x45\x4e\x44\xae\x42\x60\x82\
|
||||
\x00\x00\x05\x0d\
|
||||
\x3c\
|
||||
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
|
||||
\x30\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\x6e\
|
||||
\x6f\x22\x3f\x3e\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\x20\x73\x76\
|
||||
\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\x57\x33\x43\
|
||||
\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\x2f\x2f\x45\
|
||||
\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
|
||||
\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\x73\x2f\x53\
|
||||
\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\x67\x31\x31\
|
||||
\x2e\x64\x74\x64\x22\x3e\x3c\x73\x76\x67\x20\x74\x3d\x22\x31\x36\
|
||||
\x35\x35\x31\x30\x35\x33\x35\x33\x37\x31\x33\x22\x20\x63\x6c\x61\
|
||||
\x73\x73\x3d\x22\x69\x63\x6f\x6e\x22\x20\x76\x69\x65\x77\x42\x6f\
|
||||
\x78\x3d\x22\x30\x20\x30\x20\x31\x30\x32\x34\x20\x31\x30\x32\x34\
|
||||
\x22\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\
|
||||
\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
|
||||
\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
|
||||
\x67\x22\x20\x70\x2d\x69\x64\x3d\x22\x32\x32\x39\x32\x22\x20\x78\
|
||||
\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\
|
||||
\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\
|
||||
\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x77\x69\x64\x74\x68\x3d\
|
||||
\x22\x31\x32\x38\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x31\x32\
|
||||
\x38\x22\x3e\x3c\x64\x65\x66\x73\x3e\x3c\x73\x74\x79\x6c\x65\x20\
|
||||
\x74\x79\x70\x65\x3d\x22\x74\x65\x78\x74\x2f\x63\x73\x73\x22\x3e\
|
||||
\x40\x66\x6f\x6e\x74\x2d\x66\x61\x63\x65\x20\x7b\x20\x66\x6f\x6e\
|
||||
\x74\x2d\x66\x61\x6d\x69\x6c\x79\x3a\x20\x66\x65\x65\x64\x62\x61\
|
||||
\x63\x6b\x2d\x69\x63\x6f\x6e\x66\x6f\x6e\x74\x3b\x20\x73\x72\x63\
|
||||
\x3a\x20\x75\x72\x6c\x28\x22\x2f\x2f\x61\x74\x2e\x61\x6c\x69\x63\
|
||||
\x64\x6e\x2e\x63\x6f\x6d\x2f\x74\x2f\x66\x6f\x6e\x74\x5f\x31\x30\
|
||||
\x33\x31\x31\x35\x38\x5f\x75\x36\x39\x77\x38\x79\x68\x78\x64\x75\
|
||||
\x2e\x77\x6f\x66\x66\x32\x3f\x74\x3d\x31\x36\x33\x30\x30\x33\x33\
|
||||
\x37\x35\x39\x39\x34\x34\x22\x29\x20\x66\x6f\x72\x6d\x61\x74\x28\
|
||||
\x22\x77\x6f\x66\x66\x32\x22\x29\x2c\x20\x75\x72\x6c\x28\x22\x2f\
|
||||
\x2f\x61\x74\x2e\x61\x6c\x69\x63\x64\x6e\x2e\x63\x6f\x6d\x2f\x74\
|
||||
\x2f\x66\x6f\x6e\x74\x5f\x31\x30\x33\x31\x31\x35\x38\x5f\x75\x36\
|
||||
\x39\x77\x38\x79\x68\x78\x64\x75\x2e\x77\x6f\x66\x66\x3f\x74\x3d\
|
||||
\x31\x36\x33\x30\x30\x33\x33\x37\x35\x39\x39\x34\x34\x22\x29\x20\
|
||||
\x66\x6f\x72\x6d\x61\x74\x28\x22\x77\x6f\x66\x66\x22\x29\x2c\x20\
|
||||
\x75\x72\x6c\x28\x22\x2f\x2f\x61\x74\x2e\x61\x6c\x69\x63\x64\x6e\
|
||||
\x2e\x63\x6f\x6d\x2f\x74\x2f\x66\x6f\x6e\x74\x5f\x31\x30\x33\x31\
|
||||
\x31\x35\x38\x5f\x75\x36\x39\x77\x38\x79\x68\x78\x64\x75\x2e\x74\
|
||||
\x74\x66\x3f\x74\x3d\x31\x36\x33\x30\x30\x33\x33\x37\x35\x39\x39\
|
||||
\x34\x34\x22\x29\x20\x66\x6f\x72\x6d\x61\x74\x28\x22\x74\x72\x75\
|
||||
\x65\x74\x79\x70\x65\x22\x29\x3b\x20\x7d\x0a\x3c\x2f\x73\x74\x79\
|
||||
\x6c\x65\x3e\x3c\x2f\x64\x65\x66\x73\x3e\x3c\x70\x61\x74\x68\x20\
|
||||
\x64\x3d\x22\x4d\x35\x31\x37\x2e\x36\x38\x38\x38\x38\x39\x20\x37\
|
||||
\x39\x36\x2e\x34\x34\x34\x34\x34\x34\x63\x2d\x34\x35\x2e\x35\x31\
|
||||
\x31\x31\x31\x31\x20\x30\x2d\x38\x35\x2e\x33\x33\x33\x33\x33\x33\
|
||||
\x2d\x31\x37\x2e\x30\x36\x36\x36\x36\x37\x2d\x31\x31\x39\x2e\x34\
|
||||
\x36\x36\x36\x36\x37\x2d\x35\x31\x2e\x32\x4c\x37\x33\x2e\x39\x35\
|
||||
\x35\x35\x35\x36\x20\x33\x38\x31\x2e\x31\x35\x35\x35\x35\x36\x63\
|
||||
\x2d\x32\x32\x2e\x37\x35\x35\x35\x35\x36\x2d\x32\x32\x2e\x37\x35\
|
||||
\x35\x35\x35\x36\x2d\x31\x37\x2e\x30\x36\x36\x36\x36\x37\x2d\x35\
|
||||
\x36\x2e\x38\x38\x38\x38\x38\x39\x20\x35\x2e\x36\x38\x38\x38\x38\
|
||||
\x38\x2d\x37\x39\x2e\x36\x34\x34\x34\x34\x35\x20\x32\x32\x2e\x37\
|
||||
\x35\x35\x35\x35\x36\x2d\x32\x32\x2e\x37\x35\x35\x35\x35\x36\x20\
|
||||
\x35\x36\x2e\x38\x38\x38\x38\x38\x39\x2d\x31\x37\x2e\x30\x36\x36\
|
||||
\x36\x36\x37\x20\x37\x39\x2e\x36\x34\x34\x34\x34\x35\x20\x35\x2e\
|
||||
\x36\x38\x38\x38\x38\x39\x6c\x33\x32\x39\x2e\x39\x35\x35\x35\x35\
|
||||
\x35\x20\x33\x36\x34\x2e\x30\x38\x38\x38\x38\x39\x63\x35\x2e\x36\
|
||||
\x38\x38\x38\x38\x39\x20\x35\x2e\x36\x38\x38\x38\x38\x39\x20\x31\
|
||||
\x37\x2e\x30\x36\x36\x36\x36\x37\x20\x31\x31\x2e\x33\x37\x37\x37\
|
||||
\x37\x38\x20\x32\x38\x2e\x34\x34\x34\x34\x34\x35\x20\x31\x31\x2e\
|
||||
\x33\x37\x37\x37\x37\x38\x73\x32\x32\x2e\x37\x35\x35\x35\x35\x36\
|
||||
\x2d\x35\x2e\x36\x38\x38\x38\x38\x39\x20\x33\x34\x2e\x31\x33\x33\
|
||||
\x33\x33\x33\x2d\x31\x37\x2e\x30\x36\x36\x36\x36\x37\x6c\x33\x31\
|
||||
\x32\x2e\x38\x38\x38\x38\x38\x39\x2d\x33\x36\x34\x2e\x30\x38\x38\
|
||||
\x38\x38\x39\x63\x32\x32\x2e\x37\x35\x35\x35\x35\x36\x2d\x32\x32\
|
||||
\x2e\x37\x35\x35\x35\x35\x36\x20\x35\x36\x2e\x38\x38\x38\x38\x38\
|
||||
\x39\x2d\x32\x38\x2e\x34\x34\x34\x34\x34\x34\x20\x37\x39\x2e\x36\
|
||||
\x34\x34\x34\x34\x35\x2d\x35\x2e\x36\x38\x38\x38\x38\x39\x20\x32\
|
||||
\x32\x2e\x37\x35\x35\x35\x35\x36\x20\x32\x32\x2e\x37\x35\x35\x35\
|
||||
\x35\x36\x20\x32\x38\x2e\x34\x34\x34\x34\x34\x34\x20\x35\x36\x2e\
|
||||
\x38\x38\x38\x38\x38\x39\x20\x35\x2e\x36\x38\x38\x38\x38\x38\x20\
|
||||
\x37\x39\x2e\x36\x34\x34\x34\x34\x35\x4c\x36\x33\x37\x2e\x31\x35\
|
||||
\x35\x35\x35\x36\x20\x37\x33\x39\x2e\x35\x35\x35\x35\x35\x36\x63\
|
||||
\x2d\x32\x38\x2e\x34\x34\x34\x34\x34\x34\x20\x33\x39\x2e\x38\x32\
|
||||
\x32\x32\x32\x32\x2d\x36\x38\x2e\x32\x36\x36\x36\x36\x37\x20\x35\
|
||||
\x36\x2e\x38\x38\x38\x38\x38\x39\x2d\x31\x31\x39\x2e\x34\x36\x36\
|
||||
\x36\x36\x37\x20\x35\x36\x2e\x38\x38\x38\x38\x38\x38\x20\x35\x2e\
|
||||
\x36\x38\x38\x38\x38\x39\x20\x30\x20\x30\x20\x30\x20\x30\x20\x30\
|
||||
\x7a\x22\x20\x70\x2d\x69\x64\x3d\x22\x32\x32\x39\x33\x22\x3e\x3c\
|
||||
\x2f\x70\x61\x74\x68\x3e\x3c\x2f\x73\x76\x67\x3e\
|
||||
\x00\x00\x07\x08\
|
||||
\x89\
|
||||
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||
\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3\x3e\x61\xcb\
|
||||
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x06\
|
||||
\xc2\x49\x44\x41\x54\x78\x5e\xed\x9b\x7b\x68\x1c\x55\x14\xc6\xcf\
|
||||
\xc9\x6c\x51\x50\x50\xa2\x28\xa8\x28\x28\x28\x28\x28\x28\x28\x28\
|
||||
\xe8\xec\xce\xce\x2e\x0a\x0a\x2a\xe6\x61\xd3\x52\x69\xf1\x51\xd1\
|
||||
\xfa\x2a\x4a\x8b\x62\x8b\x5a\xd1\x2a\x5a\x14\x2b\x6a\x8b\x5a\xa3\
|
||||
\x35\x54\xc5\x77\x66\xee\x4d\x57\x22\x0d\xc5\x42\xb1\x50\x28\x15\
|
||||
\x25\x50\x14\x4a\x45\xa9\x18\x34\x66\x33\x47\x46\x6e\x30\x94\x24\
|
||||
\xdd\xb9\xfb\x9a\xd9\x73\xf6\xaf\x40\xee\x77\x77\xbe\xef\xfc\xf6\
|
||||
\xbb\xb3\xbb\x09\x82\x3c\x58\x27\x80\xac\xdd\x8b\x79\x10\x00\x98\
|
||||
\x43\x20\x00\x08\x00\xcc\x13\x60\x6e\x5f\x1a\x40\x00\x60\x9e\x00\
|
||||
\x73\xfb\xd2\x00\x02\x00\xf3\x04\x98\xdb\x97\x06\x10\x00\x98\x27\
|
||||
\xc0\xdc\xbe\x34\x80\x00\xc0\x3c\x01\xe6\xf6\xa5\x01\x04\x00\xe6\
|
||||
\x09\x30\xb7\x2f\x0d\x20\x00\x30\x4f\x80\xb9\x7d\x69\x00\x01\x80\
|
||||
\x79\x02\xcc\xed\x4b\x03\x08\x00\xcc\x13\x60\x6e\x5f\x1a\x40\x00\
|
||||
\x60\x9e\x00\x73\xfb\xd2\x00\x02\x00\xf3\x04\x98\xdb\x97\x06\x10\
|
||||
\x00\x98\x27\xc0\xdc\xbe\x34\x80\x00\xc0\x3c\x01\xe6\xf6\xa5\x01\
|
||||
\x04\x00\xe6\x09\x30\xb7\x2f\x0d\x20\x00\x30\x4f\x80\xb9\x7d\x69\
|
||||
\x00\x01\x80\x79\x02\xcc\xed\x4b\x03\x08\x00\xcc\x13\x60\x6e\x5f\
|
||||
\x1a\x40\x00\x60\x9e\x00\x73\xfb\xd2\x00\x02\x00\xf3\x04\x98\xdb\
|
||||
\x97\x06\x10\x00\x98\x27\xc0\xdc\x7e\xe6\x1a\xc0\xf7\xfd\xf5\xd5\
|
||||
\x6a\x75\xc7\xce\x9d\x3b\xbf\x4f\xfb\xec\x5c\xd7\xcd\xe5\x72\xb9\
|
||||
\x41\xa5\x54\x4f\x5a\xaf\x35\x53\x00\x78\x9e\xb7\x11\x11\x1f\x06\
|
||||
\x80\x83\x44\x34\xa0\xb5\xfe\x2e\xad\xc1\xba\xae\x7b\xa2\xe3\x38\
|
||||
\x83\x88\x78\x33\x00\x0c\xa5\x15\x82\xcc\x00\x50\x2c\x16\x5f\x05\
|
||||
\x80\x95\x33\x03\x27\xa2\x71\xc7\x71\x16\x07\x41\xb0\x2b\x6d\x10\
|
||||
\xb8\xae\x7b\xb2\x19\xfe\x8d\xb3\xae\x2d\x95\x10\x64\x02\x00\xcf\
|
||||
\xf3\xb6\x22\xe2\xb2\x39\x06\xfd\x33\x00\x0c\x28\xa5\x2a\x69\x81\
|
||||
\xc0\x75\xdd\x53\xcd\xf0\xaf\x9f\xe3\x9a\x52\x07\x41\xaa\x01\x88\
|
||||
\x6b\x34\x97\xcb\x6d\x03\x80\x5b\x17\x18\xf0\x11\x44\x1c\x08\xc3\
|
||||
\x30\x68\x37\x04\xae\xeb\x9e\xbe\x68\xd1\xa2\x41\x22\xf2\x17\xb8\
|
||||
\x96\x54\x41\x90\x5a\x00\xca\xe5\x72\xf7\xf4\xf4\xf4\x20\x00\x94\
|
||||
\x6b\x18\xec\x51\x73\x4f\xf0\x79\x0d\x6b\x9b\xb2\xc4\xf3\xbc\x33\
|
||||
\x11\xf1\x7d\x00\xc8\xd7\xf0\x04\xa9\x81\x20\x95\x00\xb8\xae\x7b\
|
||||
\x8e\xe3\x38\xdb\x11\xf1\xea\x1a\xc2\x9c\x59\xf2\x97\x39\x0e\x3e\
|
||||
\x4a\xa0\x69\xc8\xd2\x42\xa1\x70\x76\x5c\xfb\x44\x74\x6d\x82\x0d\
|
||||
\x53\x01\x41\xea\x00\xc8\xe7\xf3\x17\x39\x8e\xf3\x21\x00\x5c\x9a\
|
||||
\x20\xcc\x99\xa5\xd3\x44\xb4\x58\x6b\xbd\xdd\x42\x6b\x25\x29\x14\
|
||||
\x0a\xe7\x99\xe1\x27\x81\x75\xe6\xb9\xda\x0e\x41\xea\x00\x88\x93\
|
||||
\xf1\x7d\xff\x09\x22\x5a\x67\x35\x11\x00\x40\xc4\xa5\x61\x18\xbe\
|
||||
\x6b\xab\xaf\x55\x57\x28\x14\x2e\x30\xc3\xbf\xb2\x56\xcd\xac\x75\
|
||||
\x11\x00\xf4\x28\xa5\x76\x58\x68\x1b\x26\x49\x25\x00\xb1\x3b\xcf\
|
||||
\xf3\x1e\x47\xc4\xf5\xb6\x4e\x89\x68\x85\xd6\xfa\x2d\x5b\xfd\xf1\
|
||||
\x74\xa6\xa9\xe2\x7b\x94\xcb\x8f\xb7\x76\x8e\xdf\x4f\x11\x51\x8f\
|
||||
\xd6\xfa\x13\x0b\x6d\x43\x25\xa9\x05\x20\x76\x59\x2c\x16\xd7\x02\
|
||||
\xc0\x53\x75\x38\x5e\xa9\x94\x7a\xad\x0e\xfd\x9c\xd2\x7c\x3e\x7f\
|
||||
\x49\xfc\xca\xb7\x3c\xa6\xfe\xee\xea\xea\xea\x09\x82\xe0\xb3\x46\
|
||||
\x5f\x97\xcd\x7e\xa9\x06\xc0\x1c\x07\x6b\x88\xe8\x69\x1b\x73\xb1\
|
||||
\x86\x88\x1e\xd0\x5a\xbf\x6c\xab\x3f\x56\x57\x2e\x97\x2f\x33\xef\
|
||||
\x4e\x2e\xb6\xd8\x73\x02\x11\x7b\xc2\x30\xfc\xd2\x42\xdb\x14\x49\
|
||||
\xea\x01\x30\x4d\xf0\x18\x00\x6c\xa8\x23\x81\xd5\x4a\xa9\x8d\x75\
|
||||
\xe8\xff\x93\x96\x4a\xa5\x2b\xa2\x28\x8a\x5f\xf9\x17\x5a\xec\xf5\
|
||||
\x07\x11\xf5\x6a\xad\xbf\xb6\xd0\x36\x4d\x92\x09\x00\x4c\x13\x3c\
|
||||
\x4a\x44\xcf\xda\x26\x81\x88\x6b\xc3\x30\x7c\xc6\x56\x5f\x2a\x95\
|
||||
\xae\x32\xc3\x3f\x3f\xe9\x1e\x88\xf8\x7b\x14\x45\xf1\xf0\xc3\xa4\
|
||||
\xda\x66\xaf\xcf\x0c\x00\xa6\x09\x56\x03\xc0\x73\x75\x84\xb2\x4e\
|
||||
\x29\xf5\x64\x52\xbd\xef\xfb\xd7\x10\x51\xfc\xca\x3f\x37\xa9\x16\
|
||||
\x00\x7e\xed\xea\xea\xea\x0d\x82\x60\xc4\x42\xdb\x74\x49\xa6\x00\
|
||||
\x30\x10\x3c\x02\x00\xcf\xdb\x26\x83\x88\x1b\xc2\x30\x5c\x53\xab\
|
||||
\xde\xf7\xfd\xeb\xcc\xf0\xcf\xaa\x55\x33\x6b\xdd\x61\x44\xec\x0d\
|
||||
\xc3\xf0\x1b\x0b\x6d\x4b\x24\x99\x03\xc0\x1c\x07\x0f\x11\xd1\x0b\
|
||||
\xb6\x09\xc5\x5a\xad\x75\x0c\xd2\x82\x8f\x52\xa9\x54\x88\xa2\x28\
|
||||
\xfe\x78\xf7\x8c\xe3\xad\x9d\xe3\xf7\xbf\x00\x40\xaf\x52\xea\x5b\
|
||||
\x0b\x6d\xcb\x24\x99\x04\xc0\x34\xc1\x83\x00\xf0\xa2\x6d\x52\x88\
|
||||
\xb8\x29\x0c\xc3\x55\xf3\xe9\x7d\xdf\x2f\x99\x57\xfe\x69\x16\xcf\
|
||||
\x71\xc8\xdc\xf0\x8d\x59\x68\x5b\x2a\xc9\x2c\x00\xa6\x09\x56\x11\
|
||||
\xd1\x4b\x75\x24\xb6\x59\x29\x75\xcf\xb1\x7a\xdf\xf7\x6f\x30\xc3\
|
||||
\x3f\x25\xe9\xde\x88\x38\x8e\x88\x7d\x41\x10\xec\x4e\xaa\x6d\xc7\
|
||||
\xfa\x4c\x03\x10\x07\xe6\x79\xde\xfd\x88\x58\xcf\xfb\xfc\x2d\x4a\
|
||||
\xa9\xe5\x33\xe1\xfb\xbe\x7f\x93\x19\xfe\x49\x16\x03\xf9\xc9\x9c\
|
||||
\xf9\x7b\x2c\xb4\x6d\x91\x64\x1e\x00\x73\x1c\xdc\x07\x00\x9b\x6c\
|
||||
\x13\x24\xa2\x6d\x5a\xeb\x25\xc5\x62\xf1\x16\x00\x88\xef\xf6\x4f\
|
||||
\xb0\xd8\xeb\x07\x73\xe6\xef\xb5\xd0\xb6\x4d\xd2\x11\x00\x98\xe3\
|
||||
\xe0\x5e\x22\x7a\xa5\x8e\x24\xe3\x6f\x20\xe3\x3f\x3c\x71\x2c\xf6\
|
||||
\x38\x60\xce\xfc\x7d\x16\xda\xb6\x4a\x3a\x06\x00\x73\x1c\xac\x44\
|
||||
\xc4\xf8\x6f\x07\x5b\xf6\x20\xa2\xfd\xb9\x5c\xae\x77\x78\x78\x78\
|
||||
\x7f\xcb\x9e\xb4\x81\x4f\xd4\x51\x00\x98\x26\xb8\x9b\x88\x1a\xfe\
|
||||
\x05\xd0\x3c\x99\xef\x33\x1f\xf2\x1c\x68\xe0\x4c\x5a\xba\x55\xc7\
|
||||
\x01\x60\x9a\xe0\x2e\x44\xdc\xdc\xe4\x24\xf7\x12\x51\x9f\xd6\xfa\
|
||||
\x60\x93\x9f\xa7\xa9\xdb\x77\x24\x00\xe6\xc6\xf0\x4e\x00\x78\xbd\
|
||||
\x49\xe9\xed\x89\xa2\xa8\x6f\x64\x64\xe4\xc7\x26\xed\xdf\xb2\x6d\
|
||||
\x3b\x16\x00\x73\x1c\xac\x20\xa2\x37\x1a\x9c\xe6\xee\x6a\xb5\xda\
|
||||
\x57\xa9\x54\xc6\x1b\xbc\x6f\x5b\xb6\xeb\x68\x00\xcc\x71\xb0\x1c\
|
||||
\x11\xdf\x6c\x44\xba\x88\xb8\xcb\x7c\xc8\x73\xa8\x11\xfb\xa5\x61\
|
||||
\x8f\x8e\x07\xc0\x1c\x07\x77\x00\xc0\x96\x3a\x03\x1f\x8d\x87\x1f\
|
||||
\x86\x61\xfc\x19\x7f\xc7\x3c\x58\x00\x60\x8e\x83\x65\x44\xb4\xd5\
|
||||
\x72\x72\x15\x73\xc3\x77\xd8\x52\x9f\x5a\x19\x1b\x00\x4c\x13\x2c\
|
||||
\x05\x80\xb7\x13\x4e\x43\x4f\x4e\x4e\xf6\x8f\x8e\x8e\x1e\x49\xa8\
|
||||
\xcb\xc4\x72\x56\x00\x98\x26\x58\x42\x44\xef\xd4\x38\x9d\xc0\x71\
|
||||
\x9c\xfe\xe1\xe1\xe1\xdf\x6a\x5c\x9f\xb9\x65\xec\x00\x30\x37\x86\
|
||||
\x03\x88\xb8\xe0\xff\x0d\x20\xe2\x57\x44\xd4\xaf\x94\x3a\x9a\xb9\
|
||||
\xa9\x26\xb8\x60\x96\x00\x98\xe3\xe0\x76\x00\x78\x6f\x9e\xac\xbe\
|
||||
\x30\x6f\xf5\xfe\x4c\x90\x65\x26\x97\xb2\x05\xc0\x1c\x07\xfd\xe6\
|
||||
\xab\xdf\xd9\xc3\xfb\x74\x62\x62\xa2\x6f\x6c\x6c\x2c\xfe\x5f\xc3\
|
||||
\x8e\x7f\xb0\x06\xc0\x1c\x07\xbd\x88\xf8\x41\xfc\x33\x11\x7d\xdc\
|
||||
\xdd\xdd\xdd\x37\x34\x34\xf4\x4f\xc7\x4f\xde\x18\x64\x0f\x80\x39\
|
||||
\x0e\x7a\x10\xf1\xb6\xa9\xa9\xa9\xfe\x4a\xa5\x52\xe5\x32\xfc\xd8\
|
||||
\xa7\x00\xf0\xff\xb4\xe3\x2c\x88\xd3\xf0\x05\x00\x6e\xd3\x9e\xc3\
|
||||
\xaf\x34\x00\x73\x08\x04\x00\x01\x80\x79\x02\xcc\xed\x4b\x03\x08\
|
||||
\x00\xcc\x13\x60\x6e\x5f\x1a\x40\x00\x60\x9e\x00\x73\xfb\xd2\x00\
|
||||
\x02\x00\xf3\x04\x98\xdb\x97\x06\x10\x00\x98\x27\xc0\xdc\xbe\x34\
|
||||
\x80\x00\xc0\x3c\x01\xe6\xf6\xa5\x01\x04\x00\xe6\x09\x30\xb7\x2f\
|
||||
\x0d\x20\x00\x30\x4f\x80\xb9\x7d\x69\x00\x01\x80\x79\x02\xcc\xed\
|
||||
\x4b\x03\x08\x00\xcc\x13\x60\x6e\x5f\x1a\x40\x00\x60\x9e\x00\x73\
|
||||
\xfb\xd2\x00\x02\x00\xf3\x04\x98\xdb\x97\x06\x10\x00\x98\x27\xc0\
|
||||
\xdc\xbe\x34\x80\x00\xc0\x3c\x01\xe6\xf6\xa5\x01\x04\x00\xe6\x09\
|
||||
\x30\xb7\x2f\x0d\x20\x00\x30\x4f\x80\xb9\x7d\x69\x00\x01\x80\x79\
|
||||
\x02\xcc\xed\x4b\x03\x08\x00\xcc\x13\x60\x6e\x5f\x1a\x40\x00\x60\
|
||||
\x9e\x00\x73\xfb\xd2\x00\x02\x00\xf3\x04\x98\xdb\x97\x06\x10\x00\
|
||||
\x98\x27\xc0\xdc\xbe\x34\x80\x00\xc0\x3c\x01\xe6\xf6\xa5\x01\x98\
|
||||
\x03\xf0\x2f\x1a\xf0\xdc\x90\x9e\x40\x3c\x9b\x00\x00\x00\x00\x49\
|
||||
\x45\x4e\x44\xae\x42\x60\x82\
|
||||
"
|
||||
|
||||
qt_resource_name = b"\
|
||||
\x00\x07\
|
||||
\x07\x3b\xe0\xb3\
|
||||
\x00\x70\
|
||||
\x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\
|
||||
\x00\x06\
|
||||
\x05\x04\x66\x45\
|
||||
\x00\x49\
|
||||
\x00\x6e\x00\x5f\x00\x6f\x00\x6e\x00\x65\
|
||||
\x00\x03\
|
||||
\x00\x00\x76\xf3\
|
||||
\x00\x70\
|
||||
\x00\x69\x00\x63\
|
||||
\x00\x08\
|
||||
\x09\xe6\x72\x67\
|
||||
\x7b\xad\
|
||||
\x59\x34\x00\x20\x53\xf3\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
\x00\x0b\
|
||||
\x0f\x8a\xc9\x87\
|
||||
\x7b\xad\
|
||||
\x59\x34\x00\x5f\x52\x17\x88\x68\x54\x11\x53\xf3\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||
\x00\x08\
|
||||
\x04\x1e\x72\x67\
|
||||
\x7b\xad\
|
||||
\x59\x34\x00\x20\x4e\x0b\x00\x2e\x00\x73\x00\x76\x00\x67\
|
||||
\x00\x0b\
|
||||
\x0e\xdf\xc8\xa7\
|
||||
\x7b\xad\
|
||||
\x59\x34\x00\x5f\x52\x17\x88\x68\x5c\x55\x5f\x00\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||
"
|
||||
|
||||
qt_resource_struct_v1 = b"\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
|
||||
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
|
||||
\x00\x00\x00\x26\x00\x02\x00\x00\x00\x04\x00\x00\x00\x04\
|
||||
\x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x32\
|
||||
\x00\x00\x00\x32\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x7a\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x43\
|
||||
\x00\x00\x00\x48\x00\x00\x00\x00\x00\x01\x00\x00\x05\x36\
|
||||
"
|
||||
|
||||
qt_resource_struct_v2 = b"\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x26\x00\x02\x00\x00\x00\x04\x00\x00\x00\x04\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x64\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x32\
|
||||
\x00\x00\x01\x81\x5b\xf7\x7e\xef\
|
||||
\x00\x00\x00\x32\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x01\x81\x5b\xf7\x72\x92\
|
||||
\x00\x00\x00\x7a\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x43\
|
||||
\x00\x00\x01\x81\x5b\xfc\x68\x05\
|
||||
\x00\x00\x00\x48\x00\x00\x00\x00\x00\x01\x00\x00\x05\x36\
|
||||
\x00\x00\x01\x81\x5b\xfc\x85\xb4\
|
||||
"
|
||||
|
||||
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
|
||||
if qt_version < [5, 8, 0]:
|
||||
rcc_version = 1
|
||||
qt_resource_struct = qt_resource_struct_v1
|
||||
else:
|
||||
rcc_version = 2
|
||||
qt_resource_struct = qt_resource_struct_v2
|
||||
|
||||
def qInitResources():
|
||||
QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
|
||||
|
||||
def qCleanupResources():
|
||||
QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
|
||||
|
||||
qInitResources()
|
0
plugins/veg_method/readme.md
Normal file
0
plugins/veg_method/readme.md
Normal file
12424
plugins/veg_method/scripts/ACD.py
Normal file
12424
plugins/veg_method/scripts/ACD.py
Normal file
File diff suppressed because it is too large
Load Diff
12424
plugins/veg_method/scripts/AHT.py
Normal file
12424
plugins/veg_method/scripts/AHT.py
Normal file
File diff suppressed because it is too large
Load Diff
12424
plugins/veg_method/scripts/LHBA.py
Normal file
12424
plugins/veg_method/scripts/LHBA.py
Normal file
File diff suppressed because it is too large
Load Diff
12424
plugins/veg_method/scripts/OCD.py
Normal file
12424
plugins/veg_method/scripts/OCD.py
Normal file
File diff suppressed because it is too large
Load Diff
12424
plugins/veg_method/scripts/SH.py
Normal file
12424
plugins/veg_method/scripts/SH.py
Normal file
File diff suppressed because it is too large
Load Diff
690
plugins/veg_method/scripts/__init__.py
Normal file
690
plugins/veg_method/scripts/__init__.py
Normal file
@ -0,0 +1,690 @@
|
||||
from datetime import datetime
|
||||
from osgeo import gdal
|
||||
import math,os
|
||||
import time
|
||||
from PyQt5 import QtWidgets
|
||||
from sklearn.cluster import k_means
|
||||
from rscder.utils.geomath import geo2imageRC, imageRC2geo
|
||||
from rscder.utils.project import Project, PairLayer
|
||||
from misc import Register, AlgFrontend
|
||||
|
||||
VEG_CD = Register('植被变化检测方法')
|
||||
|
||||
import numpy as np
|
||||
from .ACD import ACD
|
||||
from .AHT import AHT
|
||||
from .OCD import OCD
|
||||
from .LHBA import LHBA
|
||||
from .SH import SH
|
||||
|
||||
def warp(file,ds:gdal.Dataset,srcWin=[0,0,0,0]):
|
||||
driver = gdal.GetDriverByName('GTiff')
|
||||
xsize=ds.RasterXSize
|
||||
ysize=ds.RasterYSize
|
||||
geo=ds.GetGeoTransform()
|
||||
orj=ds.GetProjection()
|
||||
band=ds.RasterCount
|
||||
if os.path.exists(file):
|
||||
os.remove(file)
|
||||
out_ds:gdal.Dataset=driver.Create(file, xsize, ysize, band, gdal.GDT_Byte)
|
||||
out_ds.SetGeoTransform(geo)
|
||||
out_ds.SetProjection(orj)
|
||||
for b in range(1,band+1):
|
||||
out_ds.GetRasterBand(b).WriteArray(ds.ReadAsArray(*srcWin,band_list=[b]),*(0,0))
|
||||
del out_ds
|
||||
|
||||
@VEG_CD.register
|
||||
class BasicCD(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return '差分法'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None,*args, **kargs):
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
|
||||
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
|
||||
|
||||
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])
|
||||
block_data1 = ds1.ReadAsArray(*block_xy1, *block_size1)
|
||||
block_data2 = ds2.ReadAsArray(*block_xy2, *block_size2)
|
||||
|
||||
if band == 1:
|
||||
block_data1 = block_data1[None, ...]
|
||||
block_data2 = block_data2[None, ...]
|
||||
# pdb.set_trace()
|
||||
block_diff = block_data1.sum(0) - block_data2.sum(0)
|
||||
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.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('归一化概率中...')
|
||||
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
|
||||
|
||||
@VEG_CD.register
|
||||
class LSTS(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'LSTS'
|
||||
|
||||
@staticmethod
|
||||
def get_widget(parent=None):
|
||||
|
||||
widget = QtWidgets.QWidget(parent)
|
||||
|
||||
return widget
|
||||
|
||||
@staticmethod
|
||||
def get_params(widget=None):
|
||||
return dict(n=5, w_size=(3,3))
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message=None,n=5,w_size=(3,3), *args, **kws):
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
|
||||
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, '%d.tif'%(int(datetime.now().timestamp() * 1000)))
|
||||
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)
|
||||
pixnum=w_size[0]*w_size[1]
|
||||
# send_message.emit('pixnum:'pixnum)
|
||||
max_diff = 0
|
||||
min_diff = math.inf
|
||||
win_h=w_size[0]//2 #half hight of window
|
||||
win_w=w_size[1]//2 #half width of window
|
||||
a=[[(i+1)**j for j in range(n+1)] for i in range(pixnum)]
|
||||
A=np.array(a).astype(np.float64)#
|
||||
|
||||
k_=np.array(range(1,n+1))
|
||||
df1=np.zeros(pixnum).astype(np.float64)
|
||||
df2=np.zeros(pixnum).astype(np.float64)
|
||||
|
||||
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])
|
||||
block_data1 = ds1.ReadAsArray(*block_xy1, *block_size1)
|
||||
block_data2 = ds2.ReadAsArray(*block_xy2, *block_size2)
|
||||
|
||||
if band == 1:
|
||||
block_data1 = block_data1[None, ...]
|
||||
block_data2 = block_data2[None, ...]
|
||||
# pdb.set_trace()
|
||||
else:
|
||||
block_data1=np.mean(block_data1,0)
|
||||
block_data2=np.mean(block_data2,0)
|
||||
block_diff=np.zeros(block_data1.shape).astype(np.float64)
|
||||
|
||||
for i in range(win_h,block_size1[1]-win_h):
|
||||
for j_ in range(win_w,block_size1[0]-win_w):
|
||||
pix=0
|
||||
|
||||
#get b
|
||||
# b1=block_data[i+win_h:i+win_h] c in range(j_-win_w,j_+win_w+1)
|
||||
b1=block_data1[i-win_h:i+win_h+1,j_-win_w:j_+win_w+1]
|
||||
b2=block_data2[i-win_h:i+win_h+1,j_-win_w:j_+win_w+1]
|
||||
b1=[b if (r+1)//2 else b[::-1] for r,b in enumerate(b1)]
|
||||
b2=[b if (r+1)//2 else b[::-1] for r,b in enumerate(b2)]
|
||||
b1=np.expand_dims(np.concatenate(b1,0),1)
|
||||
b2=np.expand_dims(np.concatenate(b2,0),1)
|
||||
|
||||
x1=np.squeeze(np.linalg.pinv(A).dot(b1))
|
||||
x2=np.squeeze(np.linalg.pinv(A).dot(b2))
|
||||
#df
|
||||
k_=range(1,n+1)
|
||||
for pix in range(1,pixnum+1):
|
||||
df1[pix-1]=x1[1:n+1].dot(np.array([k*(pix**(k-1)) for k in k_]))
|
||||
df2[pix-1]=x2[1:n+1].dot(np.array([k*(pix**(k-1)) for k in k_]))
|
||||
|
||||
#distance 欧式距离
|
||||
block_diff[i][j_]=np.dot(df1-df2,df1-df2)**0.5
|
||||
|
||||
min_diff = min(min_diff, block_diff[block_diff > 0].min())
|
||||
max_diff = max(max_diff, block_diff.max())
|
||||
out_ds.GetRasterBand(1).WriteArray(block_diff, *block_xy)
|
||||
|
||||
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('归一化概率中...')
|
||||
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('LSTS法计算完成')
|
||||
return out_normal_tif
|
||||
|
||||
|
||||
@VEG_CD.register
|
||||
class CVAAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'CVA'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
|
||||
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
|
||||
|
||||
|
||||
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])
|
||||
block_data1 = ds1.ReadAsArray(*block_xy1, *block_size1)
|
||||
block_data2 = ds2.ReadAsArray(*block_xy2, *block_size2)
|
||||
|
||||
if band == 1:
|
||||
block_data1 = block_data1[None, ...]
|
||||
block_data2 = block_data2[None, ...]
|
||||
# pdb.set_trace()
|
||||
block_diff=np.sum((block_data1-block_data2)**2,0)**0.5
|
||||
min_diff = min(min_diff, block_diff[block_diff > 0].min())
|
||||
max_diff = max(max_diff, block_diff.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('归一化概率中...')
|
||||
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
|
||||
|
||||
@VEG_CD.register
|
||||
class ACDAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'ACD'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
# send_message.emit = print
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
|
||||
|
||||
#运算
|
||||
send_message.emit('开始ACD计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
ACD(temp_tif1,temp_tif2,out_normal_tif)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
|
||||
return out_normal_tif
|
||||
|
||||
|
||||
@VEG_CD.register
|
||||
class AHTAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'AHT'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
|
||||
|
||||
#运算
|
||||
send_message.emit('开始AHT计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
AHT(temp_tif1,temp_tif2,out_normal_tif)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
|
||||
return out_normal_tif
|
||||
|
||||
|
||||
@VEG_CD.register
|
||||
class OCDAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'OCD'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
|
||||
|
||||
#运算
|
||||
send_message.emit('开始OCD计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
OCD(temp_tif1,temp_tif2,out_normal_tif,Project().other_path)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
|
||||
return out_normal_tif
|
||||
|
||||
@VEG_CD.register
|
||||
class LHBAAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'LHBA'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
#运算
|
||||
send_message.emit('开始LHBA计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
LHBA(temp_tif1,temp_tif2,out_normal_tif)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
return out_normal_tif
|
||||
|
||||
|
||||
@VEG_CD.register
|
||||
class SHAlg(AlgFrontend):
|
||||
|
||||
@staticmethod
|
||||
def get_name():
|
||||
return 'SH'
|
||||
|
||||
@staticmethod
|
||||
def run_alg(pth1:str,pth2:str,layer_parent:PairLayer,send_message = None, *args, **kargs):
|
||||
|
||||
if send_message is None:
|
||||
class Empty:
|
||||
|
||||
def emit(self, *args, **kws):
|
||||
print(args)
|
||||
send_message = Empty()
|
||||
|
||||
|
||||
|
||||
xsize = layer_parent.size[0]
|
||||
ysize = layer_parent.size[1]
|
||||
geo=layer_parent.grid.geo
|
||||
proj=layer_parent.grid.proj
|
||||
#提取公共部分
|
||||
send_message.emit('提取重叠区域数据.....')
|
||||
|
||||
ds2:gdal.Dataset=gdal.Open(pth2)
|
||||
temp_tif2 = os.path.join(Project().other_path,'temp2.tif')
|
||||
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])
|
||||
warp(temp_tif2,ds2,srcWin=[start2x,start2y,xsize,ysize])
|
||||
del ds2
|
||||
send_message.emit('图像二提取完成')
|
||||
|
||||
|
||||
ds1:gdal.Dataset=gdal.Open(pth1)
|
||||
temp_tif1 = os.path.join(Project().other_path, 'temp1.tif')
|
||||
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])
|
||||
warp(temp_tif1,ds1,srcWin=[start1x,start1y,xsize,ysize])
|
||||
del ds1
|
||||
send_message.emit('图像一提取完成')
|
||||
|
||||
#运算
|
||||
send_message.emit('开始SH计算.....')
|
||||
time.sleep(0.1)
|
||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer_parent.name, int(np.random.rand() * 100000)))
|
||||
SH(temp_tif1,temp_tif2,out_normal_tif)
|
||||
#添加投影
|
||||
send_message.emit('录入投影信息.....')
|
||||
time.sleep(0.1)
|
||||
ds=gdal.Open(out_normal_tif,1)
|
||||
ds.SetGeoTransform(geo)
|
||||
ds.SetProjection(proj)
|
||||
del ds
|
||||
return out_normal_tif
|
@ -2,7 +2,8 @@ import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5.QtWidgets import QAction, QActionGroup, QLabel, QFileDialog, QMenuBar
|
||||
from PyQt5.QtCore import Qt, QSize, QSettings, pyqtSignal
|
||||
from PyQt5.QtWidgets import QAction, QActionGroup, QLabel, QFileDialog, QMenuBar, QToolBar, QVBoxLayout, QComboBox
|
||||
from rscder.gui import project
|
||||
from rscder.gui.project import Create
|
||||
from rscder.utils.icons import IconInstance
|
||||
@ -20,18 +21,20 @@ class ActionManager(QtCore.QObject):
|
||||
instance = None
|
||||
|
||||
def __init__(self,
|
||||
double_map,
|
||||
layer_tree,
|
||||
follow_box,
|
||||
result_box,
|
||||
message_box,
|
||||
parent=None):
|
||||
double_map,
|
||||
layer_tree,
|
||||
follow_box,
|
||||
result_box,
|
||||
message_box,
|
||||
parent=None):
|
||||
super().__init__(parent)
|
||||
self.w_parent = parent
|
||||
self.actions = {}
|
||||
self.action_groups = {}
|
||||
self.action_group_actions = {}
|
||||
|
||||
self.toolbars = {}
|
||||
|
||||
self.double_map = double_map
|
||||
self.layer_tree = layer_tree
|
||||
self.follow_box = follow_box
|
||||
@ -52,7 +55,7 @@ class ActionManager(QtCore.QObject):
|
||||
self.basic_menu = menubar.addMenu( '&基础工具')
|
||||
self.filter_menu = self.basic_menu.addMenu(IconInstance().FILTER, '&滤波处理')
|
||||
self.change_detection_menu = menubar.addMenu('&通用变化检测')
|
||||
self.unsupervised_menu = self.change_detection_menu.addMenu(IconInstance().UNSUPERVISED, '&无监督变化检测')
|
||||
# self.unsupervised_menu = self.change_detection_menu.addMenu(IconInstance().UNSUPERVISED, '&无监督变化检测')
|
||||
self.supervised_menu = self.change_detection_menu.addMenu(IconInstance().SUPERVISED,'&监督变化检测')
|
||||
self.ai_menu = self.change_detection_menu.addMenu(IconInstance().AI_DETECT,'&AI变化检测')
|
||||
self.special_chagne_detec_menu = menubar.addMenu( '&专题变化检测')
|
||||
@ -73,10 +76,28 @@ class ActionManager(QtCore.QObject):
|
||||
self.plugin_menu = menubar.addMenu('&插件')
|
||||
self.help_menu = menubar.addMenu( '&帮助')
|
||||
|
||||
# vbox = QVBoxLayout()
|
||||
# follow_combox = QComboBox(self.follow_box)
|
||||
# vbox.addWidget(follow_combox)
|
||||
# self.follow_box.setLayout(vbox)
|
||||
|
||||
|
||||
def set_toolbar(self, toolbar):
|
||||
self.toolbar = toolbar
|
||||
self.toolbar:QToolBar = toolbar
|
||||
self.toolbar.setIconSize(QtCore.QSize(24, 24))
|
||||
|
||||
def add_toolbar(self, name=None):
|
||||
|
||||
toolbar = self.w_parent.addToolBar(name)
|
||||
toolbar.setMovable(True)
|
||||
toolbar.setFloatable(False)
|
||||
toolbar.setIconSize(QSize(32, 32))
|
||||
toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
toolbar.setContextMenuPolicy(Qt.PreventContextMenu)
|
||||
toolbar.setLayoutDirection(Qt.LeftToRight)
|
||||
|
||||
return toolbar
|
||||
|
||||
def set_status_bar(self, status_bar):
|
||||
self.status_bar = status_bar
|
||||
|
||||
@ -132,6 +153,9 @@ class ActionManager(QtCore.QObject):
|
||||
zomm_in.setCheckable(True)
|
||||
zomm_in.setChecked(False)
|
||||
|
||||
toolbar = self.add_toolbar('Map')
|
||||
toolbar.addActions([pan, zomm_out, zomm_in, locate])
|
||||
|
||||
self.double_map.connect_map_tool(pan, zomm_in, zomm_out)
|
||||
# self.double_map.connect_grid_show(grid_line)
|
||||
|
||||
@ -148,6 +172,9 @@ class ActionManager(QtCore.QObject):
|
||||
plugin_list = self.add_action(QAction(IconInstance().PLUGINS,'&插件列表', self.w_parent), 'Plugin')
|
||||
plugin_list.triggered.connect(self.plugin_list)
|
||||
|
||||
# toolbar = self.add_toolbar('Plugin')
|
||||
# toolbar.addAction(plugin_list)
|
||||
|
||||
self.plugin_menu.addAction(plugin_list)
|
||||
|
||||
self.message_box.info('菜单初始化完成')
|
||||
|
@ -47,8 +47,8 @@ class LicenseGen(QDialog):
|
||||
self.btn_cancel.clicked.connect(self.reject)
|
||||
|
||||
hbox4 = QHBoxLayout()
|
||||
hbox4.addWidget(self.btn_generate, alignment = QtCore.Qt.AlignRight, stretch= 0)
|
||||
hbox4.addWidget(self.btn_cancel, alignment = QtCore.Qt.AlignRight, stretch= 0)
|
||||
hbox4.addWidget(self.btn_generate, alignment = QtCore.Qt.AlignCenter, stretch= 0)
|
||||
hbox4.addWidget(self.btn_cancel, alignment = QtCore.Qt.AlignCenter, stretch= 0)
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
vbox.addLayout(hbox1)
|
||||
|
@ -1,5 +1,6 @@
|
||||
from PyQt5.QtWidgets import QComboBox, QWidget, QLabel, QHBoxLayout, QVBoxLayout
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtCore import Qt
|
||||
from rscder.utils.icons import IconInstance
|
||||
from rscder.utils.project import PairLayer, Project, RasterLayer, ResultPointLayer,SingleBandRasterLayer
|
||||
class LayerCombox(QComboBox):
|
||||
@ -7,6 +8,7 @@ class LayerCombox(QComboBox):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.addItem('---', None)
|
||||
self.setMinimumWidth(200)
|
||||
|
||||
for layer in Project().layers.values():
|
||||
self.addItem(IconInstance().LAYER, layer.name, layer.id)
|
||||
@ -34,8 +36,9 @@ class PairLayerCombox(QWidget):
|
||||
layer_label = QLabel('图层组:')
|
||||
|
||||
hbox = QHBoxLayout()
|
||||
hbox.setAlignment(Qt.AlignLeft)
|
||||
hbox.addWidget(layer_label)
|
||||
hbox.addWidget(self.layer_combox)
|
||||
hbox.addWidget(self.layer_combox, 2)
|
||||
|
||||
self.raster_layer1 = QComboBox(self)
|
||||
self.raster_layer1.addItem('---', None)
|
||||
@ -49,12 +52,14 @@ class PairLayerCombox(QWidget):
|
||||
self.layer_combox.currentIndexChanged.connect(self.on_group_changed)
|
||||
|
||||
hbox1 = QHBoxLayout()
|
||||
hbox1.setAlignment(Qt.AlignLeft)
|
||||
hbox1.addWidget(QLabel('时相1:'))
|
||||
hbox1.addWidget(self.raster_layer1)
|
||||
hbox1.addWidget(self.raster_layer1, 2)
|
||||
|
||||
hbox2 = QHBoxLayout()
|
||||
hbox2.setAlignment(Qt.AlignLeft)
|
||||
hbox2.addWidget(QLabel('时相2:'))
|
||||
hbox2.addWidget(self.raster_layer2)
|
||||
hbox2.addWidget(self.raster_layer2, 2)
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
vbox.addLayout(hbox)
|
||||
|
@ -1,10 +1,11 @@
|
||||
from colorsys import hls_to_rgb
|
||||
import os
|
||||
from turtle import width
|
||||
from osgeo import gdal
|
||||
from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow, QToolBox
|
||||
from PyQt5.QtWidgets import QDialog, QFileDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox,QSpacerItem
|
||||
from PyQt5.QtWidgets import QDialog, QFileDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox,QSpacerItem,QDialogButtonBox
|
||||
from PyQt5.QtCore import Qt, QSize,QSettings,pyqtSignal,QThread
|
||||
from PyQt5.QtGui import QIcon,QColor
|
||||
from PyQt5.QtGui import QIcon,QColor,QPalette,QPixmap
|
||||
from PyQt5 import QtGui
|
||||
from threading import Thread
|
||||
from rscder.utils.icons import IconInstance
|
||||
@ -38,6 +39,8 @@ class loader(QDialog):
|
||||
signal1=pyqtSignal(str)
|
||||
def __init__(self, parent=None) -> None:
|
||||
super().__init__(parent)
|
||||
self.left_layer=None
|
||||
self.right_layer=None
|
||||
self.setWindowTitle('载入数据')
|
||||
self.setWindowIcon(IconInstance().DATA_LOAD)
|
||||
self.pyramid:bool=False
|
||||
@ -46,18 +49,20 @@ class loader(QDialog):
|
||||
self.path1=''
|
||||
self.path2=''
|
||||
self.bands=['red:','green:','blue:','NIR:']
|
||||
self.bandsorder=[3,2,1,4]
|
||||
self.mapcanva1 = QgsMapCanvas(self)
|
||||
self.mapcanva2 = QgsMapCanvas(self)
|
||||
self.mapcanva1.setCanvasColor(QColor(0, 0, 0))
|
||||
self.mapcanva2.setCanvasColor(QColor(0, 0, 0))
|
||||
self.mapcanva1.setFixedWidth(200)
|
||||
self.mapcanva1.setFixedHeight(200)
|
||||
self.mapcanva2.setFixedWidth(200)
|
||||
self.mapcanva2.setFixedHeight(200)
|
||||
self.bandsorder=[1,2,3,4]
|
||||
|
||||
self.left_map=QLabel()
|
||||
self.left_map.setFixedSize(200,200)
|
||||
self.left_map.setAutoFillBackground(True)
|
||||
self.left_map.setBackgroundRole(QPalette.Dark)
|
||||
|
||||
self.right_map=QLabel()
|
||||
self.right_map.setFixedSize(200,200)
|
||||
self.right_map.setAutoFillBackground(True)
|
||||
self.right_map.setBackgroundRole(QPalette.Dark)
|
||||
maplayout=QHBoxLayout()
|
||||
maplayout.addWidget(self.mapcanva1)
|
||||
maplayout.addWidget(self.mapcanva2)
|
||||
maplayout.addWidget(self.left_map)
|
||||
maplayout.addWidget(self.right_map)
|
||||
|
||||
path1_label = QLabel('时相1影像:')
|
||||
path1_label.setFixedWidth(60)
|
||||
@ -145,11 +150,16 @@ class loader(QDialog):
|
||||
|
||||
ok_button.clicked.connect(self.ok)
|
||||
cancel_button.clicked.connect(self.cancel)
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.setDirection(QHBoxLayout.RightToLeft)
|
||||
button_layout.addWidget(cancel_button, 0, Qt.AlignRight)
|
||||
button_layout.addWidget(ok_button, 0, Qt.AlignRight)
|
||||
ok_button.setDefault(True)
|
||||
cancel_button.setDefault(False)
|
||||
buttonbox=QDialogButtonBox(self)
|
||||
buttonbox.addButton(ok_button,QDialogButtonBox.NoRole)
|
||||
buttonbox.addButton(cancel_button,QDialogButtonBox.NoRole)
|
||||
buttonbox.setCenterButtons(True)
|
||||
# button_layout = QHBoxLayout()
|
||||
# button_layout.setDirection(QHBoxLayout.RightToLeft)
|
||||
# button_layout.addWidget(cancel_button, 0, Qt.AlignCenter)
|
||||
# button_layout.addWidget(ok_button, 0, Qt.AlignCenter)
|
||||
|
||||
main_layout = QVBoxLayout()
|
||||
main_layout.addLayout(path1_layout)
|
||||
@ -157,7 +167,8 @@ class loader(QDialog):
|
||||
main_layout.addLayout(path2_layout)
|
||||
main_layout.addLayout(style2_layout)
|
||||
main_layout.addLayout(maplayout)
|
||||
main_layout.addLayout(button_layout)
|
||||
main_layout.addWidget(buttonbox)
|
||||
# main_layout.addLayout(button_layout)
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def open_file1(self):
|
||||
@ -171,24 +182,23 @@ class loader(QDialog):
|
||||
if result==QMessageBox.Yes:
|
||||
progress1:QDialog=progressDialog(self,'加载时相一')
|
||||
progress1.setModal(False)
|
||||
self.temp1=os.path.join(Project().other_path,'temp1.tif')
|
||||
t1=GdalPreviewImage(self.path1,self.temp1,1024,self.parent())
|
||||
# t1.started.connect(progress1.show)
|
||||
t1.finished.connect(self.loadfile1)
|
||||
t1.finished.connect(lambda :self.setlabel(progress1) )
|
||||
self.left_layer=MultiBandRasterLayer(path=self.path1)
|
||||
t1=GdalPreviewImage(self.left_layer,self.left_map,width=200,parent=self.parent())
|
||||
t1.finished.connect(lambda :self.setlabel(progress1))
|
||||
t2=build_pyramids_overviews(self.path1,self.parent())
|
||||
t2.finished.connect(progress1.hide)
|
||||
t1.start()
|
||||
t1.finished.connect(t2.start)
|
||||
t1.finished.connect(lambda : self.open1.setEnabled(True))
|
||||
t1.start()
|
||||
# t2.start()
|
||||
progress1.show()
|
||||
else:
|
||||
progress1=progressDialog(self,'加载时相一')
|
||||
progress1.setModal(False)
|
||||
self.temp1=os.path.join(Project().other_path,'temp1.tif')
|
||||
t1=GdalPreviewImage(self.path1,self.temp1,1024,self.parent())
|
||||
self.left_layer=MultiBandRasterLayer(path=self.path1)
|
||||
t1=GdalPreviewImage(self.left_layer,self.left_map,width=200,parent=self.parent())
|
||||
# t1.started.connect(progress1.show)
|
||||
t1.finished.connect(self.loadfile1)
|
||||
t1.finished.connect(lambda : self.open1.setEnabled(True))
|
||||
t1.finished.connect(progress1.hide)
|
||||
t1.start()
|
||||
progress1.show()
|
||||
@ -196,14 +206,7 @@ class loader(QDialog):
|
||||
|
||||
except:
|
||||
return
|
||||
def loadfile1(self):
|
||||
try:
|
||||
self.left_layer=MultiBandRasterLayer(path=self.temp1)
|
||||
self.mapcanva1.setLayers([self.left_layer.layer])
|
||||
self.mapcanva1.zoomToFeatureExtent(self.left_layer.layer.extent())
|
||||
self.open1.setEnabled(True)
|
||||
except:
|
||||
return
|
||||
|
||||
def open_file2(self):
|
||||
path2 = QFileDialog.getOpenFileNames(self, '打开数据2', Settings.General().last_path, '*.*')
|
||||
if path2[0]!='':
|
||||
@ -216,12 +219,14 @@ class loader(QDialog):
|
||||
progress2=progressDialog(self,'加载时相二')
|
||||
progress2.setModal(False)
|
||||
# progress1.show
|
||||
self.temp2=os.path.join(Project().other_path,'temp2.tif')
|
||||
t1=GdalPreviewImage(self.path2,self.temp2,1024,self.parent())
|
||||
self.right_layer=MultiBandRasterLayer(path=self.path2)
|
||||
|
||||
t1=GdalPreviewImage(self.right_layer,self.right_map,width=200,parent=self.parent())
|
||||
|
||||
# t1.started.connect(progress1.show)
|
||||
t1.finished.connect(self.loadfile2)
|
||||
t1.finished.connect(lambda :self.open2.setEnabled(True))
|
||||
t1.finished.connect(lambda :self.setlabel(progress2))
|
||||
|
||||
t2=build_pyramids_overviews(self.path2,self.parent())
|
||||
t2.finished.connect(progress2.hide)
|
||||
t1.start()
|
||||
@ -230,24 +235,15 @@ class loader(QDialog):
|
||||
else:
|
||||
progress2=progressDialog(self,'加载时相二')
|
||||
progress2.setModal(False)
|
||||
self.temp2=os.path.join(Project().other_path,'temp2.tif')
|
||||
t1=GdalPreviewImage(self.path2,self.temp2,1024,self.parent())
|
||||
self.right_layer=MultiBandRasterLayer(path=self.path2)
|
||||
t1=GdalPreviewImage(self.right_layer,self.right_map,width=200,parent=self.parent())
|
||||
|
||||
# t1.started.connect(progress1.show)
|
||||
t1.finished.connect(self.loadfile2)
|
||||
t1.finished.connect(lambda :self.open2.setEnabled(True))
|
||||
t1.finished.connect(progress2.hide)
|
||||
t1.start()
|
||||
progress2.show()
|
||||
|
||||
|
||||
|
||||
def loadfile2(self):
|
||||
try:
|
||||
self.right_layer=MultiBandRasterLayer(path=self.temp2)
|
||||
self.mapcanva2.setLayers([self.right_layer.layer])
|
||||
self.mapcanva2.zoomToFeatureExtent(self.right_layer.layer.extent())
|
||||
self.open2.setEnabled(True)
|
||||
except:
|
||||
return
|
||||
def ok(self):
|
||||
self.bandsorder1=[int(q.text()) for q in self.style1_inputs ]
|
||||
self.style1={'r':self.bandsorder1[0],'g':self.bandsorder1[1],'b':self.bandsorder1[2],'NIR':self.bandsorder1[3]}
|
||||
@ -265,8 +261,7 @@ class loader(QDialog):
|
||||
def cancel(self):
|
||||
self.reject()
|
||||
|
||||
def open_alg(self,path):
|
||||
pass
|
||||
|
||||
def setlabel(self,s):
|
||||
try:
|
||||
s.setlabel('创建影像金字塔..')
|
||||
@ -276,72 +271,22 @@ class loader(QDialog):
|
||||
self.bandsorder1=[int(q.text()) for q in self.style1_inputs ]
|
||||
self.style1={'r':self.bandsorder1[0],'g':self.bandsorder1[1],'b':self.bandsorder1[2],'NIR':self.bandsorder1[3]}
|
||||
self.left_layer.set_stlye(self.style1)
|
||||
self.left_map.setPixmap(self.left_layer.previewAsPixmapo(width=200))
|
||||
|
||||
def set_style2(self):
|
||||
self.bandsorder2=[int(q.text()) for q in self.style2_inputs ]
|
||||
self.style2={'r':self.bandsorder2[0],'g':self.bandsorder2[1],'b':self.bandsorder2[2],'NIR':self.bandsorder2[3]}
|
||||
self.right_layer.set_stlye(self.style2)
|
||||
self.right_map.setPixmap(self.right_layer.previewAsPixmapo(width=200))
|
||||
|
||||
class GdalPreviewImage(QThread):
|
||||
def __init__(self,srcFile,tarFilename,width=1024.0,parent=None) -> None:
|
||||
def __init__(self,layer,map,width=200,parent=None) -> None:
|
||||
super(GdalPreviewImage,self).__init__(parent)
|
||||
self.srcFile=srcFile
|
||||
self.tarFilename=tarFilename
|
||||
self.layer=layer
|
||||
self.map=map
|
||||
self.width=width
|
||||
def run(self):
|
||||
try:
|
||||
srcFile=self.srcFile
|
||||
tarFilename=self.tarFilename
|
||||
width=self.width
|
||||
p=tarFilename
|
||||
dataset = gdal.Open(srcFile, gdal.GA_ReadOnly)
|
||||
srcProjection = dataset.GetProjection()
|
||||
srcGeoTransform = dataset.GetGeoTransform()
|
||||
srcWidth = dataset.RasterXSize
|
||||
srcHeight = dataset.RasterYSize
|
||||
srcBandCount = dataset.RasterCount
|
||||
# srcNoDatas = [
|
||||
# dataset.GetRasterBand(bandIndex).GetNoDataValue()
|
||||
# for bandIndex in range(1, srcBandCount+1)
|
||||
# ]
|
||||
# print(srcNoDatas)
|
||||
srcBandDataType = dataset.GetRasterBand(1).DataType
|
||||
# 创建重采样后的栅格
|
||||
outFilePath = p
|
||||
resampleFactor=width/srcWidth
|
||||
driver = gdal.GetDriverByName('GTiff')
|
||||
outWidth = int(srcWidth * resampleFactor)
|
||||
outHeight = int(srcHeight * resampleFactor)
|
||||
outDataset = driver.Create(
|
||||
outFilePath,
|
||||
outWidth,
|
||||
outHeight,
|
||||
srcBandCount,
|
||||
srcBandDataType
|
||||
)
|
||||
print(outDataset)
|
||||
geoTransforms = list(srcGeoTransform)
|
||||
geoTransforms[1] = geoTransforms[1]/resampleFactor
|
||||
geoTransforms[5] = geoTransforms[5]/resampleFactor
|
||||
outGeoTransform = tuple(geoTransforms)
|
||||
outDataset.SetGeoTransform(outGeoTransform)
|
||||
outDataset.SetProjection(srcProjection)
|
||||
# for bandIndex in range(1, srcBandCount+1):
|
||||
# band = outDataset.GetRasterBand(bandIndex)
|
||||
# band.SetNoDataValue(srcNoDatas[bandIndex-1])
|
||||
gdal.ReprojectImage(
|
||||
dataset,
|
||||
outDataset,
|
||||
srcProjection,
|
||||
srcProjection,
|
||||
gdal.gdalconst.GRA_NearestNeighbour,
|
||||
0.0, 0.0,
|
||||
)
|
||||
del outDataset
|
||||
except:
|
||||
pass
|
||||
|
||||
# return outFilePath
|
||||
self.map.setPixmap(self.layer.previewAsPixmapo(width=self.width))
|
||||
|
||||
|
||||
class build_pyramids_overviews(QThread):
|
||||
|
@ -15,10 +15,7 @@ from rscder.utils.icons import IconInstance
|
||||
from rscder.utils.project import Project
|
||||
from rscder.gui.layercombox import LayerCombox
|
||||
from rscder.gui.eagle_eye import eagleEye
|
||||
import skimage
|
||||
import numpy as np
|
||||
import sys
|
||||
import scipy
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
|
||||
closed = pyqtSignal()
|
||||
|
@ -92,8 +92,8 @@ class Create(QDialog):
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.setDirection(QHBoxLayout.RightToLeft)
|
||||
button_layout.addWidget(ok_button, 0, Qt.AlignRight)
|
||||
button_layout.addWidget(cancel_button, 0, Qt.AlignRight)
|
||||
button_layout.addWidget(ok_button, 0, Qt.AlignHCenter)
|
||||
button_layout.addWidget(cancel_button, 0, Qt.AlignHCenter)
|
||||
|
||||
main_layout = QVBoxLayout()
|
||||
main_layout.addLayout(file_input_layout)
|
||||
|
@ -62,7 +62,10 @@ class PluginLoader(QObject):
|
||||
self.plugins.append(obj(self.ctx))
|
||||
break
|
||||
except Exception as e:
|
||||
# import traceback
|
||||
# traceback.print_exc()
|
||||
self.ctx['message_box'].error(f'{plugin["name"]} load error: {e}')
|
||||
|
||||
|
||||
|
||||
self.plugin_loaded.emit()
|
19
rscder/utils/geomath.py
Normal file
19
rscder/utils/geomath.py
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
def imageRC2geo(geo:list,x,y):
|
||||
'''
|
||||
根据GDAL的六参数模型将影像图上坐标(行列号)转为投影坐标或地理坐标(根据具体数据的坐标系统转换)
|
||||
:param geo: GDAL地理数据,getGeotransform
|
||||
'''
|
||||
trans = geo
|
||||
px = trans[0] + x * trans[1] + y * trans[2]
|
||||
py = trans[3] + x * trans[4] + y * trans[5]
|
||||
return [px, py]
|
||||
|
||||
def geo2imageRC(geo:list,px,py):
|
||||
'''
|
||||
根据GDAL的六 参数模型将给定的投影或地理坐标转为影像图上坐标(行列号),return x,y
|
||||
'''
|
||||
dTemp = geo[1] * geo[5] - geo[2] *geo[4]
|
||||
x= int((geo[5] * (px - geo[0]) -geo[2] * (py - geo[3])) / dTemp + 0.5)
|
||||
y = int((geo[1] * (py - geo[3]) -geo[4] * (px - geo[0])) / dTemp + 0.5)
|
||||
return [x,y]
|
@ -8,6 +8,7 @@ from pathlib import Path
|
||||
from pydoc import render_doc
|
||||
import shutil
|
||||
from statistics import stdev
|
||||
from tabnanny import check
|
||||
from threading import Thread
|
||||
from time import sleep, time
|
||||
from typing import Dict, List
|
||||
@ -26,9 +27,9 @@ from qgis.core import (\
|
||||
QgsGeometry, QgsPointXY, QgsMultiBandColorRenderer)
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, Qt, QThread,QSize
|
||||
from PyQt5.QtWidgets import QTreeWidgetItem, QAction,QMessageBox
|
||||
from PyQt5.QtGui import QColor, QIcon, QFont
|
||||
from PyQt5.QtGui import QColor, QIcon, QFont,QPixmap
|
||||
import yaml
|
||||
|
||||
from rscder.utils.geomath import geo2imageRC,imageRC2geo
|
||||
from .misc import singleton
|
||||
def relative_path(path: str, root:str) -> str:
|
||||
return os.path.relpath(path, root)
|
||||
@ -235,6 +236,7 @@ def from_dict(data:dict):
|
||||
if cls_type is not None and cls_type in globals():
|
||||
return globals()[cls_type](**data)
|
||||
|
||||
|
||||
class BasicLayer(QObject):
|
||||
|
||||
LEFT_VIEW=1
|
||||
@ -375,13 +377,13 @@ class GridLayer(BasicLayer):
|
||||
self.x_lines = []
|
||||
for xi in range(self.x_size // self.cell_size[0] +1):
|
||||
self.x_lines.append(self.x_min + self.x_res * xi * self.cell_size[0])
|
||||
if self.x_lines[-1] == self.x_max:
|
||||
if self.x_lines[-1] > self.x_max:
|
||||
self.x_lines.pop()
|
||||
self.x_lines.append(self.x_max)
|
||||
self.y_lines = []
|
||||
for yi in range(self.y_size // self.cell_size[1]+1):
|
||||
self.y_lines.append(self.y_min + self.y_res * yi * self.cell_size[1])
|
||||
if self.y_lines[-1] == self.y_max:
|
||||
if self.y_lines[-1] < self.y_max:
|
||||
self.y_lines.pop()
|
||||
self.y_lines.append(self.y_max)
|
||||
crs = QgsCoordinateReferenceSystem()
|
||||
@ -408,11 +410,13 @@ class GridLayer(BasicLayer):
|
||||
|
||||
self.set_render()
|
||||
|
||||
|
||||
|
||||
class Mask(object):
|
||||
def __init__(self,geoxy) -> None:
|
||||
super().__init__()
|
||||
self.xy=geoxy
|
||||
class RasterLayer(BasicLayer):
|
||||
|
||||
def __init__(self, name=None, enable=False, path=None, view_mode=BasicLayer.BOATH_VIEW,style_info={'r':3,'g':2,'b':1,'NIR':0}):
|
||||
def __init__(self, name=None, enable=False, path=None, view_mode=BasicLayer.BOATH_VIEW,style_info={'r':1,'g':2,'b':3,'NIR':0}):
|
||||
if name is None:
|
||||
name = os.path.splitext(os.path.basename(path))[0]
|
||||
super().__init__(name, enable, IconInstance().RASTER, path, BasicLayer.IN_FILE, view_mode)
|
||||
@ -420,18 +424,68 @@ class RasterLayer(BasicLayer):
|
||||
self.style_info=style_info
|
||||
self.apply_style()
|
||||
def compare(self, other:'RasterLayer'):
|
||||
ds1 = gdal.Open(self.path)
|
||||
ds2 = gdal.Open(other.path)
|
||||
'''
|
||||
与其他图像比较,看是否处于同一投影,有无重叠区域,能否进行变化检测
|
||||
other:其它同类图层
|
||||
return:-1,无法进行比较;0,有重叠区域;1,完全重叠。
|
||||
'''
|
||||
ds1:gdal.Dataset = gdal.Open(self.path)
|
||||
ds2 :gdal.Dataset = gdal.Open(other.path)
|
||||
geo1=ds1.GetGeoTransform()
|
||||
geo2=ds2.GetGeoTransform()
|
||||
map1xy=[imageRC2geo(geo1,0,0),imageRC2geo(geo1,ds1.RasterXSize,ds1.RasterYSize)]
|
||||
map2xy=[imageRC2geo(geo2,0,0),imageRC2geo(geo2,ds2.RasterXSize,ds2.RasterYSize)]
|
||||
map1xx=[map1xy[0][0],map1xy[1][0]]
|
||||
map1yy=[map1xy[0][1],map1xy[1][1]]
|
||||
map2xx=[map2xy[0][0],map2xy[1][0]]
|
||||
map2yy=[map2xy[0][1],map2xy[1][1]]
|
||||
map1xx.sort()
|
||||
map1yy.sort()
|
||||
map2yy.sort()
|
||||
map2xx.sort()
|
||||
if ds1 is None or ds2 is None:
|
||||
Project().message_box.error('图层打开失败')
|
||||
return False
|
||||
|
||||
if ds1.RasterXSize != ds2.RasterXSize or ds1.RasterYSize != ds2.RasterYSize:
|
||||
Project().message_box.error('图层尺寸不一致')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
return -1
|
||||
if not ds1.GetProjection()==ds2.GetProjection():
|
||||
Project().message_box.error('投影不一致')
|
||||
return -1
|
||||
elif (map1xx[0]>map2xx[1] or map1xx[1]<map2xx[0])or(map1yy[0]>map2yy[1] or map1yy[1]<map2yy[0] ):
|
||||
Project().message_box.error('图层无重叠区域')
|
||||
return -1
|
||||
elif ds1.RasterXSize == ds2.RasterXSize and ds1.RasterYSize == ds2.RasterYSize and geo1==geo2:
|
||||
# Project().message_box.error('两图一致')
|
||||
return 1
|
||||
#图层尺寸相同
|
||||
Project().message_box.warning('图层不完全重叠')
|
||||
del ds1
|
||||
del ds2
|
||||
return 0
|
||||
def overlap(self,other:'RasterLayer'):
|
||||
'''
|
||||
与其他图像比较,看是否处于同一投影,有无重叠区域,能否进行变化检测
|
||||
other:其它同类图层
|
||||
return:[重叠区域左上点xy,重叠区域右下点xy]
|
||||
'''
|
||||
ds1:gdal.Dataset = gdal.Open(self.path)
|
||||
ds2 :gdal.Dataset = gdal.Open(other.path)
|
||||
geo1=ds1.GetGeoTransform()
|
||||
geo2=ds2.GetGeoTransform()
|
||||
#地理(投影)坐标,y向下变小
|
||||
map1xy=[imageRC2geo(geo1,0,0),imageRC2geo(geo1,ds1.RasterXSize,ds1.RasterYSize)]
|
||||
map2xy=[imageRC2geo(geo2,0,0),imageRC2geo(geo2,ds2.RasterXSize,ds2.RasterYSize)]
|
||||
xx=[map1xy[0][0],map1xy[1][0],map2xy[0][0],map2xy[1][0]]
|
||||
yy=[map1xy[0][1],map1xy[1][1],map2xy[0][1],map2xy[1][1]]
|
||||
xx.sort()
|
||||
yy.sort()
|
||||
return [xx[1],yy[2],xx[2],yy[1]]
|
||||
@property
|
||||
def band(self):
|
||||
ds:gdal.Dataset = gdal.Open(self.path)
|
||||
if ds is None:
|
||||
return None
|
||||
band = ds.RasterCount
|
||||
del ds
|
||||
return band
|
||||
@property
|
||||
def geo(self):
|
||||
ds = gdal.Open(self.path)
|
||||
@ -493,6 +547,13 @@ class RasterLayer(BasicLayer):
|
||||
'prewmap':self.preview
|
||||
}
|
||||
return mapinfo
|
||||
|
||||
def previewAsPixmapo(self,width,height=None):
|
||||
w=self.layer.width()
|
||||
h=self.layer.height()
|
||||
if height:
|
||||
return QPixmap.fromImage(self.layer.previewAsImage(QSize(width,height)))
|
||||
return QPixmap.fromImage(self.layer.previewAsImage(QSize(width,int(width*h/w))))
|
||||
@property
|
||||
def preview(self,width=400):
|
||||
w=self.layer.width()
|
||||
@ -505,16 +566,30 @@ class MultiBandRasterLayer(RasterLayer):
|
||||
renderer=QgsMultiBandColorRenderer(self.layer.dataProvider(),self.style_info['r'],self.style_info['g'],self.style_info['b'])
|
||||
self.layer.setRenderer(renderer)
|
||||
self.layer.triggerRepaint()
|
||||
# @property
|
||||
# def info(self):
|
||||
# mapinfo=super().info
|
||||
# mapinfo['渲染属性']['波段']='单波段'
|
||||
def toArray(self,mask=None,band:list=None):
|
||||
ds:gdal.Dataset=gdal.Open(self.path)
|
||||
res=None
|
||||
startx=0
|
||||
starty=0
|
||||
xsize=ds.RasterXSize
|
||||
ysize=ds.RasterYSize
|
||||
if mask:
|
||||
#转为图像坐标
|
||||
startx,starty=geo2imageRC(self.geo,mask[0],mask[1])
|
||||
x2,y2=geo2imageRC(self.geo,mask[2],mask[3])
|
||||
xsize=x2-startx
|
||||
ysize=y2-starty
|
||||
res=ds.ReadAsArray(startx,starty,xsize,ysize,band_list=band)
|
||||
del ds
|
||||
return res
|
||||
def readAsArray(self,xoff: int = 0, yoff: int = 0, xsize= None, ysize = None, buf_obj= None, buf_xsize= None, buf_ysize = None, buf_type= None, callback = None, callback_data = None, interleave = 'band', band_list = None):
|
||||
ds:gdal.Dataset = gdal.Open(self.path)
|
||||
array=ds.ReadAsArray(xoff= 0, yoff= 0, xsize= None, ysize = None, buf_obj= None, buf_xsize= None, buf_ysize = None, buf_type= None, callback = None, callback_data = None, interleave= 'band', band_list = None)
|
||||
return array
|
||||
class SingleBandRasterLayer(RasterLayer):
|
||||
|
||||
def apply_style(self):
|
||||
pass
|
||||
|
||||
|
||||
class VectorLayer(BasicLayer):
|
||||
pass
|
||||
|
||||
@ -696,7 +771,7 @@ class ResultPointLayer(BasicLayer):
|
||||
return {'基础属性':basic,'渲染属性':render}
|
||||
class PairLayer(BasicLayer):
|
||||
|
||||
def __init__(self, pth1, pth2,style_info1,style_info2) -> None:
|
||||
def __init__(self, pth1, pth2,style_info1,style_info2,mask=None) -> None:
|
||||
|
||||
self.layers:List[BasicLayer] = []
|
||||
self.id = str(uuid.uuid1())
|
||||
@ -708,25 +783,38 @@ class PairLayer(BasicLayer):
|
||||
self.grid = None
|
||||
self.cell_size = Project().cell_size
|
||||
name = os.path.basename(pth1)[:4] + '-' + os.path.basename(pth2)[:4]
|
||||
self.mask=mask
|
||||
# self.layer_update.connect(Project().layer_updated)
|
||||
|
||||
super().__init__(name, True, IconInstance().DOCUMENT)
|
||||
self.layer = self.main_l1.layer
|
||||
if self.check():
|
||||
self.geo = self.main_l1.geo
|
||||
self.proj = self.main_l1.proj
|
||||
self.size = self.main_l1.size
|
||||
self.layers.append(self.main_l1)
|
||||
self.layers.append(self.main_l2)
|
||||
self.grid = GridLayer(self.proj, self.geo, self.size[0], self.size[1], cell_size=Project().cell_size)
|
||||
self.grid.set_layer_parent(self)
|
||||
|
||||
# self.layers.append(self.grid)
|
||||
@property
|
||||
def l1_geo(self):
|
||||
return self.main_l1.geo
|
||||
@property
|
||||
def l2_geo(self):
|
||||
return self.main_l2.geo
|
||||
|
||||
def check(self):
|
||||
if self.checked:
|
||||
return self.checked
|
||||
self.checked = self.main_l1.compare(self.main_l2)
|
||||
return self.checked
|
||||
if not self.checked==-1:#重叠
|
||||
self.mask=Mask(self.main_l1.overlap(self.main_l2))
|
||||
x1,y1=geo2imageRC(self.l1_geo,*self.mask.xy[0:2])
|
||||
x2,y2=geo2imageRC(self.l1_geo,*self.mask.xy[2:])
|
||||
self.size=[x2-x1,y2-y1]
|
||||
self.geo = self.main_l1.geo
|
||||
self.proj = self.main_l1.proj
|
||||
gridgeo=[self.mask.xy[0],self.l1_geo[1],self.l1_geo[2],self.mask.xy[1],self.l1_geo[4],self.l1_geo[5]]
|
||||
self.grid = GridLayer(self.proj, gridgeo , self.size[0], self.size[1], cell_size=Project().cell_size)
|
||||
self.grid.set_layer_parent(self)
|
||||
return self.checked!=-1
|
||||
|
||||
def add_result_layer(self, result):
|
||||
result.set_layer_parent(self)
|
||||
@ -763,10 +851,12 @@ class PairLayer(BasicLayer):
|
||||
pth2=self.main_l2.path,
|
||||
style_info1=self.main_l1.style_info,
|
||||
style_info2=self.main_l2.style_info,
|
||||
layers=[to_dict(l) for l in self.layers if not (l is self.grid or l is self.main_l1 or l is self.main_l2) ]
|
||||
layers=[to_dict(l) for l in self.layers if not (l is self.grid or l is self.main_l1 or l is self.main_l2) ],
|
||||
|
||||
)
|
||||
return data
|
||||
|
||||
|
||||
@property
|
||||
def info(self):
|
||||
|
||||
@ -791,7 +881,9 @@ class PairLayer(BasicLayer):
|
||||
|
||||
#公共掩模
|
||||
maskData={}
|
||||
|
||||
if self.mask:
|
||||
maskData['左上角坐标']=self.mask.xy[0:2]
|
||||
maskData['右下角坐标']=self.mask.xy[2:]
|
||||
|
||||
mapinfo={
|
||||
'坐标系':metadata,
|
||||
|
Loading…
x
Reference in New Issue
Block a user