From 08550bd7469c8004dc8b5733a355ed3f93288c2d Mon Sep 17 00:00:00 2001 From: copper Date: Mon, 17 Apr 2023 13:05:10 +0800 Subject: [PATCH] fixbug;remove bug --- .gitignore | 6 +- ReadMe.md | 52 --- build.bat | 11 - conda.yaml | 23 -- lic_t.lic | 1 - license.lic | 1 - plugins/export_to/main.py | 86 +++- plugins/filter_collection/__init__.py | 5 +- plugins/filter_collection/lee_filter.py | 112 ++++++ plugins/filter_collection/lms_filter.py | 140 +++++++ plugins/filter_collection/lmsnp_filter.py | 128 ++++++ .../unsupervised_method/scripts/__init__.py | 367 +++++++++++++++++- res.qrc | 53 --- result.txt | 118 ++++++ rscder/ECD.py | 9 +- rscder/gui/actions.py | 15 +- rscder/gui/guicfg.py | 39 ++ rscder/gui/location.py | 67 ++++ rscder/mul/mulstart.py | 5 +- rscder/utils/icons.py | 4 +- setup.py | 13 +- test.py | 36 ++ 使用手册.txt | 24 -- 安装方法.md | 42 ++ 24 files changed, 1174 insertions(+), 183 deletions(-) delete mode 100644 ReadMe.md delete mode 100644 build.bat delete mode 100644 conda.yaml delete mode 100644 lic_t.lic delete mode 100644 license.lic create mode 100644 plugins/filter_collection/lee_filter.py create mode 100644 plugins/filter_collection/lms_filter.py create mode 100644 plugins/filter_collection/lmsnp_filter.py delete mode 100644 res.qrc create mode 100644 result.txt create mode 100644 rscder/gui/guicfg.py create mode 100644 rscder/gui/location.py create mode 100644 test.py delete mode 100644 使用手册.txt create mode 100644 安装方法.md 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. 格网展示