diff --git a/.gitignore b/.gitignore
index c239d90..b6cec3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -222,7 +222,11 @@ share
nuitka.help
log.txt
-
+logs/
+*.7z
+*.zip*
+*.tar.gz
+install/
!plugins/unsupervised_method/scripts/*.pyd
!plugins/*/scripts/*.pyd
diff --git a/ReadMe.md b/ReadMe.md
deleted file mode 100644
index b0ad41e..0000000
--- a/ReadMe.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# 变化检测
-王铜
-CVEO团队
-
-# 环境
-Python3.7 + PyQt + QGIS
-
-## 配置方式
-
-```
-conda create -f conda.yaml
-```
-或
-
-```
-conda env create -n cevo_qt -f conda.yaml
-```
-
-
-# 打包方式
-
-1. 打包keygen:
-
-```
-nuitka keygen.py --standalone --plugin-enable=qt-plugins --plugin-enable=numpy --show-progress --include-package=qgis --plugin-enable=pylint-warnings --output-dir=package --windows-disable-console --windows-icon-from-ico=logo.ico --no-pyi-file
-```
-
-2. 打包主体:
-
-```
-nuitka RSCDer.py --standalone --plugin-enable=qt-plugins --plugin-enable=numpy --show-progress --include-package=qgis --plugin-enable=pylint-warnings --output-dir=package --windows-disable-console --windows-icon-from-ico=logo.ico --no-pyi-file
-
-```
-
-3. 打包插件:
-
-```
-python setup.py
-```
-
-# 功能
-
-1. 证书检查与生成
- 1. 基于MAC地址与过期时间进行证书生成,启动时检查证书,过期则退出
-2. 工程管理
- 1. 以工程为单位进行数据管理与生产
- 2. 提供工程保存与导入功能
- 3. 提供多种格式的栅格数据导入(TIF、PNG、BMP、JPG)等
- 4. 提供矢量数据导入
-3. 基本工具
- 1. 双视图同步浏览
- 2. 格网展示
diff --git a/build.bat b/build.bat
deleted file mode 100644
index ab9f59d..0000000
--- a/build.bat
+++ /dev/null
@@ -1,11 +0,0 @@
-nuitka ECD.py --standalone --plugin-enable=pyqt5 --include-qt-plugins=sensible,styles --plugin-enable=numpy --nofollow-import-to=cv2 --nofollow-import-to=scipy --nofollow-import-to=yaml --nofollow-import-to=matplotlib --nofollow-import-to=PIL --nofollow-import-to=skimage --nofollow-import-to=numpy --nofollow-import-to=osgeo --nofollow-import-to=cryptography --nofollow-import-to=brotli --nofollow-import-to=cffi --show-progress --include-package=qgis --include-package=distutils --output-dir=package --windows-icon-from-ico=logo.ico --windows-disable-console
-
-@REM nuitka ECD.py --standalone --plugin-enable=pyqt5 --include-qt-plugins=sensible,styles --plugin-enable=numpy --plugin-enable=anti-bloat --show-progress --include-package=qgis --output-dir=package --windows-icon-from-ico=logo.ico
-@REM nuitka keygen.py --standalone --plugin-enable=qt-plugins --plugin-enable=numpy --show-progress --plugin-enable=pylint-warnings --output-dir=package --windows-disable-console --windows-icon-from-ico=logo.ico --no-pyi-file
-
-
-REM Win7 with console
-REM nuitka gui.py --mingw64 --standalone --plugin-enable=qt-plugins --plugin-enable=numpy --recurse-all --show-progress --include-package=qgis --output-dir=package --windows-icon=icons/logo.ico
-
-REM Win7
-@REM nuitka gui.py --mingw64 --standalone --plugin-enable=qt-plugins --plugin-enable=numpy --recurse-all --show-progress --include-package=qgis --output-dir=package --windows-disable-console --windows-icon=icons/logo.ico
\ No newline at end of file
diff --git a/conda.yaml b/conda.yaml
deleted file mode 100644
index 96a0a96..0000000
--- a/conda.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: cveo_ss
-channels:
- - conda-forge
- - defaults
-dependencies:
- - cryptography=3.4.7
- - gdal=3.3
- - pyqt=5.12.3
- - pyqtads=3.8.2
- - python=3.7.10
- - python=3.7
- - qgis=3.18.3
- - scikit-image
- - scipy
- - pip:
- - attrs==21.4.0
- - cython==0.29.24
- - nuitka==0.8.3
- - opencv-python==4.5.3.56
- - pillow==6.2.2
- - pycryptodome==3.14.1
- - scikit-learn==1.0.2
- - sklearn==0.0
\ No newline at end of file
diff --git a/lic_t.lic b/lic_t.lic
deleted file mode 100644
index 02a42fd..0000000
--- a/lic_t.lic
+++ /dev/null
@@ -1 +0,0 @@
-IieXktda+1nRK9zLwe87uPPn2VpCwmUrEOPfyenaW/Sek70/CqqbCr7nangL1+pVXSkzDELia7Qq8e+pDMuHCXzxyJOALRj4j3bhFVExwqSTLuXwdev1e26nr7vnECl7H0SCVynr8To7ciwcnmK6HJXre6i+mBdTjACmKseTMlWp480XOt7uHysltORbTA3J
\ No newline at end of file
diff --git a/license.lic b/license.lic
deleted file mode 100644
index fcdb940..0000000
--- a/license.lic
+++ /dev/null
@@ -1 +0,0 @@
-vd4FiYncytyziGH9GNCAA8hGGr1/79Xmphtc5+PHPJDpxvqj1hP7+985QMojYO4M5Qn/aqEAvFgeDN3CA8x1YAK8SdCgSXSBJpRBK8wqPQjBY1ak96QfdPCrTLunr+xuPxK3Gxe772adTTsee2+ot7WePYUsC4y4NcS5+rlP1if87xtYqVeSwx3c64cOmAGP
\ No newline at end of file
diff --git a/plugins/export_to/main.py b/plugins/export_to/main.py
index 5c0ad22..bb6868d 100644
--- a/plugins/export_to/main.py
+++ b/plugins/export_to/main.py
@@ -6,6 +6,8 @@ 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
+from osgeo import gdal, gdal_array
+import numpy as np
class ExportDialog(QDialog):
TXT='*.txt'
@@ -90,8 +92,12 @@ class ExportPlugin(BasicPlugin):
self.export_bin = QAction(IconInstance().DOCUMENT, '导出栅格二值变化检测结果')
self.export_bin.triggered.connect(self.export_bin_action)
+
+ self.export_rgb = QAction(IconInstance().DOCUMENT, '导出变化幅度渲染结果')
+ self.export_rgb.triggered.connect(self.export_rgb_action)
ActionManager().export_menu.addAction(self.export_txt)
ActionManager().export_menu.addAction(self.export_bin)
+ ActionManager().export_menu.addAction(self.export_rgb)
# self.ctx['toolbar'].addAction(self.export_txt)
@@ -111,4 +117,82 @@ class ExportPlugin(BasicPlugin):
out = dialog.out_path
if result:
shutil.copy(result.path, out)
- self.message_box.info('导出成功')
\ No newline at end of file
+ self.message_box.info('导出成功')
+
+ def export_rgb_action(self):
+ dialog = ExportDialog(self.mainwindow, ExportDialog.TIF)
+ btn = QPushButton('选择样式文件')
+ style_path = ''
+ def select_style():
+ select_file = QFileDialog.getOpenFileName(self, '选择样式文件', '*.*')
+ if select_file[0]:
+ # style_path.setText(select_file[0])
+ style_path = select_file[0]
+ btn.setText(select_file[0])
+ btn.clicked.connect(select_style)
+ dialog.layout().addWidget(btn)
+
+ default_style = [
+ [0, 0, 255, 0],
+ [1, 255, 0, 0]
+ ]
+
+ if style_path is '':
+ style = default_style
+ else:
+ style = np.loadtxt(style_path, comments='#', delimiter=',')
+ style = style.tolist()
+
+ if dialog.exec_():
+ result = dialog.result_layer.path
+ out = dialog.out_path
+ self.render(style, result, out)
+
+ def render(self, style:list, path, out):
+ data = gdal_array.LoadFile(path)
+ if len(data.shape) == 3:
+ data = data[..., 0]
+
+ def get_color(v):
+ first_color = []
+ second_color = []
+ first_value = 0
+ second_value = 1
+ for s in style:
+ if s[0] <= v:
+ first_value = s[0]
+ first_color = s[1:]
+ else:
+ second_value = s[0]
+ second_color = s[1:]
+ break
+ if second_value == -1:
+ return np.array(style[-1][1:])
+
+ first_dis = (v - first_value) / (second_value - first_value)
+ second_dis = (second_value - v) / (second_value - first_value)
+ first_color = np.array(first_color)
+ second_color = np.array(second_color)
+ color = first_color* first_dis + second_color * second_dis
+ return color
+
+
+ get_color = np.frompyfunc(get_color, nin=1, nout=1)
+
+ Y, X = data.shape
+ rgbs = get_color(data.reshape(-1,))
+ rgbs = np.stack(rgbs).reshape((Y, X, 3)).astype(np.uint8)
+
+ driver = gdal.GetDriverByName('GTiff')
+ # out_tif = os.path.join(Project().other_path, 'temp.tif')
+ out_ds = driver.Create(out, X, Y, 3, gdal.GDT_Byte)
+ ds = gdal.Open(path)
+ geo = ds.GetGeoTransform()
+ proj = ds.GetProjectionRef()
+ out_ds.SetGeoTransform(geo)
+ out_ds.SetProjection(proj)
+
+ for i in range(3):
+ out_ds.GetRasterBand(i+1).WriteArray(rgbs[..., i])
+
+ del out_ds
\ No newline at end of file
diff --git a/plugins/filter_collection/__init__.py b/plugins/filter_collection/__init__.py
index fc6ffc4..f59d8c1 100644
--- a/plugins/filter_collection/__init__.py
+++ b/plugins/filter_collection/__init__.py
@@ -5,4 +5,7 @@ FILTER = Register('滤波处理算法')
from .mean_filter import MeanFilter
from filter_collection.main import *
from .morphology_filter import MorphologyFilter
-from .bilater_filter import BilaterFilter
\ No newline at end of file
+from .bilater_filter import BilaterFilter
+from .lee_filter import LeeFilter
+from .lms_filter import AdaptiveFilter
+from .lmsnp_filter import AdaptiveNPFilter
\ No newline at end of file
diff --git a/plugins/filter_collection/lee_filter.py b/plugins/filter_collection/lee_filter.py
new file mode 100644
index 0000000..4bea138
--- /dev/null
+++ b/plugins/filter_collection/lee_filter.py
@@ -0,0 +1,112 @@
+from misc import AlgFrontend
+from misc.utils import format_now
+from osgeo import gdal, gdal_array
+from skimage.filters import rank
+from skimage.morphology import rectangle
+from filter_collection import FILTER
+from PyQt5.QtWidgets import QDialog, QAction
+from PyQt5 import QtCore, QtGui, QtWidgets
+from rscder.utils.project import PairLayer, Project, RasterLayer, ResultPointLayer
+from rscder.utils.icons import IconInstance
+import os
+from datetime import datetime
+
+from scipy.ndimage.filters import uniform_filter
+from scipy.ndimage.measurements import variance
+
+def lee_filter(img, size):
+ img_mean = uniform_filter(img, size)
+ img_sqr_mean = uniform_filter(img**2, size)
+ img_variance = img_sqr_mean - img_mean**2
+
+ overall_variance = variance(img)
+
+ img_weights = img_variance / (img_variance + overall_variance)
+ img_output = img_mean + img_weights * (img - img_mean)
+ return img_output
+
+@FILTER.register
+class LeeFilter(AlgFrontend):
+
+ @staticmethod
+ def get_name():
+ return 'Lee滤波'
+
+ @staticmethod
+ def get_icon():
+ return IconInstance().ARITHMETIC2
+
+ @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
+ name = os.path.splitext(os.path.basename(pth))[0]
+ out_path = os.path.join(Project().other_path, '{}_{}_{}.tif'.format(name, LeeFilter.get_name(), format_now()))
+ 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 = lee_filter(data, (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
diff --git a/plugins/filter_collection/lms_filter.py b/plugins/filter_collection/lms_filter.py
new file mode 100644
index 0000000..81def22
--- /dev/null
+++ b/plugins/filter_collection/lms_filter.py
@@ -0,0 +1,140 @@
+from misc import AlgFrontend
+from misc.utils import format_now
+from osgeo import gdal, gdal_array
+from skimage.filters import rank
+from skimage.morphology import rectangle
+from filter_collection import FILTER
+from PyQt5.QtWidgets import QDialog, QAction
+from PyQt5 import QtCore, QtGui, QtWidgets
+from rscder.utils.project import PairLayer, Project, RasterLayer, ResultPointLayer
+from rscder.utils.icons import IconInstance
+import os
+from datetime import datetime
+import numpy as np
+import torch
+import torch.nn.functional as F
+def adaptiveMedianDeNoise(count, original):
+ # 初始窗口大小
+ startWindow = 3
+ # 卷积范围
+ c = count // 2
+ rows, cols = original.shape
+ newI = np.zeros(original.shape)
+ # median =
+
+ for i in range(c, rows - c):
+ for j in range(c, cols - c):
+ k = int(startWindow / 2)
+ median = np.median(original[i - k:i + k + 1, j - k:j + k + 1])
+ mi = np.min(original[i - k:i + k + 1, j - k:j + k + 1])
+ ma = np.max(original[i - k:i + k + 1, j - k:j + k + 1])
+ if mi < median < ma:
+ if mi < original[i, j] < ma:
+ newI[i, j] = original[i, j]
+ else:
+ newI[i, j] = median
+
+ else:
+ while True:
+ startWindow = startWindow + 2
+ k = int(startWindow / 2)
+ median = np.median(original[i - k:i + k + 1, j - k:j + k + 1])
+ mi = np.min(original[i - k:i + k + 1, j - k:j + k + 1])
+ ma = np.max(original[i - k:i + k + 1, j - k:j + k + 1])
+
+ if mi < median < ma or startWindow > count:
+ break
+
+ if mi < median < ma or startWindow > count:
+ if mi < original[i, j] < ma:
+ newI[i, j] = original[i, j]
+ else:
+ newI[i, j] = median
+
+ return newI
+
+@FILTER.register
+class AdaptiveFilter(AlgFrontend):
+
+ @staticmethod
+ def get_name():
+ return '自适应滤波'
+
+ @staticmethod
+ def get_icon():
+ return IconInstance().ARITHMETIC2
+
+ @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)
+
+ x_input = widget.findChild(QtWidgets.QLineEdit, 'xinput')
+ # y_input = widget.findChild(QtWidgets.QLineEdit, 'yinput')
+
+ if x_input is None:
+ return dict(x_size=3)
+
+ x_size = int(x_input.text())
+ # y_size = int(y_input.text())
+
+ return dict(x_size=x_size)
+
+ @staticmethod
+ def run_alg(pth, x_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
+ name = os.path.splitext(os.path.basename(pth))[0]
+ out_path = os.path.join(Project().other_path, '{}_{}_{}.tif'.format(name, AdaptiveFilter.get_name(), format_now()))
+ 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 = adaptiveMedianDeNoise(x_size, data)
+
+ out_band = out_ds.GetRasterBand(i+1)
+ out_band.WriteArray(data)
+
+ out_ds.FlushCache()
+ del out_ds
+ del ds
+ return out_path
diff --git a/plugins/filter_collection/lmsnp_filter.py b/plugins/filter_collection/lmsnp_filter.py
new file mode 100644
index 0000000..0afabd2
--- /dev/null
+++ b/plugins/filter_collection/lmsnp_filter.py
@@ -0,0 +1,128 @@
+from misc import AlgFrontend
+from misc.utils import format_now
+from osgeo import gdal, gdal_array
+from skimage.filters import rank
+from skimage.morphology import rectangle
+from filter_collection import FILTER
+from PyQt5.QtWidgets import QDialog, QAction
+from PyQt5 import QtCore, QtGui, QtWidgets
+from rscder.utils.project import PairLayer, Project, RasterLayer, ResultPointLayer
+from rscder.utils.icons import IconInstance
+import os
+from datetime import datetime
+import numpy as np
+import torch
+import torch.nn.functional as F
+def adaptiveMedianDeNoise(count, original):
+ # 初始窗口大小
+ startWindow = 3
+ # 卷积范围
+ c = count // 2
+ rows, cols = original.shape
+ newI = np.zeros(original.shape)
+ # median =
+
+ for i in range(c, rows - c):
+ for j in range(c, cols - c):
+ k = int(startWindow / 2)
+ median = np.median(original[i - k:i + k + 1, j - k:j + k + 1])
+ mi = np.min(original[i - k:i + k + 1, j - k:j + k + 1])
+ ma = np.max(original[i - k:i + k + 1, j - k:j + k + 1])
+ if mi < median < ma:
+ if mi < original[i, j] < ma:
+ newI[i, j] = original[i, j]
+ else:
+ newI[i, j] = median
+
+ else:
+ while True:
+ startWindow = startWindow + 2
+ k = int(startWindow / 2)
+ median = np.median(original[i - k:i + k + 1, j - k:j + k + 1])
+ mi = np.min(original[i - k:i + k + 1, j - k:j + k + 1])
+ ma = np.max(original[i - k:i + k + 1, j - k:j + k + 1])
+
+ if mi < median < ma or startWindow > count:
+ break
+
+ if mi < median < ma or startWindow > count:
+ if mi < original[i, j] < ma:
+ newI[i, j] = original[i, j]
+ else:
+ newI[i, j] = median
+
+ return newI
+
+@FILTER.register
+class AdaptiveNPFilter(AlgFrontend):
+
+ @staticmethod
+ def get_name():
+ return '自动滤波(无参自适应滤波)'
+
+ @staticmethod
+ def get_icon():
+ return IconInstance().ARITHMETIC2
+
+ @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 None
+
+ @staticmethod
+ def get_params(widget:QtWidgets.QWidget=None):
+ return dict()
+
+ @staticmethod
+ def run_alg(pth, x_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
+ name = os.path.splitext(os.path.basename(pth))[0]
+ out_path = os.path.join(Project().other_path, '{}_{}_{}.tif'.format(name, AdaptiveNPFilter.get_name(), format_now()))
+ 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 = adaptiveMedianDeNoise(5, data)
+
+ out_band = out_ds.GetRasterBand(i+1)
+ out_band.WriteArray(data)
+
+ out_ds.FlushCache()
+ del out_ds
+ del ds
+ return out_path
diff --git a/plugins/unsupervised_method/scripts/__init__.py b/plugins/unsupervised_method/scripts/__init__.py
index 56be14c..b4ffddb 100644
--- a/plugins/unsupervised_method/scripts/__init__.py
+++ b/plugins/unsupervised_method/scripts/__init__.py
@@ -164,6 +164,132 @@ class BasicCD(AlgFrontend):
return out_normal_tif
+@UNSUPER_CD.register
+class LogCD(AlgFrontend):
+
+ @staticmethod
+ def get_name():
+ return '对数比值法'
+
+ @staticmethod
+ def get_icon():
+ return IconInstance().ARITHMETIC3
+
+ @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])
+
+ if block_size1[0] * block_size1[1] == 0 or block_size2[0] * block_size2[1] == 0:
+ continue
+
+ block_data1 = ds1.ReadAsArray(*block_xy1, *block_size1)
+ block_data2 = ds2.ReadAsArray(*block_xy2, *block_size2)
+ # if block_data1.shape[0] == 0:
+ # continue
+ if band == 1:
+ block_data1 = block_data1[None, ...]
+ block_data2 = block_data2[None, ...]
+ # pdb.set_trace()
+
+ block_diff = np.log( block_data1.sum(0) / (block_data2.sum(0) + 1e-6 ) )
+ 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):
@@ -444,7 +570,7 @@ class CVAAlg(AlgFrontend):
return out_normal_tif
-@UNSUPER_CD.register
+# @UNSUPER_CD.register
class ACDAlg(AlgFrontend):
@staticmethod
@@ -524,6 +650,7 @@ class AHTAlg(AlgFrontend):
@staticmethod
def run_alg(pth1: str, pth2: str, layer_parent: PairLayer, send_message=None, *args, **kargs):
+
if send_message is None:
class Empty:
@@ -559,11 +686,11 @@ class AHTAlg(AlgFrontend):
send_message.emit('图像一提取完成')
# 运算
- send_message.emit('开始AHT计算.....')
+ 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)))
- AHT(temp_tif1, temp_tif2, out_normal_tif)
+ LHBA(temp_tif1, temp_tif2, out_normal_tif)
# 添加投影
send_message.emit('录入投影信息.....')
time.sleep(0.1)
@@ -571,11 +698,10 @@ class AHTAlg(AlgFrontend):
ds.SetGeoTransform(geo)
ds.SetProjection(proj)
del ds
-
return out_normal_tif
-@UNSUPER_CD.register
+# @UNSUPER_CD.register
class OCDAlg(AlgFrontend):
@staticmethod
@@ -766,3 +892,234 @@ class SHAlg(AlgFrontend):
ds.SetProjection(proj)
del ds
return out_normal_tif
+
+
+
+@UNSUPER_CD.register
+class KPVDAlg(AlgFrontend):
+
+ @staticmethod
+ def get_name():
+ return 'KPVD'
+
+ @staticmethod
+ def get_icon():
+ return IconInstance().ARITHMETIC3
+
+ @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 MOHDAlg(AlgFrontend):
+
+ @staticmethod
+ def get_name():
+ return 'MOHD'
+
+ @staticmethod
+ def get_icon():
+ return IconInstance().ARITHMETIC3
+
+ @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
diff --git a/res.qrc b/res.qrc
deleted file mode 100644
index 60b5d4a..0000000
--- a/res.qrc
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
- icons/AI仯.png
- icons/ʹð.png
- icons/·仯.png
- icons/
- icons/.png
- icons/ɾ.png
- icons/ѧ.png
- icons/.png
- icons/ȥ.png
- icons/˫.png
- icons/.png
- icons/ͼ.png
- icons/ͼ.png
- icons/ͼ.png
- icons/λ.png
- icons/.png
- icons/.png
- icons/̱.png
- icons/ (1).png
- icons/.png
- icons/ƽ.png
- icons/ල.png
- icons/Ӱ.png
- icons/.png
- icons/ (1).png
- icons/-չ.png
- icons/-.png
- icons/.png
- icons/ݼ.png
- icons/ļ.png
- icons/ĵ.png
- icons/ֲ仯.bmp
- icons/ˮ仯.png
- icons/仯.png
- icons/±仯.png
- icons/˲.png
- icons/ر仯.png
- icons/涨.png
- icons/ල.png
- icons/ʸ.png
- icons/ر.png
- icons/.png
- icons/ͼ.png
- icons/˳.png
- icons/ѡҪ.png
- icons/·仯.png
- icons/ң.png
- icons/·仯.png
- icons/Ǽල.png
-
-
diff --git a/result.txt b/result.txt
new file mode 100644
index 0000000..6e23ced
--- /dev/null
+++ b/result.txt
@@ -0,0 +1,118 @@
+x,y,diff,status
+234053.9937022142,3530980.0747939292,80.47999999999999,1
+234153.9937022142,3530980.0747939292,76.88000000000001,1
+234253.9937022142,3530980.0747939292,77.83,1
+234353.9937022142,3530980.0747939292,81.65,1
+234453.9937022142,3530980.0747939292,84.71,1
+234553.9937022142,3530980.0747939292,79.03999999999999,1
+234653.9937022142,3530980.0747939292,74.18,1
+234753.9937022142,3530980.0747939292,76.0,1
+234853.9937022142,3530980.0747939292,85.37,1
+234953.9937022142,3530980.0747939292,73.00999999999999,1
+235053.9937022142,3530980.0747939292,52.32,1
+235153.9937022142,3530980.0747939292,86.32,1
+235253.9937022142,3530980.0747939292,84.875,1
+234053.9937022142,3530880.0747939292,79.83,1
+234153.9937022142,3530880.0747939292,84.71,1
+234253.9937022142,3530880.0747939292,78.86999999999999,1
+234353.9937022142,3530880.0747939292,79.36999999999999,1
+234453.9937022142,3530880.0747939292,80.62,1
+234553.9937022142,3530880.0747939292,81.55,1
+234653.9937022142,3530880.0747939292,73.83,1
+234753.9937022142,3530880.0747939292,78.67,1
+234853.9937022142,3530880.0747939292,71.81,1
+234953.9937022142,3530880.0747939292,75.89,1
+235053.9937022142,3530880.0747939292,59.660000000000004,1
+235153.9937022142,3530880.0747939292,80.33,1
+235253.9937022142,3530880.0747939292,82.5,1
+234053.9937022142,3530780.0747939292,80.27,1
+234153.9937022142,3530780.0747939292,81.04,1
+234253.9937022142,3530780.0747939292,78.48,1
+234353.9937022142,3530780.0747939292,84.17999999999999,1
+234453.9937022142,3530780.0747939292,91.45,1
+234553.9937022142,3530780.0747939292,81.96,1
+234653.9937022142,3530780.0747939292,74.38,1
+234753.9937022142,3530780.0747939292,74.42999999999999,1
+234853.9937022142,3530780.0747939292,68.12,1
+234953.9937022142,3530780.0747939292,73.22999999999999,1
+235053.9937022142,3530780.0747939292,56.28999999999999,1
+235153.9937022142,3530780.0747939292,75.52,1
+235253.9937022142,3530780.0747939292,74.55000000000001,1
+234053.9937022142,3530680.0747939292,78.72,1
+234153.9937022142,3530680.0747939292,77.56,1
+234253.9937022142,3530680.0747939292,73.77,1
+234353.9937022142,3530680.0747939292,77.64999999999999,1
+234453.9937022142,3530680.0747939292,86.4,1
+234553.9937022142,3530680.0747939292,80.36,1
+234653.9937022142,3530680.0747939292,70.63000000000001,1
+234753.9937022142,3530680.0747939292,77.24,1
+234853.9937022142,3530680.0747939292,61.29,1
+234953.9937022142,3530680.0747939292,54.230000000000004,1
+235053.9937022142,3530680.0747939292,50.22,1
+235153.9937022142,3530680.0747939292,71.95,1
+235253.9937022142,3530680.0747939292,76.75,1
+234053.9937022142,3530580.0747939292,78.06,1
+234153.9937022142,3530580.0747939292,83.17,1
+234253.9937022142,3530580.0747939292,83.14,1
+234353.9937022142,3530580.0747939292,84.32,1
+234453.9937022142,3530580.0747939292,62.23,1
+234553.9937022142,3530580.0747939292,84.72,1
+234653.9937022142,3530580.0747939292,86.11999999999999,1
+234753.9937022142,3530580.0747939292,81.85,1
+234853.9937022142,3530580.0747939292,70.58,1
+234953.9937022142,3530580.0747939292,50.63999999999999,1
+235053.9937022142,3530580.0747939292,63.17,1
+235153.9937022142,3530580.0747939292,76.55,1
+235253.9937022142,3530580.0747939292,74.225,1
+234053.9937022142,3530480.0747939292,78.14,1
+234153.9937022142,3530480.0747939292,77.41,1
+234253.9937022142,3530480.0747939292,78.31,1
+234353.9937022142,3530480.0747939292,78.0,1
+234453.9937022142,3530480.0747939292,82.67,1
+234553.9937022142,3530480.0747939292,89.29,1
+234653.9937022142,3530480.0747939292,73.53,1
+234753.9937022142,3530480.0747939292,82.24000000000001,1
+234853.9937022142,3530480.0747939292,81.16,1
+234953.9937022142,3530480.0747939292,73.44000000000001,1
+235053.9937022142,3530480.0747939292,74.52,1
+235153.9937022142,3530480.0747939292,71.52,1
+235253.9937022142,3530480.0747939292,89.85,1
+234053.9937022142,3530380.0747939292,79.36,1
+234153.9937022142,3530380.0747939292,78.77,1
+234253.9937022142,3530380.0747939292,72.13000000000001,1
+234353.9937022142,3530380.0747939292,77.56,1
+234453.9937022142,3530380.0747939292,74.67,1
+234553.9937022142,3530380.0747939292,84.54,1
+234653.9937022142,3530380.0747939292,89.53,1
+234753.9937022142,3530380.0747939292,85.99,1
+234853.9937022142,3530380.0747939292,87.22999999999999,1
+234953.9937022142,3530380.0747939292,85.53,1
+235053.9937022142,3530380.0747939292,75.82,1
+235153.9937022142,3530380.0747939292,66.47999999999999,1
+235253.9937022142,3530380.0747939292,67.55,1
+234053.9937022142,3530280.0747939292,80.64,1
+234153.9937022142,3530280.0747939292,81.23,1
+234253.9937022142,3530280.0747939292,76.6,1
+234353.9937022142,3530280.0747939292,93.39,1
+234453.9937022142,3530280.0747939292,85.55,1
+234553.9937022142,3530280.0747939292,90.69,1
+234653.9937022142,3530280.0747939292,87.16000000000001,1
+234753.9937022142,3530280.0747939292,87.01,1
+234853.9937022142,3530280.0747939292,90.9,1
+234953.9937022142,3530280.0747939292,86.92999999999999,1
+235053.9937022142,3530280.0747939292,67.22,1
+235153.9937022142,3530280.0747939292,63.77,1
+235253.9937022142,3530280.0747939292,78.475,1
+234053.9937022142,3530180.0747939292,76.86111111111111,1
+234153.9937022142,3530180.0747939292,79.76388888888889,1
+234253.9937022142,3530180.0747939292,80.15277777777777,1
+234353.9937022142,3530180.0747939292,91.45833333333333,1
+234453.9937022142,3530180.0747939292,82.05555555555556,1
+234553.9937022142,3530180.0747939292,94.15277777777777,1
+234653.9937022142,3530180.0747939292,82.72222222222221,1
+234753.9937022142,3530180.0747939292,89.11111111111111,1
+234853.9937022142,3530180.0747939292,91.41666666666667,1
+234953.9937022142,3530180.0747939292,87.58333333333333,1
+235053.9937022142,3530180.0747939292,64.54166666666666,1
+235153.9937022142,3530180.0747939292,56.40277777777778,1
+235253.9937022142,3530180.0747939292,64.86111111111111,1
diff --git a/rscder/ECD.py b/rscder/ECD.py
index 8be20dc..6d3b545 100644
--- a/rscder/ECD.py
+++ b/rscder/ECD.py
@@ -1,19 +1,26 @@
import os
import sys
+# sys.path.insert(0, os.path.dirname(__file__))
# 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.join( os.path.dirname(__file__), '..')
BASE_DIR = os.path.join( os.path.dirname(__file__), '..')
+# import ctypes
-from .mul.mulstart import MulStart
+# ctypes.windll.LoadLibrary()
+
+from rscder.mul.mulstart import MulStart
import logging
from plugins.misc import format_now
+os.makedirs(os.path.join(BASE_DIR, 'logs'), exist_ok=True)
+
logging.basicConfig(level=logging.INFO, filename=os.path.join(BASE_DIR, 'logs', format_now() + '_log.txt'), filemode='a', format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
def main():
+ # print(sys.path)
t = MulStart()
t.run()
diff --git a/rscder/gui/actions.py b/rscder/gui/actions.py
index 66ced04..b21eaaf 100644
--- a/rscder/gui/actions.py
+++ b/rscder/gui/actions.py
@@ -13,6 +13,8 @@ from rscder.gui.plugins import PluginDialog
from rscder.utils.setting import Settings
from rscder.gui.load import loader
from functools import partial
+from rscder.gui.guicfg import GUICfg
+from rscder.gui.location import Location
def get_action_manager() -> 'ActionManager':
return ActionManager()
@@ -66,7 +68,7 @@ class ActionManager(QtCore.QObject):
self.road_menu = self.special_chagne_detec_menu.addMenu(IconInstance().ROAD_CHANGE,'&道路变化检测')
self.landslide_menu = self.special_chagne_detec_menu.addMenu(IconInstance().LANDSIDE,'&滑坡变化检测')
- self.seg_chagne_detec_menu = menubar.addMenu('&分类后变化检测')
+ # self.seg_chagne_detec_menu = menubar.addMenu('&分类后变化检测')
self.postop_menu = menubar.addMenu( '&检测后处理')
# self.noise_menu = self.postop_menu.addMenu(IconInstance().NOISE,'&噪声处理')
@@ -165,6 +167,7 @@ class ActionManager(QtCore.QObject):
pan = self.add_action(QAction(IconInstance().PAN,'&漫游', self.w_parent), 'Basic')
locate = self.add_action(QAction(IconInstance().ZOOM_TO,'&定位', self.w_parent), 'Basic')
+ locate.triggered.connect(self.locate)
pan.setCheckable(True)
pan.setChecked(True)
zomm_out.setCheckable(True)
@@ -253,6 +256,12 @@ class ActionManager(QtCore.QObject):
self.message_box.info('工程初始化完成')
+
+ def locate(self):
+ loc = Location(self.w_parent)
+ loc.show()
+ loc.extent.connect(self.double_map.zoom_to_extent)
+
def project_open(self):
if Project().is_init:
Project().save()
@@ -278,7 +287,9 @@ class ActionManager(QtCore.QObject):
self.message_box.info('Data loaded')
def view_setting(self):
- pass
+ g = GUICfg(self.w_parent)
+ g.show()
+
def add_action(self, action, group=None):
diff --git a/rscder/gui/guicfg.py b/rscder/gui/guicfg.py
new file mode 100644
index 0000000..8c949df
--- /dev/null
+++ b/rscder/gui/guicfg.py
@@ -0,0 +1,39 @@
+from PyQt5.QtWidgets import QDialog, QFormLayout, QLineEdit, QCheckBox, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit, QFileDialog, QMessageBox
+from PyQt5 import QtCore, QtGui
+from PyQt5.QtGui import QIcon
+from rscder.utils.icons import IconInstance
+from rscder.utils.setting import Settings
+
+class GUICfg(QDialog):
+
+ def __init__(self, parent = None, flags = QtCore.Qt.WindowFlags() ) -> None:
+ super().__init__(parent, flags)
+
+ self.setWindowTitle("界面定制")
+ self.setWindowIcon(IconInstance(parent).LOGO)
+
+ form_layout = QFormLayout(self)
+ default_size_label = QLabel('默认格网')
+ default_size = QLineEdit()
+ default_size.setValidator(QtGui.QIntValidator(1, 1000))
+
+ def set_defaultsize():
+ Settings.General().size = (int(default_size.text()), int(default_size.text()))
+ # form_layout.addRow
+ default_size.textChanged.connect( set_defaultsize )
+
+
+ form_layout.addRow(default_size_label, default_size)
+
+ self.setLayout(form_layout)
+
+ auto_save_label = QLabel('自动保存')
+ auto_save = QCheckBox()
+ auto_save.setChecked(Settings.General().auto_save)
+
+ def set_autosave():
+ Settings.General().auto_save = auto_save.isChecked()
+
+ auto_save.stateChanged.connect(set_autosave)
+
+ form_layout.addRow(auto_save_label, auto_save)
diff --git a/rscder/gui/location.py b/rscder/gui/location.py
new file mode 100644
index 0000000..1b02a45
--- /dev/null
+++ b/rscder/gui/location.py
@@ -0,0 +1,67 @@
+from PyQt5.QtWidgets import QDialog, QFormLayout, QLineEdit, QCheckBox, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit, QFileDialog, QMessageBox
+from PyQt5 import QtCore, QtGui
+from PyQt5.QtGui import QIcon
+from rscder.utils.icons import IconInstance
+from rscder.utils.setting import Settings
+from rscder.utils.project import Project
+from qgis.core import QgsRectangle
+
+class Location(QDialog):
+
+ extent = QtCore.pyqtSignal(object)
+
+ def __init__(self, parent = None, flags = QtCore.Qt.WindowFlags() ) -> None:
+ super().__init__(parent, flags)
+
+ self.setWindowTitle("定位")
+ self.setWindowIcon(IconInstance(parent).LOGO)
+
+ X_label = QLabel('X:')
+ Y_label = QLabel('Y:')
+ X = QLineEdit()
+ X.setValidator(QtGui.QDoubleValidator())
+ Y = QLineEdit()
+ Y.setValidator(QtGui.QDoubleValidator())
+
+ hlay = QHBoxLayout()
+ hlay.addWidget(X_label)
+ hlay.addWidget(X)
+ hlay.addWidget(Y_label)
+ hlay.addWidget(Y)
+
+ btns = QPushButton('确定')
+ hlay.addWidget(btns)
+ self.setLayout(hlay)
+
+ def loc():
+ x = float(X.text())
+ y = float(Y.text())
+ extent = QgsRectangle(x - 100, y - 100, x + 100, y + 100 )
+ self.extent.emit(extent)
+
+ btns.clicked.connect(loc)
+ # form_layout = QFormLayout(self)
+ # default_size_label = QLabel('默认格网')
+ # default_size = QLineEdit()
+ # default_size.setValidator(QtGui.QIntValidator(1, 1000))
+
+ # def set_defaultsize():
+ # Settings.General().size = (int(default_size.text()), int(default_size.text()))
+ # # form_layout.addRow
+ # default_size.textChanged.connect( set_defaultsize )
+
+
+ # form_layout.addRow(default_size_label, default_size)
+
+ # self.setLayout(form_layout)
+
+ # auto_save_label = QLabel('自动保存')
+ # auto_save = QCheckBox()
+ # auto_save.setChecked(Settings.General().auto_save)
+
+ # def set_autosave():
+ # Settings.General().auto_save = auto_save.isChecked()
+
+ # auto_save.stateChanged.connect(set_autosave)
+
+ # form_layout.addRow(auto_save_label, auto_save)
diff --git a/rscder/mul/mulstart.py b/rscder/mul/mulstart.py
index 73623fc..6d1b043 100644
--- a/rscder/mul/mulstart.py
+++ b/rscder/mul/mulstart.py
@@ -9,7 +9,8 @@ from rscder.gui.mainwindow import MainWindow
import multiprocessing
from rscder.gui import license
from rscder.utils.setting import Settings
-
+import os
+BASE_DIR = os.environ['ECD_BASEDIR']
class MulStart:
def __init__(self, **kargs) -> None:
@@ -38,7 +39,7 @@ class MulStart:
else:
sys.exit(0)
# Create and display the splash screen
- splash_pix = QPixmap("./icons/splash.png")
+ splash_pix = QPixmap(os.path.join(BASE_DIR, "./icons/splash.png"))
# splash_pix.scaledToWidth(800)
# splash_pix.scaledToHeight(600)
diff --git a/rscder/utils/icons.py b/rscder/utils/icons.py
index 6b380e0..83cd4a8 100644
--- a/rscder/utils/icons.py
+++ b/rscder/utils/icons.py
@@ -54,8 +54,8 @@ class IconInstance(QObject):
self.DATA_LOAD = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/数据加载.png'))
self.EXCIT = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/退出.png'))
- self.ZOOM_IN = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/放大.png'))
- self.ZOOM_OUT = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/缩小.png'))
+ self.ZOOM_OUT = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/放大.png'))
+ self.ZOOM_IN = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/缩小.png'))
self.TABLE = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/table.png'))
diff --git a/setup.py b/setup.py
index dab23c7..3125988 100644
--- a/setup.py
+++ b/setup.py
@@ -1,18 +1,25 @@
from setuptools import setup, find_packages
+# from __future__ import print_function
+
setup(
name='rscder',
version='1.0',
author='Wang Tong',
author_email='copper.w@foxmail.com',
description='RSCDER',
- long_description=open('ReadMe.md', 'r'),
packages=find_packages(),
ext_package=[],
+ include_package_data=True,
+ # package_data={"opencv": ['opencv_ffmpeg3415_64.dll', 'opencv_world3415.dll']},
+ # data_files=[
+ # ('lib/site-packages', ['opencv_ffmpeg3415_64.dll', 'opencv_world3415.dll'])
+ # ],
entry_points=dict(
- console_scripts=[
+ gui_scripts=[
'rscder = rscder.ECD:main',
'keygen = rscder.keygen:main'
]
)
-)
\ No newline at end of file
+)
+
diff --git a/test.py b/test.py
new file mode 100644
index 0000000..882eafd
--- /dev/null
+++ b/test.py
@@ -0,0 +1,36 @@
+import numpy as np
+
+style = [
+ [0, 255, 0, 0],
+ [1, 0, 255, 0]
+]
+def get_color(v):
+ first_color = []
+ second_color = []
+ first_value = -1
+ second_value = -1
+ for s in style:
+ if s[0] <= v:
+ first_value = s[0]
+ first_color = s[1:]
+ else:
+ second_value = s[0]
+ second_color = s[1:]
+ break
+
+ if second_value == -1:
+ return np.array(style[-1][1:])
+
+ first_dis = (v - first_value) / (second_value - first_value)
+ second_dis = (second_value - v) / (second_value - first_value)
+ first_color = np.array(first_color)
+ second_color = np.array(second_color)
+ color = first_color* first_dis + second_color * second_dis
+ return color
+
+
+get_color = np.frompyfunc(get_color, nin=1, nout=1)
+
+value = np.array([0, 0.5, 0.7, 1])
+
+print( np.stack(get_color(value)).reshape((2, 2, 3)))
\ No newline at end of file
diff --git a/使用手册.txt b/使用手册.txt
deleted file mode 100644
index b390c31..0000000
--- a/使用手册.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-1. lic文件生成
-点击ECD.exe,复制所显示的mac地址
-点击keygen.exe,粘贴mac地址,设置截止日期,并选择保存路径(无需输入后缀名)
-点击Generate
-
-2. lic文件导入
-点击ECD.exe,点击Open,选择生成的lic文件
-点击OK
-
-3. 新建工程与数据导入
-点击ECD.exe
-点击新建工程
-选择路径、名称
-将会在路径下看到与名称相同的文件夹
-
-点击载入数据
-选择两幅不同时相的影像
-
-4. 差分法检测
-
-点击基本变化检测
-点击差分法
-选择图层
-点击确定
\ No newline at end of file
diff --git a/安装方法.md b/安装方法.md
new file mode 100644
index 0000000..1b6df9c
--- /dev/null
+++ b/安装方法.md
@@ -0,0 +1,42 @@
+# 变化检测
+
+王铜
+CVEO团队
+
+# 安装
+
+1. 安装miniconda3/anaconda3
+ miniconda3安装包位于install\Miniconda3-py38_23.1.0-1-Windows-x86_64.exe
+2. 打开cmd,激活conda
+3. 安装依赖
+ 将install/opencvxxxx.dll复制到 `C:\Windows\System32`中
+4. 切换目录,安装环境
+ 解压cveo_ss.tar.gz至 `cveo_ss`
+
+```shell
+cd
+.\Scripts\activate.bat
+.\Scripts\conda-unpack.exe
+cd
+python setup.py develop
+
+# 启动keygen生成证书
+keygen
+# 启动rscder
+rscder
+```
+
+4. 插件开发
+
+# 功能
+
+1. 证书检查与生成
+ 1. 基于MAC地址与过期时间进行证书生成,启动时检查证书,过期则退出
+2. 工程管理
+ 1. 以工程为单位进行数据管理与生产
+ 2. 提供工程保存与导入功能
+ 3. 提供多种格式的栅格数据导入(TIF、PNG、BMP、JPG)等
+ 4. 提供矢量数据导入
+3. 基本工具
+ 1. 双视图同步浏览
+ 2. 格网展示