This commit is contained in:
copper 2022-05-11 22:17:55 +08:00
parent b7c35f59e8
commit 0843a369be
11 changed files with 97 additions and 9149 deletions

3
.gitignore vendored
View File

@ -211,5 +211,8 @@ rc.py
model/ model/
plugins/*.c
plugin-build/ plugin-build/
3rd/ 3rd/
default/
plugins/*/*.c

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,17 @@
import math import math
import os import os
import pdb
from rscder.plugins.basic import BasicPlugin from rscder.plugins.basic import BasicPlugin
from PyQt5.QtWidgets import QAction from PyQt5.QtWidgets import QAction
from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSignal
from rscder.utils.project import PairLayer from rscder.utils.project import PairLayer, ResultLayer
from osgeo import gdal, gdal_array from osgeo import gdal, gdal_array
from threading import Thread from threading import Thread
import numpy as np import numpy as np
class BasicMethod(BasicPlugin): class BasicMethod(BasicPlugin):
message_send = pyqtSignal(str) message_send = pyqtSignal(str)
table_result_ok = pyqtSignal(str)
@staticmethod @staticmethod
def info(): def info():
@ -21,15 +23,17 @@ class BasicMethod(BasicPlugin):
} }
def set_action(self): def set_action(self):
basic_change_detection_menu = self.ctx['basic_change_detection_menu'] basic_change_detection_menu = self.ctx['change_detection_menu']
basic_diff_method = QAction('差分法') basic_diff_method = QAction('差分法')
basic_change_detection_menu.addAction(basic_diff_method) basic_change_detection_menu.addAction(basic_diff_method)
basic_diff_method.setEnabled(False) basic_diff_method.setEnabled(False)
self.basic_diff_method = basic_diff_method self.basic_diff_method = basic_diff_method
basic_diff_method.triggered.connect(self.basic_diff_alg)
self.message_send.connect(self.send_message) self.message_send.connect(self.send_message)
self.table_result_ok.connect(self.on_table_result_ok)
self.gap = 128 self.gap = 128
@ -39,6 +43,23 @@ class BasicMethod(BasicPlugin):
def send_message(self, s): def send_message(self, s):
self.message_box.info(s) self.message_box.info(s)
def on_table_result_ok(self, s):
with open(s, 'r') as f:
lines = f.readlines()
data_lines = lines[1:]
if len(data_lines) > 0:
data_table = []
for l in data_lines:
l = l.strip()
ls = l.split(',')
ls = [float(i) for i in ls]
data_table.append(ls)
result = ResultLayer(ResultLayer.POINT)
result.data = data_table
self.result_table.set_data(result)
def run_basic_diff_alg(self, pth1, pth2, cell_size, out): def run_basic_diff_alg(self, pth1, pth2, cell_size, out):
self.message_send.emit('开始计算差分法') self.message_send.emit('开始计算差分法')
@ -70,10 +91,10 @@ class BasicMethod(BasicPlugin):
if band == 1: if band == 1:
block_data1 = block_data1[None, ...] block_data1 = block_data1[None, ...]
block_data2 = block_data2[None, ...] block_data2 = block_data2[None, ...]
# pdb.set_trace()
block_diff = block_data1 - block_data2 block_diff = block_data1 - block_data2
block_diff = block_diff.astype(np.float32) block_diff = block_diff.astype(np.float32)
block_diff = block_diff.abs().sum(0) block_diff = np.abs(block_diff).sum(0)
min_diff = min(min_diff, block_diff.min()) min_diff = min(min_diff, block_diff.min())
max_diff = max(max_diff, block_diff.max()) max_diff = max(max_diff, block_diff.max())
@ -82,7 +103,7 @@ class BasicMethod(BasicPlugin):
self.message_send.emit(f'完成{j}/{yblocks}') self.message_send.emit(f'完成{j}/{yblocks}')
out_ds.FlushCache() out_ds.FlushCache()
out_ds = None del out_ds
self.message_send.emit('归一化概率中...') self.message_send.emit('归一化概率中...')
temp_in_ds = gdal.Open(out_tif) temp_in_ds = gdal.Open(out_tif)
@ -100,12 +121,15 @@ class BasicMethod(BasicPlugin):
out_normal_ds.GetRasterBand(1).WriteArray(block_data, *block_xy) out_normal_ds.GetRasterBand(1).WriteArray(block_data, *block_xy)
out_normal_ds.FlushCache() out_normal_ds.FlushCache()
out_normal_ds = None del out_normal_ds
self.message_send.emit('完成归一化概率') self.message_send.emit('完成归一化概率')
self.message_send.emit('计算变化表格中...') self.message_send.emit('计算变化表格中...')
out_csv = os.path.join(out, 'diff_table.csv') out_csv = os.path.join(out, 'diff_table.csv')
xblocks = xsize // cell_size[0] xblocks = xsize // cell_size[0]
normal_in_ds = gdal.Open(out_normal_tif)
with open(out_csv, 'w') as f: with open(out_csv, 'w') as f:
f.write('x,y,diff,status\n') f.write('x,y,diff,status\n')
for j in range(yblocks): for j in range(yblocks):
@ -113,7 +137,7 @@ class BasicMethod(BasicPlugin):
block_size = (xsize, cell_size[1]) block_size = (xsize, cell_size[1])
if block_xy[1] + block_size[1] > ysize: if block_xy[1] + block_size[1] > ysize:
block_size = (xsize, ysize - block_xy[1]) block_size = (xsize, ysize - block_xy[1])
block_data = temp_in_ds.ReadAsArray(*block_xy, *block_size) block_data = normal_in_ds.ReadAsArray(*block_xy, *block_size)
for i in range(xblocks): for i in range(xblocks):
start_x = i * cell_size[0] start_x = i * cell_size[0]
end_x = start_x + cell_size[0] end_x = start_x + cell_size[0]
@ -127,21 +151,26 @@ class BasicMethod(BasicPlugin):
center_y = center_y * geo[5] + geo [3] center_y = center_y * geo[5] + geo [3]
f.write(f'{center_x},{center_y},{block_data_xy.mean()},1\n') f.write(f'{center_x},{center_y},{block_data_xy.mean()},1\n')
self.table_result_ok.emit(out_csv)
self.message_send.emit('完成计算变化表格') self.message_send.emit('完成计算变化表格')
self.message_send.emit('差分法计算完成') self.message_send.emit('差分法计算完成')
def basic_diff_alg(self): def basic_diff_alg(self):
# layer_select = # layer_select =
layer:PairLayer = self.project.layers.values()[0] layer:PairLayer = list(self.project.layers.values())[0]
img1 = layer.pth2 img1 = layer.pth1
img2 = layer.pth2 img2 = layer.pth2
if not layer.check(): if not layer.check():
return return
out_dir =os.path.join(self.project.root, 'basic_diff_result')
if not os.path.exists(out_dir):
os.makedirs(out_dir, exist_ok=True)
t = Thread(target=self.run_basic_diff_alg, args=(img1, img2, layer.pth1)) t = Thread(target=self.run_basic_diff_alg, args=(img1, img2, layer.cell_size, out_dir))
t.start() t.start()

