diff --git a/log.txt b/log.txt index fbd1589..ff46a6d 100644 --- a/log.txt +++ b/log.txt @@ -1,4 +1,4 @@ -2022-05-25 15:29:52,208 - root - INFO - lic data:2022-12-01 00:00:00 -2022-05-25 15:29:52,209 - root - INFO - remain_days: 189 -2022-05-25 15:29:53,515 - root - INFO - lic data:2022-12-01 00:00:00 -2022-05-25 15:29:53,515 - root - INFO - remain_days: 189 +2022-05-27 10:22:57,895 - root - INFO - lic data:2022-12-01 00:00:00 +2022-05-27 10:22:57,896 - root - INFO - remain_days: 187 +2022-05-27 10:22:59,201 - root - INFO - lic data:2022-12-01 00:00:00 +2022-05-27 10:22:59,201 - root - INFO - remain_days: 187 diff --git a/plugins/basic_change/main.py b/plugins/basic_change/main.py index 5fec53c..0848178 100644 --- a/plugins/basic_change/main.py +++ b/plugins/basic_change/main.py @@ -1,11 +1,12 @@ import math import os import pdb +from rscder.gui.actions import ActionManager from rscder.plugins.basic import BasicPlugin from PyQt5.QtWidgets import QAction, QDialog, QHBoxLayout, QVBoxLayout, QPushButton from PyQt5.QtCore import pyqtSignal from PyQt5.QtGui import QIcon -from rscder.utils.project import BasicLayer, Project, RasterLayer +from rscder.utils.project import BasicLayer, Project, RasterLayer, SingleBandRasterLayer from rscder.gui.layercombox import PairLayerCombox from osgeo import gdal from threading import Thread @@ -22,8 +23,7 @@ class MyDialog(QDialog): self.setFixedWidth(500) self.layer_select = PairLayerCombox(self) - self.layer_select.setFixedWidth(400) - + # self.number_input = QLineEdit(self) self.ok_button = QPushButton('确定', self) @@ -57,7 +57,6 @@ class MyDialog(QDialog): class BasicMethod(BasicPlugin): - message_send = pyqtSignal(str) result_ok = pyqtSignal(dict) @staticmethod @@ -70,23 +69,15 @@ class BasicMethod(BasicPlugin): } def set_action(self): - basic_change_detection_menu = self.ctx['change_detection_menu'] basic_diff_method = QAction('差分法') - basic_change_detection_menu.addAction(basic_diff_method) - + ActionManager().unsupervised_menu.addAction(basic_diff_method) basic_diff_method.setEnabled(False) self.basic_diff_method = basic_diff_method basic_diff_method.triggered.connect(self.basic_diff_alg) - self.message_send.connect(self.send_message) - def setup(self): self.basic_diff_method.setEnabled(True) - self.otsu_method.setEnabled(True) - - def send_message(self, s): - self.message_box.info(s) def run_basic_diff_alg(self, layer1:RasterLayer, layer2:RasterLayer): @@ -97,12 +88,12 @@ class BasicMethod(BasicPlugin): cell_size = layer1.layer_parent.cell_size - self.message_send.emit('开始计算差分法') + self.send_message.emit('开始计算差分法') ds1 = gdal.Open(pth1) ds2 = gdal.Open(pth2) if not layer1.compare(layer2): - self.message_send.emit('两个图层的尺寸不同') + self.send_message.emit('两个图层的尺寸不同') return xsize = ds1.RasterXSize ysize = ds1.RasterYSize @@ -140,11 +131,11 @@ class BasicMethod(BasicPlugin): max_diff = max(max_diff, block_diff.max()) out_ds.GetRasterBand(1).WriteArray(block_diff, *block_xy) - self.message_send.emit(f'完成{j}/{yblocks}') + self.send_message.emit(f'完成{j}/{yblocks}') out_ds.FlushCache() del out_ds - self.message_send.emit('归一化概率中...') + self.send_message.emit('归一化概率中...') temp_in_ds = gdal.Open(out_tif) out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer1.layer_parent.name, int(np.random.rand() * 100000))) @@ -172,14 +163,14 @@ class BasicMethod(BasicPlugin): except: pass - raster_result_layer = RasterLayer(None, True, out_normal_tif, BasicLayer.BOATH_VIEW) + raster_result_layer = SingleBandRasterLayer(None, True, out_normal_tif, BasicLayer.BOATH_VIEW) # layer1.layer_parent.add_result_layer(point_result_lalyer) layer1.layer_parent.add_result_layer(raster_result_layer) - # self.message_send.emit('完成计算变化表格') + # self.send_message.emit('完成计算变化表格') - self.message_send.emit('差分法计算完成') + self.send_message.emit('差分法计算完成') def basic_diff_alg(self): # layer_select = diff --git a/plugins/evaluation/main.py b/plugins/evaluation/main.py index 4fddc25..35865f1 100644 --- a/plugins/evaluation/main.py +++ b/plugins/evaluation/main.py @@ -1,7 +1,14 @@ +from threading import Thread + +import numpy as np +from rscder.gui.actions import ActionManager from rscder.plugins.basic import BasicPlugin -from PyQt5.QtWidgets import QAction, QDialog, QHBoxLayout, QVBoxLayout, QPushButton +from rscder.gui.layercombox import RasterLayerCombox +from PyQt5.QtWidgets import QAction, QFileDialog, QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton from PyQt5.QtGui import QIcon from PyQt5.QtCore import Qt +from osgeo import gdal +from rscder.utils.project import SingleBandRasterLayer class EvalutationDialog(QDialog): @@ -11,13 +18,26 @@ class EvalutationDialog(QDialog): self.setWindowTitle('精度评估') self.setWindowIcon(QIcon(":/icons/logo.png")) - self.setFixedWidth(500) + self.layer_select = RasterLayerCombox(self) + self.gt_file = None - self.ok_button = QPushButton('OK', self) + gt_file_select_label = QLabel('真值文件:') + self.gt_file_select = QPushButton('选择...', self) + self.gt_file_select.clicked.connect(self.on_gt_file_select) + + hbox1 = QHBoxLayout() + hbox1.addWidget(gt_file_select_label) + hbox1.addWidget(self.gt_file_select) + + hbox2 = QHBoxLayout() + hbox2.addWidget(QLabel('二值化结果图层:')) + hbox2.addWidget(self.layer_select) + + self.ok_button = QPushButton('确定', self) self.ok_button.setIcon(QIcon(":/icons/ok.svg")) self.ok_button.clicked.connect(self.on_ok) - self.cancel_button = QPushButton('Cancel', self) + self.cancel_button = QPushButton('取消', self) self.cancel_button.setIcon(QIcon(":/icons/cancel.svg")) self.cancel_button.clicked.connect(self.on_cancel) @@ -26,11 +46,98 @@ class EvalutationDialog(QDialog): self.button_layout.addWidget(self.cancel_button) self.main_layout = QVBoxLayout() + self.main_layout.addLayout(hbox1) + self.main_layout.addLayout(hbox2) self.main_layout.addLayout(self.button_layout) self.setLayout(self.main_layout) + def on_gt_file_select(self): + file_name, _ = QFileDialog.getOpenFileName(self, '选择真值文件', '', '*.tif') + if file_name: + self.gt_file = file_name + self.gt_file_select.setText(file_name) + def on_ok(self): self.accept() def on_cancel(self): - self.reject() \ No newline at end of file + self.reject() + + +class EvaluationPlugin(BasicPlugin): + + @staticmethod + def info(): + return { + 'name': '精度评估', + 'author': 'RSC', + 'version': '1.0.0', + 'description': '精度评估', + 'category': 'Evaluation' + } + + def set_action(self): + self.action = QAction(QIcon(":/icons/evaluation.svg"), '精度评估', self.mainwindow) + self.action.triggered.connect(self.show_dialog) + ActionManager().evaluation_menu.addAction(self.action) + + def run_alg(self, layer:SingleBandRasterLayer, gt): + if layer is None or gt is None: + return + self.send_message.emit('正在进行精度评估...') + + pred_ds = gdal.Open(layer.path) + pred_band = pred_ds.GetRasterBand(1) + gt_ds = gdal.Open(gt) + gt_band = gt_ds.GetRasterBand(1) + + if pred_band is None or gt_band is None: + return + + if pred_ds.RasterXSize != gt_ds.RasterXSize or pred_ds.RasterYSize != gt_ds.RasterYSize: + self.send_message.emit('真值与预测结果大小不匹配') + return + + + xsize = pred_ds.RasterXSize + ysize = pred_ds.RasterYSize + + max_pixels = 1e6 + y_block_size = int(max_pixels / xsize) + 1 + block_count = int(ysize / y_block_size) + 1 + + cfm = np.zeros((2,2)) + + for i in range(block_count): + block_size = (xsize, y_block_size) + block_offset = (0, i * y_block_size) + + if i == block_count - 1: + block_size = (xsize, ysize - i * y_block_size) + + pred_block = pred_band.ReadAsArray(*block_offset, *block_size) + gt_block = gt_band.ReadAsArray(*block_offset, *block_size) + pred_block = pred_block.astype(np.uint8) + gt_block = gt_block.astype(np.uint8) + valid_mask = ((pred_block == 1) | (pred_block == 0)) & ((gt_block == 1) | (gt_block == 0)) + pred_block = pred_block[valid_mask] + gt_block = gt_block[valid_mask] + + for k in range(2): + for l in range(2): + cfm[k,l] += np.sum((pred_block == k) & (gt_block == l)) + + + self.send_message.emit('精度评估完成') + + def show_dialog(self): + dialog = EvalutationDialog(self.mainwindow) + dialog.exec_() + if dialog.result() == QDialog.Accepted: + layer = dialog.layer_select.current_layer() + if not isinstance(layer, SingleBandRasterLayer): + self.send_message.emit('请选择一个单波段栅格图层') + return + t = Thread(target=self.run_alg, args=(layer, dialog.gt_file)) + t.start() + \ No newline at end of file diff --git a/plugins/export_to/main.py b/plugins/export_to/main.py index b3fbe5d..08514e6 100644 --- a/plugins/export_to/main.py +++ b/plugins/export_to/main.py @@ -1,4 +1,5 @@ import shutil +from rscder.gui.actions import ActionManager from rscder.utils.project import Project, PairLayer, ResultPointLayer from rscder.plugins.basic import BasicPlugin from PyQt5.QtWidgets import QDialog, QHBoxLayout, QFileDialog, QComboBox, QVBoxLayout, QPushButton, QLabel, QLineEdit, QAction @@ -27,7 +28,6 @@ class ExportDialog(QDialog): for i in range(result_layer_select.count() - 1): result_layer_select.setItemIcon(i + 1, QIcon(":/icons/layer.png")) - def on_result_layer_select(index): self.result_layer = result_layer_select.currentData() @@ -86,9 +86,9 @@ class ExportPlugin(BasicPlugin): self.export_txt = QAction(QIcon(":/icons/document.png"), '导出为 Arcgis 兼容的TXT', self.mainwindow) self.export_txt.triggered.connect(self.export_txt_action) - self.ctx['postop_menu'].addAction(self.export_txt) + ActionManager().export_menu.addAction(self.export_txt) - self.ctx['toolbar'].addAction(self.export_txt) + # self.ctx['toolbar'].addAction(self.export_txt) def export_txt_action(self): dialog = ExportDialog(self.mainwindow) diff --git a/plugins/plugins.yaml b/plugins/plugins.yaml index 82173f5..0059eb2 100644 --- a/plugins/plugins.yaml +++ b/plugins/plugins.yaml @@ -25,4 +25,18 @@ module: some_filter name: MeanFilter path: ./plugin\some_filter + version: 1.0.0 +- author: RSCDER + description: OTSU + enabled: true + module: threshold + name: OTSU + path: ./plugin\threshold + version: 1.0.0 +- author: RSCDER + description: TableResult + enabled: true + module: table_result + name: TableResult + path: ./plugin\table_result version: 1.0.0 \ No newline at end of file diff --git a/plugins/some_filter/main.py b/plugins/some_filter/main.py index d806dd4..362c916 100644 --- a/plugins/some_filter/main.py +++ b/plugins/some_filter/main.py @@ -3,6 +3,7 @@ from threading import Thread from PyQt5.QtWidgets import QDialog, QAction from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal +from rscder.gui.actions import ActionManager from rscder.utils.project import PairLayer, Project, RasterLayer, ResultPointLayer from rscder.plugins.basic import BasicPlugin from rscder.gui.layercombox import RasterLayerCombox @@ -87,7 +88,7 @@ class MainPlugin(BasicPlugin): # self.action.setCheckable) # self.action.setChecked(False) self.action.triggered.connect(self.run) - self.ctx['basic_menu'].addAction(self.action) + ActionManager().filter_menu.addAction(self.action) self.alg_ok.connect(self.alg_oked) # basic diff --git a/plugins/table_result/__init__.py b/plugins/table_result/__init__.py index e69de29..4ac01df 100644 --- a/plugins/table_result/__init__.py +++ b/plugins/table_result/__init__.py @@ -0,0 +1 @@ +from table_result.main import * \ No newline at end of file diff --git a/plugins/table_result/main.py b/plugins/table_result/main.py index 612c4a9..7ce2c07 100644 --- a/plugins/table_result/main.py +++ b/plugins/table_result/main.py @@ -1 +1,111 @@ -from table_result.main import * +import os +from threading import Thread +from rscder.gui.actions import ActionManager +from rscder.gui.layercombox import RasterLayerCombox, ResultPointLayerCombox +from rscder.plugins.basic import BasicPlugin +from PyQt5.QtWidgets import QAction, QDialog, QLabel, QHBoxLayout, QVBoxLayout, QPushButton +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtGui import QIcon + +from rscder.utils.project import Project, ResultPointLayer, SingleBandRasterLayer +from osgeo import gdal +class TableResultDialog(QDialog): + + def __init__(self, parent=None): + super().__init__(parent) + + self.setWindowTitle('表格结果') + self.setWindowIcon(QIcon(":/icons/logo.png")) + + self.layer_select = RasterLayerCombox(self) + hbox = QHBoxLayout() + hbox.addWidget(QLabel('二值化结果图层:')) + hbox.addWidget(self.layer_select) + + self.ok_button = QPushButton('确定', self) + self.ok_button.setIcon(QIcon(":/icons/ok.svg")) + self.ok_button.clicked.connect(self.on_ok) + + self.cancel_button = QPushButton('取消', self) + self.cancel_button.setIcon(QIcon(":/icons/cancel.svg")) + self.cancel_button.clicked.connect(self.on_cancel) + + self.button_layout = QHBoxLayout() + self.button_layout.addWidget(self.ok_button) + self.button_layout.addWidget(self.cancel_button) + + self.main_layout = QVBoxLayout() + self.main_layout.addLayout(hbox) + self.main_layout.addLayout(self.button_layout) + self.setLayout(self.main_layout) + + def on_ok(self): + self.accept() + + def on_cancel(self): + self.reject() + + +class TableResultPlugin(BasicPlugin): + + @staticmethod + def info(): + return { + 'name': 'TableResult', + 'author': 'RSC', + 'version': '1.0.0', + 'description': '表格结果' + } + + def set_action(self): + self.action = QAction(QIcon(":/icons/table_result.svg"), '表格结果', self.mainwindow) + self.action.triggered.connect(self.show_dialog) + ActionManager().position_menu.addAction(self.action) + + def run(self, layer:SingleBandRasterLayer): + self.send_message.emit('正在计算表格结果...') + if not isinstance(layer, SingleBandRasterLayer): + self.send_message.emit('请选择一个单波段栅格图层') + return + + cell_size = layer.layer_parent.cell_size + ds = gdal.Open(layer.path) + xsize = ds.RasterXSize + ysize = ds.RasterYSize + geo = ds.GetGeoTransform() + + out_csv = os.path.join(Project().other_path, f'{layer.name}_table_result.csv') + yblocks = ysize // cell_size[1] + 1 + xblocks = xsize // cell_size[0] + 1 + with open(out_csv, 'w') as f: + f.write('x,y,diff,status\n') + for j in range(yblocks): + block_xy = (0, j * cell_size[1]) + block_size = (xsize, cell_size[1]) + if block_xy[1] + block_size[1] > ysize: + block_size = (xsize, ysize - block_xy[1]) + block_data = ds.ReadAsArray(*block_xy, *block_size) + for i in range(xblocks): + start_x = i * cell_size[0] + end_x = start_x + cell_size[0] + if end_x > xsize: + end_x = xsize + block_data_xy = block_data[:, start_x:end_x] + if block_data_xy.mean() > 0.5: + center_x = start_x + cell_size[0] // 2 + center_y = j * cell_size[1] + cell_size[1] // 2 + center_x = center_x * geo[1] + geo [0] + center_y = center_y * geo[5] + geo [3] + f.write(f'{center_x},{center_y},{block_data_xy.mean() * 100},1\n') + + result_layer = ResultPointLayer(out_csv, enable=True, proj=layer.proj, geo=layer.geo) + layer.layer_parent.add_result_layer(result_layer) + self.send_message.emit('计算完成') + + + def show_dialog(self): + dialog = TableResultDialog() + if dialog.exec_() == QDialog.Accepted: + if dialog.layer_select.current_layer is not None: + t = Thread(target=self.run, args=(dialog.layer_select.current_layer,)) + t.start() diff --git a/plugins/threshold/main.py b/plugins/threshold/main.py index 847e62b..76e8041 100644 --- a/plugins/threshold/main.py +++ b/plugins/threshold/main.py @@ -1,4 +1,6 @@ import os +import pdb +from threading import Thread import numpy as np from rscder.gui.actions import ActionManager from rscder.plugins.basic import BasicPlugin @@ -6,8 +8,9 @@ from PyQt5.QtWidgets import QAction, QDialog, QHBoxLayout, QVBoxLayout, QPushBut from PyQt5.QtGui import QIcon from PyQt5.QtCore import Qt from rscder.gui.layercombox import RasterLayerCombox -from rscder.utils.project import Project, RasterLayer +from rscder.utils.project import Project, RasterLayer, SingleBandRasterLayer from threshold.otsu import OTSU +from osgeo import gdal class OTSUDialog(QDialog): def __init__(self, parent=None): @@ -65,15 +68,16 @@ class OTSUPlugin(BasicPlugin): def run(self): dialog = OTSUDialog(self.mainwindow) if dialog.exec_() == QDialog.Accepted: - pass + t = Thread(target=self.run_alg, args=(dialog.layercombox.current_layer,)) + t.start() def run_alg(self, layer:RasterLayer): if layer is None or layer.path is None: return - ds = gdal.Open(layer.path) band = ds.GetRasterBand(1) - if band > 1: + band_count = ds.RasterCount + if band_count > 1: self.message_box.error('请选择符合要求的图层') return hist = np.zeros(256, dtype=np.int) @@ -94,7 +98,7 @@ class OTSUPlugin(BasicPlugin): hist += np.histogram(block.flatten(), bins=256, range=(0, 255))[0] hist = hist.astype(np.float32) gap = OTSU(hist) - self.message_box.info('阈值为:{}'.format(gap)) + self.send_message.emit('阈值为:{}'.format(gap)) out_th = os.path.join(Project().bcdm_path, '{}_otsu_bcdm.tif'.format(layer.name)) out_ds = gdal.GetDriverByName('GTiff').Create(out_th, xsize, ysize, 1, gdal.GDT_Byte) @@ -110,9 +114,10 @@ class OTSUPlugin(BasicPlugin): out_band.FlushCache() out_ds = None ds = None - self.message_box.info('OTSU阈值完成') + self.send_message.emit('OTSU阈值完成') - otsu_layer = RasterLayer(path = out_th, style_info={}) + otsu_layer = SingleBandRasterLayer(path = out_th, style_info={}) + layer.layer_parent.add_result_layer(otsu_layer) # otsu_method = QAction('OTSU阈值分割') diff --git a/rscder/gui/actions.py b/rscder/gui/actions.py index 8702a53..20869c1 100644 --- a/rscder/gui/actions.py +++ b/rscder/gui/actions.py @@ -48,11 +48,26 @@ class ActionManager(QtCore.QObject): def set_menus(self, menubar:QMenuBar): self.menubar = menubar self.file_menu = menubar.addMenu( '&文件') - self.basic_menu = menubar.addMenu( '&基本工具') + self.basic_menu = menubar.addMenu( '&基础工具') + self.filter_menu = self.basic_menu.addMenu('&滤波处理') self.change_detection_menu = menubar.addMenu( '&通用变化检测') + self.unsupervised_menu = self.change_detection_menu.addMenu('&无监督变化检测') + self.supervised_menu = self.change_detection_menu.addMenu('&监督变化检测') + self.ai_menu = self.change_detection_menu.addMenu('&AI变化检测') self.special_chagne_detec_menu = menubar.addMenu( '&专题变化检测') + self.water_menu = self.special_chagne_detec_menu.addMenu('&水体变化检测') + self.veg_menu = self.special_chagne_detec_menu.addMenu('&植被变化检测') + self.road_menu = self.special_chagne_detec_menu.addMenu('&道路变化检测') + self.landslide_menu = self.special_chagne_detec_menu.addMenu('&滑坡变化检测') + self.seg_chagne_detec_menu = menubar.addMenu('&分类后变化检测') self.postop_menu = menubar.addMenu( '&检测后处理') + + self.noise_menu = self.postop_menu.addMenu('&噪声处理') + self.position_menu = self.postop_menu.addMenu('&变化位置估计') + self.evaluation_menu = self.postop_menu.addMenu('&定量评价') + self.export_menu = self.postop_menu.addMenu('&结果导出') + self.view_menu = menubar.addMenu('&视图') self.plugin_menu = menubar.addMenu('&插件') self.help_menu = menubar.addMenu( '&帮助') diff --git a/rscder/gui/layercombox.py b/rscder/gui/layercombox.py index 4fcc47a..4e711dd 100644 --- a/rscder/gui/layercombox.py +++ b/rscder/gui/layercombox.py @@ -51,7 +51,20 @@ class PairLayerCombox(QWidget): self.layer_combox.currentIndexChanged.connect(self.on_group_changed) - self.setLayout(hbox) + hbox1 = QHBoxLayout() + hbox1.addWidget(QLabel('时相1:')) + hbox1.addWidget(self.raster_layer1) + + hbox2 = QHBoxLayout() + hbox2.addWidget(QLabel('时相2:')) + hbox2.addWidget(self.raster_layer2) + + vbox = QVBoxLayout() + vbox.addLayout(hbox) + vbox.addLayout(hbox1) + vbox.addLayout(hbox2) + + self.setLayout(vbox) def on_raster_layer1_changed(self, index): if index == 0: @@ -89,12 +102,12 @@ class RasterLayerCombox(QComboBox): self.addItem('---', None) if layer is not None: for sub in layer.layers: - if isinstance(sub, RasterLayer): + if issubclass(sub.__class__, RasterLayer): self.addItem(sub.name, sub) else: for layer in Project().layers.values(): for sub in layer.layers: - if isinstance(sub, RasterLayer): + if issubclass(sub.__class__, RasterLayer): self.addItem(sub.name, sub) # self.addItem(layer.name, layer.id) diff --git a/rscder/gui/load.py b/rscder/gui/load.py index 256f849..c0fe3a7 100644 --- a/rscder/gui/load.py +++ b/rscder/gui/load.py @@ -7,7 +7,7 @@ from PyQt5 import QtGui from rscder.utils.setting import Settings from rscder.gui.mapcanvas import DoubleCanvas from qgis.gui import QgsMapCanvas -from rscder.utils.project import RasterLayer +from rscder.utils.project import MultiBandRasterLayer, RasterLayer class loader(QDialog): def __init__(self, parent=None) -> None: super().__init__(parent) @@ -131,7 +131,7 @@ class loader(QDialog): if path1: self.path1 = path1[0][0] self.path1_input.setText(self.path1) - self.left_layer=RasterLayer(path=self.path1) + self.left_layer=MultiBandRasterLayer(path=self.path1) self.mapcanva1.setLayers([self.left_layer.layer]) self.mapcanva1.zoomToFeatureExtent(self.left_layer.layer.extent()) @@ -140,7 +140,7 @@ class loader(QDialog): if path2: self.path2 = path2[0][0] self.path2_input.setText(self.path2) - self.right_layer=RasterLayer(path=self.path2) + self.right_layer=MultiBandRasterLayer(path=self.path2) self.mapcanva2.setLayers([self.right_layer.layer]) self.mapcanva2.zoomToFeatureExtent(self.right_layer.layer.extent()) def ok(self): diff --git a/rscder/plugins/basic.py b/rscder/plugins/basic.py index e449f68..f1de42b 100644 --- a/rscder/plugins/basic.py +++ b/rscder/plugins/basic.py @@ -3,6 +3,9 @@ from rscder.utils.project import PairLayer class BasicPlugin(QObject): + + send_message = pyqtSignal(str) + ''' 插件基类 ctx: @@ -36,6 +39,7 @@ class BasicPlugin(QObject): self.set_action() # self.project.layer_load.connect(self.on_data_load) self.project.project_init.connect(self.setup) + self.send_message.connect(self.message_box.info) def set_action(self): diff --git a/rscder/utils/project.py b/rscder/utils/project.py index 1b8399b..e43ff63 100644 --- a/rscder/utils/project.py +++ b/rscder/utils/project.py @@ -432,26 +432,25 @@ class RasterLayer(BasicLayer): del ds return s def apply_style(self): - renderer=QgsMultiBandColorRenderer(self.layer.dataProvider(),self.style_info['r'],self.style_info['g'],self.style_info['b']) - self.layer.setRenderer(renderer) - self.layer.triggerRepaint() + pass + def set_stlye(self,style_info): self.style_info=style_info self.apply_style() -class BinnaryRasterLayer(RasterLayer): - def __init__(self, path, enable=True, name='栅格'): - super().__init__(name, enable, icon='') - self.path = path - self.layer = QgsRasterLayer(path, name) - self.set_render() - - def set_render(self): - renderer = QgsSingleBandGrayRenderer(self.layer.dataProvider(), 1) +class MultiBandRasterLayer(RasterLayer): + + def apply_style(self): + renderer=QgsMultiBandColorRenderer(self.layer.dataProvider(),self.style_info['r'],self.style_info['g'],self.style_info['b']) self.layer.setRenderer(renderer) self.layer.triggerRepaint() + +class SingleBandRasterLayer(RasterLayer): + def apply_style(self): + pass + class VectorLayer(BasicLayer): pass @@ -608,8 +607,8 @@ class PairLayer(BasicLayer): self.layers:List[BasicLayer] = [] self.id = str(uuid.uuid1()) self.checked = False - self.main_l1 = RasterLayer(path = pth1, enable=True, view_mode=BasicLayer.LEFT_VIEW,style_info=style_info1) - self.main_l2 = RasterLayer(path = pth2, enable=True, view_mode=BasicLayer.RIGHT_VIEW,style_info=style_info2) + self.main_l1 = MultiBandRasterLayer(path = pth1, enable=True, view_mode=BasicLayer.LEFT_VIEW,style_info=style_info1) + self.main_l2 = MultiBandRasterLayer(path = pth2, enable=True, view_mode=BasicLayer.RIGHT_VIEW,style_info=style_info2) self.main_l1.set_layer_parent(self) self.main_l2.set_layer_parent(self) self.grid = None @@ -633,7 +632,7 @@ class PairLayer(BasicLayer): if self.checked: return self.checked self.checked = self.main_l1.compare(self.main_l2) - return True + return self.checked def add_result_layer(self, result): result.set_layer_parent(self) @@ -668,6 +667,8 @@ class PairLayer(BasicLayer): enable=self.enable, pth1=self.main_l1.path, pth2=self.main_l2.path, + style_info1=self.main_l1.style_info, + style_info2=self.main_l2.style_info, layers=[to_dict(l) for l in self.layers if not (l is self.grid or l is self.main_l1 or l is self.main_l2) ] ) return data @@ -675,7 +676,7 @@ class PairLayer(BasicLayer): @staticmethod def from_dict(data): - player = PairLayer(data['pth1'], data['pth2']) + player = PairLayer(data['pth1'], data['pth2'], data['style_info1'], data['style_info2']) player.name = data['name'] for layer in data['layers']: l = from_dict(layer) diff --git a/test/random_gt.py b/test/random_gt.py new file mode 100644 index 0000000..b4341dc --- /dev/null +++ b/test/random_gt.py @@ -0,0 +1,17 @@ +from osgeo import gdal + +pth = r"D:\CVEO\2021-12-22-CDGUI\LZY_DATA\未命名1\bcdm\AAA.-BBB._68252_cmi_otsu_bcdm.tif" +npth = r'D:\CVEO\2021-12-22-CDGUI\LZY_DATA\未命名1\bcdm\gt.tif' +ds = gdal.Open(pth) +out_ds = gdal.GetDriverByName('GTiff').Create(npth, ds.RasterXSize, ds.RasterYSize, 1, gdal.GDT_Byte) +out_ds.SetGeoTransform(ds.GetGeoTransform()) +out_ds.SetProjection(ds.GetProjection()) + +data = ds.ReadAsArray() +data[100:200, 100:200] = 0 +out_ds.GetRasterBand(1).WriteArray(data) + + +out_ds.FlushCache() +del out_ds +del ds \ No newline at end of file