fixbug;remove bug
This commit is contained in:
parent
1e32f960db
commit
08550bd746
6
.gitignore
vendored
6
.gitignore
vendored
@ -222,7 +222,11 @@ share
|
|||||||
|
|
||||||
nuitka.help
|
nuitka.help
|
||||||
log.txt
|
log.txt
|
||||||
|
logs/
|
||||||
|
*.7z
|
||||||
|
*.zip*
|
||||||
|
*.tar.gz
|
||||||
|
install/
|
||||||
!plugins/unsupervised_method/scripts/*.pyd
|
!plugins/unsupervised_method/scripts/*.pyd
|
||||||
!plugins/*/scripts/*.pyd
|
!plugins/*/scripts/*.pyd
|
||||||
|
|
||||||
|
52
ReadMe.md
52
ReadMe.md
@ -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. 格网展示
|
|
11
build.bat
11
build.bat
@ -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
|
|
23
conda.yaml
23
conda.yaml
@ -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
|
|
@ -1 +0,0 @@
|
|||||||
IieXktda+1nRK9zLwe87uPPn2VpCwmUrEOPfyenaW/Sek70/CqqbCr7nangL1+pVXSkzDELia7Qq8e+pDMuHCXzxyJOALRj4j3bhFVExwqSTLuXwdev1e26nr7vnECl7H0SCVynr8To7ciwcnmK6HJXre6i+mBdTjACmKseTMlWp480XOt7uHysltORbTA3J
|
|
@ -1 +0,0 @@
|
|||||||
vd4FiYncytyziGH9GNCAA8hGGr1/79Xmphtc5+PHPJDpxvqj1hP7+985QMojYO4M5Qn/aqEAvFgeDN3CA8x1YAK8SdCgSXSBJpRBK8wqPQjBY1ak96QfdPCrTLunr+xuPxK3Gxe772adTTsee2+ot7WePYUsC4y4NcS5+rlP1if87xtYqVeSwx3c64cOmAGP
|
|
@ -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.QtWidgets import QDialog, QHBoxLayout, QFileDialog, QComboBox, QVBoxLayout, QPushButton, QLabel, QLineEdit, QAction
|
||||||
from PyQt5.QtGui import QIcon
|
from PyQt5.QtGui import QIcon
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
from osgeo import gdal, gdal_array
|
||||||
|
import numpy as np
|
||||||
class ExportDialog(QDialog):
|
class ExportDialog(QDialog):
|
||||||
|
|
||||||
TXT='*.txt'
|
TXT='*.txt'
|
||||||
@ -90,8 +92,12 @@ class ExportPlugin(BasicPlugin):
|
|||||||
|
|
||||||
self.export_bin = QAction(IconInstance().DOCUMENT, '导出栅格二值变化检测结果')
|
self.export_bin = QAction(IconInstance().DOCUMENT, '导出栅格二值变化检测结果')
|
||||||
self.export_bin.triggered.connect(self.export_bin_action)
|
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_txt)
|
||||||
ActionManager().export_menu.addAction(self.export_bin)
|
ActionManager().export_menu.addAction(self.export_bin)
|
||||||
|
ActionManager().export_menu.addAction(self.export_rgb)
|
||||||
|
|
||||||
# self.ctx['toolbar'].addAction(self.export_txt)
|
# self.ctx['toolbar'].addAction(self.export_txt)
|
||||||
|
|
||||||
@ -111,4 +117,82 @@ class ExportPlugin(BasicPlugin):
|
|||||||
out = dialog.out_path
|
out = dialog.out_path
|
||||||
if result:
|
if result:
|
||||||
shutil.copy(result.path, out)
|
shutil.copy(result.path, out)
|
||||||
self.message_box.info('导出成功')
|
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
|
@ -5,4 +5,7 @@ FILTER = Register('滤波处理算法')
|
|||||||
from .mean_filter import MeanFilter
|
from .mean_filter import MeanFilter
|
||||||
from filter_collection.main import *
|
from filter_collection.main import *
|
||||||
from .morphology_filter import MorphologyFilter
|
from .morphology_filter import MorphologyFilter
|
||||||
from .bilater_filter import BilaterFilter
|
from .bilater_filter import BilaterFilter
|
||||||
|
from .lee_filter import LeeFilter
|
||||||
|
from .lms_filter import AdaptiveFilter
|
||||||
|
from .lmsnp_filter import AdaptiveNPFilter
|
112
plugins/filter_collection/lee_filter.py
Normal file
112
plugins/filter_collection/lee_filter.py
Normal file
@ -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
|
140
plugins/filter_collection/lms_filter.py
Normal file
140
plugins/filter_collection/lms_filter.py
Normal file
@ -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
|
128
plugins/filter_collection/lmsnp_filter.py
Normal file
128
plugins/filter_collection/lmsnp_filter.py
Normal file
@ -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
|
@ -164,6 +164,132 @@ class BasicCD(AlgFrontend):
|
|||||||
return out_normal_tif
|
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
|
@UNSUPER_CD.register
|
||||||
class LSTS(AlgFrontend):
|
class LSTS(AlgFrontend):
|
||||||
|
|
||||||
@ -444,7 +570,7 @@ class CVAAlg(AlgFrontend):
|
|||||||
return out_normal_tif
|
return out_normal_tif
|
||||||
|
|
||||||
|
|
||||||
@UNSUPER_CD.register
|
# @UNSUPER_CD.register
|
||||||
class ACDAlg(AlgFrontend):
|
class ACDAlg(AlgFrontend):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -524,6 +650,7 @@ class AHTAlg(AlgFrontend):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def run_alg(pth1: str, pth2: str, layer_parent: PairLayer, send_message=None, *args, **kargs):
|
def run_alg(pth1: str, pth2: str, layer_parent: PairLayer, send_message=None, *args, **kargs):
|
||||||
|
|
||||||
|
|
||||||
if send_message is None:
|
if send_message is None:
|
||||||
class Empty:
|
class Empty:
|
||||||
|
|
||||||
@ -559,11 +686,11 @@ class AHTAlg(AlgFrontend):
|
|||||||
send_message.emit('图像一提取完成')
|
send_message.emit('图像一提取完成')
|
||||||
|
|
||||||
# 运算
|
# 运算
|
||||||
send_message.emit('开始AHT计算.....')
|
send_message.emit('开始LHBA计算.....')
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(
|
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(
|
||||||
layer_parent.name, int(np.random.rand() * 100000)))
|
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('录入投影信息.....')
|
send_message.emit('录入投影信息.....')
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
@ -571,11 +698,10 @@ class AHTAlg(AlgFrontend):
|
|||||||
ds.SetGeoTransform(geo)
|
ds.SetGeoTransform(geo)
|
||||||
ds.SetProjection(proj)
|
ds.SetProjection(proj)
|
||||||
del ds
|
del ds
|
||||||
|
|
||||||
return out_normal_tif
|
return out_normal_tif
|
||||||
|
|
||||||
|
|
||||||
@UNSUPER_CD.register
|
# @UNSUPER_CD.register
|
||||||
class OCDAlg(AlgFrontend):
|
class OCDAlg(AlgFrontend):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -766,3 +892,234 @@ class SHAlg(AlgFrontend):
|
|||||||
ds.SetProjection(proj)
|
ds.SetProjection(proj)
|
||||||
del ds
|
del ds
|
||||||
return out_normal_tif
|
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
|
||||||
|
53
res.qrc
53
res.qrc
@ -1,53 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/">
|
|
||||||
<file>icons/AI变化检测.png</file>
|
|
||||||
<file>icons/使用帮助.png</file>
|
|
||||||
<file>icons/公路变化.png</file>
|
|
||||||
<file>icons/其他</file>
|
|
||||||
<file>icons/创建工程.png</file>
|
|
||||||
<file>icons/删除.png</file>
|
|
||||||
<file>icons/办学评估.png</file>
|
|
||||||
<file>icons/单窗口.png</file>
|
|
||||||
<file>icons/去云.png</file>
|
|
||||||
<file>icons/双窗口.png</file>
|
|
||||||
<file>icons/噪声处理.png</file>
|
|
||||||
<file>icons/图像质量.png</file>
|
|
||||||
<file>icons/图像配准.png</file>
|
|
||||||
<file>icons/图层.png</file>
|
|
||||||
<file>icons/定位.png</file>
|
|
||||||
<file>icons/工具.png</file>
|
|
||||||
<file>icons/工具箱.png</file>
|
|
||||||
<file>icons/工程保存.png</file>
|
|
||||||
<file>icons/帮助 (1).png</file>
|
|
||||||
<file>icons/帮助.png</file>
|
|
||||||
<file>icons/平移.png</file>
|
|
||||||
<file>icons/弱监督.png</file>
|
|
||||||
<file>icons/影像.png</file>
|
|
||||||
<file>icons/打开工程.png</file>
|
|
||||||
<file>icons/插件配置 (1).png</file>
|
|
||||||
<file>icons/插件配置-展开.png</file>
|
|
||||||
<file>icons/插件配置-收起.png</file>
|
|
||||||
<file>icons/插件配置.png</file>
|
|
||||||
<file>icons/数据加载.png</file>
|
|
||||||
<file>icons/文件.png</file>
|
|
||||||
<file>icons/文档.png</file>
|
|
||||||
<file>icons/植被变化.bmp</file>
|
|
||||||
<file>icons/水体变化.png</file>
|
|
||||||
<file>icons/海岸变化.png</file>
|
|
||||||
<file>icons/滑坡变化.png</file>
|
|
||||||
<file>icons/滤波.png</file>
|
|
||||||
<file>icons/田地变化.png</file>
|
|
||||||
<file>icons/界面定制.png</file>
|
|
||||||
<file>icons/监督.png</file>
|
|
||||||
<file>icons/矢量.png</file>
|
|
||||||
<file>icons/网格关闭.png</file>
|
|
||||||
<file>icons/网格开.png</file>
|
|
||||||
<file>icons/视图.png</file>
|
|
||||||
<file>icons/退出.png</file>
|
|
||||||
<file>icons/选择要素.png</file>
|
|
||||||
<file>icons/道路变化.png</file>
|
|
||||||
<file>icons/遥感.png</file>
|
|
||||||
<file>icons/铁路变化.png</file>
|
|
||||||
<file>icons/非监督.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
118
result.txt
Normal file
118
result.txt
Normal file
@ -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
|
@ -1,19 +1,26 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
# sys.path.insert(0, os.path.dirname(__file__))
|
||||||
# sys.path.insert(0, os.path.join('..', os.path.dirname(__file__), 'libs'))
|
# 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['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['GDAL_DATA'] = os.path.join(os.path.dirname(__file__), 'share')
|
||||||
os.environ['ECD_BASEDIR'] = os.path.join( os.path.dirname(__file__), '..')
|
os.environ['ECD_BASEDIR'] = os.path.join( os.path.dirname(__file__), '..')
|
||||||
BASE_DIR = 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
|
import logging
|
||||||
from plugins.misc import format_now
|
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')
|
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():
|
def main():
|
||||||
|
# print(sys.path)
|
||||||
t = MulStart()
|
t = MulStart()
|
||||||
t.run()
|
t.run()
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ from rscder.gui.plugins import PluginDialog
|
|||||||
from rscder.utils.setting import Settings
|
from rscder.utils.setting import Settings
|
||||||
from rscder.gui.load import loader
|
from rscder.gui.load import loader
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from rscder.gui.guicfg import GUICfg
|
||||||
|
from rscder.gui.location import Location
|
||||||
def get_action_manager() -> 'ActionManager':
|
def get_action_manager() -> 'ActionManager':
|
||||||
return ActionManager()
|
return ActionManager()
|
||||||
|
|
||||||
@ -66,7 +68,7 @@ class ActionManager(QtCore.QObject):
|
|||||||
self.road_menu = self.special_chagne_detec_menu.addMenu(IconInstance().ROAD_CHANGE,'&道路变化检测')
|
self.road_menu = self.special_chagne_detec_menu.addMenu(IconInstance().ROAD_CHANGE,'&道路变化检测')
|
||||||
self.landslide_menu = self.special_chagne_detec_menu.addMenu(IconInstance().LANDSIDE,'&滑坡变化检测')
|
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.postop_menu = menubar.addMenu( '&检测后处理')
|
||||||
|
|
||||||
# self.noise_menu = self.postop_menu.addMenu(IconInstance().NOISE,'&噪声处理')
|
# 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')
|
pan = self.add_action(QAction(IconInstance().PAN,'&漫游', self.w_parent), 'Basic')
|
||||||
locate = self.add_action(QAction(IconInstance().ZOOM_TO,'&定位', 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.setCheckable(True)
|
||||||
pan.setChecked(True)
|
pan.setChecked(True)
|
||||||
zomm_out.setCheckable(True)
|
zomm_out.setCheckable(True)
|
||||||
@ -253,6 +256,12 @@ class ActionManager(QtCore.QObject):
|
|||||||
|
|
||||||
self.message_box.info('工程初始化完成')
|
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):
|
def project_open(self):
|
||||||
if Project().is_init:
|
if Project().is_init:
|
||||||
Project().save()
|
Project().save()
|
||||||
@ -278,7 +287,9 @@ class ActionManager(QtCore.QObject):
|
|||||||
self.message_box.info('Data loaded')
|
self.message_box.info('Data loaded')
|
||||||
|
|
||||||
def view_setting(self):
|
def view_setting(self):
|
||||||
pass
|
g = GUICfg(self.w_parent)
|
||||||
|
g.show()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_action(self, action, group=None):
|
def add_action(self, action, group=None):
|
||||||
|
39
rscder/gui/guicfg.py
Normal file
39
rscder/gui/guicfg.py
Normal file
@ -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)
|
67
rscder/gui/location.py
Normal file
67
rscder/gui/location.py
Normal file
@ -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)
|
@ -9,7 +9,8 @@ from rscder.gui.mainwindow import MainWindow
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
from rscder.gui import license
|
from rscder.gui import license
|
||||||
from rscder.utils.setting import Settings
|
from rscder.utils.setting import Settings
|
||||||
|
import os
|
||||||
|
BASE_DIR = os.environ['ECD_BASEDIR']
|
||||||
class MulStart:
|
class MulStart:
|
||||||
|
|
||||||
def __init__(self, **kargs) -> None:
|
def __init__(self, **kargs) -> None:
|
||||||
@ -38,7 +39,7 @@ class MulStart:
|
|||||||
else:
|
else:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
# Create and display the splash screen
|
# 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.scaledToWidth(800)
|
||||||
# splash_pix.scaledToHeight(600)
|
# splash_pix.scaledToHeight(600)
|
||||||
|
|
||||||
|
@ -54,8 +54,8 @@ class IconInstance(QObject):
|
|||||||
|
|
||||||
self.DATA_LOAD = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/数据加载.png'))
|
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.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'))
|
self.TABLE = QIcon(os.path.join(os.environ['ECD_BASEDIR'] , './icons/table.png'))
|
||||||
|
|
||||||
|
13
setup.py
13
setup.py
@ -1,18 +1,25 @@
|
|||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
# from __future__ import print_function
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='rscder',
|
name='rscder',
|
||||||
version='1.0',
|
version='1.0',
|
||||||
author='Wang Tong',
|
author='Wang Tong',
|
||||||
author_email='copper.w@foxmail.com',
|
author_email='copper.w@foxmail.com',
|
||||||
description='RSCDER',
|
description='RSCDER',
|
||||||
long_description=open('ReadMe.md', 'r'),
|
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
ext_package=[],
|
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(
|
entry_points=dict(
|
||||||
console_scripts=[
|
gui_scripts=[
|
||||||
'rscder = rscder.ECD:main',
|
'rscder = rscder.ECD:main',
|
||||||
'keygen = rscder.keygen:main'
|
'keygen = rscder.keygen:main'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
36
test.py
Normal file
36
test.py
Normal file
@ -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)))
|
24
使用手册.txt
24
使用手册.txt
@ -1,24 +0,0 @@
|
|||||||
1. lic文件生成
|
|
||||||
点击ECD.exe,复制所显示的mac地址
|
|
||||||
点击keygen.exe,粘贴mac地址,设置截止日期,并选择保存路径(无需输入后缀名)
|
|
||||||
点击Generate
|
|
||||||
|
|
||||||
2. lic文件导入
|
|
||||||
点击ECD.exe,点击Open,选择生成的lic文件
|
|
||||||
点击OK
|
|
||||||
|
|
||||||
3. 新建工程与数据导入
|
|
||||||
点击ECD.exe
|
|
||||||
点击新建工程
|
|
||||||
选择路径、名称
|
|
||||||
将会在路径下看到与名称相同的文件夹
|
|
||||||
|
|
||||||
点击载入数据
|
|
||||||
选择两幅不同时相的影像
|
|
||||||
|
|
||||||
4. 差分法检测
|
|
||||||
|
|
||||||
点击基本变化检测
|
|
||||||
点击差分法
|
|
||||||
选择图层
|
|
||||||
点击确定
|
|
42
安装方法.md
Normal file
42
安装方法.md
Normal file
@ -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 <cveo_ss path>
|
||||||
|
.\Scripts\activate.bat
|
||||||
|
.\Scripts\conda-unpack.exe
|
||||||
|
cd <root-of-this>
|
||||||
|
python setup.py develop
|
||||||
|
|
||||||
|
# 启动keygen生成证书
|
||||||
|
keygen
|
||||||
|
# 启动rscder
|
||||||
|
rscder
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 插件开发
|
||||||
|
|
||||||
|
# 功能
|
||||||
|
|
||||||
|
1. 证书检查与生成
|
||||||
|
1. 基于MAC地址与过期时间进行证书生成,启动时检查证书,过期则退出
|
||||||
|
2. 工程管理
|
||||||
|
1. 以工程为单位进行数据管理与生产
|
||||||
|
2. 提供工程保存与导入功能
|
||||||
|
3. 提供多种格式的栅格数据导入(TIF、PNG、BMP、JPG)等
|
||||||
|
4. 提供矢量数据导入
|
||||||
|
3. 基本工具
|
||||||
|
1. 双视图同步浏览
|
||||||
|
2. 格网展示
|
Loading…
x
Reference in New Issue
Block a user