14
plugins/plugins.yaml Normal file
View File

@ -0,0 +1,14 @@
- author: RSCDER
description: "\u5173\u4E8E"
enabled: true
module: about
name: "\u5173\u4E8E"
path: ./plugin-build\about
version: 1.0.0
- author: RSCDER
description: BasicMethod
enabled: true
module: basic_change
name: BasicMethod
path: ./plugin-build\basic_change
version: 1.0.0

View File

@ -1,5 +1,6 @@
import logging import logging
import os import os
from pathlib import Path
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QAction, QActionGroup, QLabel, QFileDialog from PyQt5.QtWidgets import QAction, QActionGroup, QLabel, QFileDialog
from rscder.gui.project import Create from rscder.gui.project import Create
@ -187,7 +188,7 @@ class ActionManager(QtCore.QObject):
if project.is_init: if project.is_init:
project.save() project.save()
project.clear() project.clear()
project.setup(os.path.join(projec_create.file, projec_create.name + '.prj')) project.setup(projec_create.file, projec_create.name + '.prj')
project.is_init = True project.is_init = True
project.cell_size = projec_create.cell_size project.cell_size = projec_create.cell_size
project.max_memory = projec_create.max_memory project.max_memory = projec_create.max_memory
@ -208,10 +209,13 @@ class ActionManager(QtCore.QObject):
if Project().is_init: if Project().is_init:
Project().save() Project().save()
project_file = QFileDialog.getOpenFileName(self.w_parent, '打开工程', '.', '*.prj') project_file = QFileDialog.getOpenFileName(self.w_parent, '打开工程', Settings.General().last_path, '*.prj')
if project_file[0] != '': if project_file[0] != '':
Project().clear() Project().clear()
Project().setup(project_file[0]) parent = str(Path(project_file[0]).parent)
Settings.General().last_path = parent
name = os.path.basename(project_file[0])
Project().setup(parent, name)
def project_save(self): def project_save(self):
if Project().is_init: if Project().is_init:
@ -221,7 +225,7 @@ class ActionManager(QtCore.QObject):
if Project().is_init: if Project().is_init:
Project().save() Project().save()
file_open = QFileDialog.getOpenFileNames(self.w_parent, '打开数据', Project().root, '*.*') file_open = QFileDialog.getOpenFileNames(self.w_parent, '打开数据', Settings.General().last_path, '*.*')
if file_open[0] != '': if file_open[0] != '':
if len(file_open[0]) != 2: if len(file_open[0]) != 2:
self.message_box.warning('请选择两个数据文件') self.message_box.warning('请选择两个数据文件')

View File

@ -38,8 +38,10 @@ class DoubleCanvas(QWidget):
self.mapcanva2.update_coordinates_text.connect(self.corr_changed) self.mapcanva2.update_coordinates_text.connect(self.corr_changed)
def set_map1_extent(): def set_map1_extent():
if self.mapcanva2.is_main:
self.mapcanva1.set_extent(self.mapcanva2.extent()) self.mapcanva1.set_extent(self.mapcanva2.extent())
def set_map2_extent(): def set_map2_extent():
if self.mapcanva1.is_main:
self.mapcanva2.set_extent(self.mapcanva1.extent()) self.mapcanva2.set_extent(self.mapcanva1.extent())
self.mapcanva1.extentsChanged.connect(set_map2_extent) self.mapcanva1.extentsChanged.connect(set_map2_extent)

View File

@ -26,7 +26,7 @@ class PluginDialog(QDialog):
for idx, plugin in enumerate(self.plugins): for idx, plugin in enumerate(self.plugins):
name_item = QTableWidgetItem(plugin['name']) name_item = QTableWidgetItem(plugin['name'])
module_item = QTableWidgetItem(plugin['module']) module_item = QTableWidgetItem(plugin['module'])
enabled_item = QTableWidgetItem() enabled_item = QTableWidgetItem('启用')
enabled_item.setCheckState(Qt.Checked if plugin['enabled'] else Qt.Unchecked) enabled_item.setCheckState(Qt.Checked if plugin['enabled'] else Qt.Unchecked)
self.plugin_table.setItem(idx, 0, name_item) self.plugin_table.setItem(idx, 0, name_item)
@ -93,7 +93,8 @@ class PluginDialog(QDialog):
info = self.plugins.pop(row) info = self.plugins.pop(row)
try: try:
shutil.rmtree(info['path']) shutil.rmtree(info['path'])
except: except Exception as e:
print(e)
pass pass
# for idx in self.plugins # for idx in self.plugins

View File

@ -1,3 +1,4 @@
from pathlib import Path
from PyQt5.QtWidgets import QDialog, QFileDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox from PyQt5.QtWidgets import QDialog, QFileDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox
from PyQt5.QtGui import QIcon, QIntValidator from PyQt5.QtGui import QIcon, QIntValidator
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
@ -10,7 +11,7 @@ class Create(QDialog):
self.setWindowTitle('Create Project') self.setWindowTitle('Create Project')
self.setWindowIcon(QIcon(":/icons/logo.svg")) self.setWindowIcon(QIcon(":/icons/logo.svg"))
self.file = str(Settings.General().root) self.file = str(Path(Settings.General().root)/'default')
self.name = '未命名' self.name = '未命名'
self.max_memory = Settings.Project().max_memory self.max_memory = Settings.Project().max_memory
self.cell_size = Settings.Project().cell_size self.cell_size = Settings.Project().cell_size

View File

@ -15,9 +15,9 @@ class ResultTable(QtWidgets.QWidget):
super(ResultTable, self).__init__(parent) super(ResultTable, self).__init__(parent)
# self.tableview = QTableView(self) # self.tableview = QTableView(self)
self.tablewidget = QTableWidget(self) self.tablewidget = QTableWidget(self)
self.tablewidget.setColumnCount(5) self.tablewidget.setColumnCount(4)
self.tablewidget.setRowCount(0) self.tablewidget.setRowCount(0)
self.tablewidget.setHorizontalHeaderLabels(['序号', 'X', 'Y', '概率', '变化']) self.tablewidget.setHorizontalHeaderLabels(['X', 'Y', '概率', '变化'])
self.tablewidget.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tablewidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.tablewidget.cellDoubleClicked.connect(self.onDoubleClicked) self.tablewidget.cellDoubleClicked.connect(self.onDoubleClicked)
@ -34,27 +34,32 @@ class ResultTable(QtWidgets.QWidget):
pass pass
def onChanged(self, row, col): def onChanged(self, row, col):
if col == 4: if col == 3:
item_idx = row item_idx = row
item_status = self.tablewidget.item(row, col).checkState() == Qt.Checked item_status = self.tablewidget.item(row, col).checkState() == Qt.Checked
if item_status:
self.tablewidget.item(row, col).setBackground(Qt.yellow)
else:
self.tablewidget.item(row, col).setBackground(Qt.green)
self.on_item_changed.emit({'idx':item_idx, 'status':item_status}) self.on_item_changed.emit({'idx':item_idx, 'status':item_status})
def onClicked(self, row, col): def onClicked(self, row, col):
if col == 4: if col == 3:
self.tablewidget.item(row, col).setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) self.tablewidget.item(row, col).setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
def onDoubleClicked(self, row, col): def onDoubleClicked(self, row, col):
x = self.tablewidget.item(row, 1).text() x = self.tablewidget.item(row, 0).text()
y = self.tablewidget.item(row, 2).text() y = self.tablewidget.item(row, 1).text()
self.on_item_click.emit({'x':x, 'y':y}) self.on_item_click.emit({'x':x, 'y':y})
def set_data(self, data:ResultLayer): def set_data(self, data:ResultLayer):
self.tablewidget.setRowCount(len(data.data)) self.tablewidget.setRowCount(len(data.data))
# print(len(data.data))
self.tablewidget.setVerticalHeaderLabels([ str(i+1) for i in range(len(data.data))])
for i, d in enumerate(data.data): for i, d in enumerate(data.data):
self.tablewidget.setItem(i, 0, QTableWidgetItem(str(i+1))) self.tablewidget.setItem(i, 0, QTableWidgetItem(str(d[0]))) # X
self.tablewidget.setItem(i, 1, QTableWidgetItem(str(d[0]))) # X self.tablewidget.setItem(i, 1, QTableWidgetItem(str(d[1]))) # Y
self.tablewidget.setItem(i, 2, QTableWidgetItem(str(d[1]))) # Y self.tablewidget.setItem(i, 2, QTableWidgetItem(str(d[2]))) # 概率
self.tablewidget.setItem(i, 3, QTableWidgetItem(str(d[2]))) # 概率
status_item = QTableWidgetItem('变化') status_item = QTableWidgetItem('变化')
if d[3] == 0: if d[3] == 0:
status_item.setBackground(Qt.green) status_item.setBackground(Qt.green)
@ -62,7 +67,7 @@ class ResultTable(QtWidgets.QWidget):
elif d[3] == 1: elif d[3] == 1:
status_item.setBackground(Qt.yellow) status_item.setBackground(Qt.yellow)
status_item.setCheckState(Qt.Checked) status_item.setCheckState(Qt.Checked)
self.tablewidget.setItem(i, 4, status_item) # 变化 self.tablewidget.setItem(i, 3, status_item) # 变化
self.tablewidget.resizeColumnsToContents() self.tablewidget.resizeColumnsToContents()
self.tablewidget.resizeRowsToContents() self.tablewidget.resizeRowsToContents()
self.tablewidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.tablewidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

View File

@ -52,7 +52,8 @@ class Project(QObject):
self.root = path self.root = path
if name is None: if name is None:
self.file = str(Path(self.root)/'default.prj') self.file = str(Path(self.root)/'default.prj')
else:
self.file = str(Path(self.root)/name)
if not os.path.exists(self.root): if not os.path.exists(self.root):
os.makedirs(self.root, exist_ok=True) os.makedirs(self.root, exist_ok=True)
if not os.path.exists(self.file): if not os.path.exists(self.file):

View File

@ -22,7 +22,7 @@ class Settings(QSettings):
@property @property
def root(self): def root(self):
_r = './3rd' _r = './plugins'
if not os.path.exists(_r): if not os.path.exists(_r):
os.makedirs(_r) os.makedirs(_r)
return _r return _r
@ -93,12 +93,12 @@ class Settings(QSettings):
@property @property
def last_path(self): def last_path(self):
with Settings(Settings.General.PRE) as s: with Settings(Settings.General.PRE) as s:
return s.value('last_path', '') return str(s.value('last_path', ''))
@last_path.setter @last_path.setter
def last_path(self, value): def last_path(self, value):
with Settings(Settings.General.PRE) as s: with Settings(Settings.General.PRE) as s:
s.setValue('last_path', value) s.setValue('last_path', str(value))
@property @property
def end_date(self): def end_date(self):