diff --git a/icons/change_detect.png b/icons/change_detect.png new file mode 100644 index 0000000..79985f3 Binary files /dev/null and b/icons/change_detect.png differ diff --git a/icons/create.png b/icons/create.png new file mode 100644 index 0000000..ba3d7d1 Binary files /dev/null and b/icons/create.png differ diff --git a/icons/data_load.png b/icons/data_load.png new file mode 100644 index 0000000..7638cad Binary files /dev/null and b/icons/data_load.png differ diff --git a/icons/delete.png b/icons/delete.png new file mode 100644 index 0000000..75aa8fd Binary files /dev/null and b/icons/delete.png differ diff --git a/icons/document.png b/icons/document.png new file mode 100644 index 0000000..9f9e9e7 Binary files /dev/null and b/icons/document.png differ diff --git a/icons/exit.png b/icons/exit.png new file mode 100644 index 0000000..51bf7cf Binary files /dev/null and b/icons/exit.png differ diff --git a/icons/filter.png b/icons/filter.png new file mode 100644 index 0000000..0297b28 Binary files /dev/null and b/icons/filter.png differ diff --git a/icons/grid.png b/icons/grid.png new file mode 100644 index 0000000..1a2cd39 Binary files /dev/null and b/icons/grid.png differ diff --git a/icons/grid_close.png b/icons/grid_close.png new file mode 100644 index 0000000..df6da86 Binary files /dev/null and b/icons/grid_close.png differ diff --git a/icons/layer.png b/icons/layer.png new file mode 100644 index 0000000..a533d3c Binary files /dev/null and b/icons/layer.png differ diff --git a/icons/open.png b/icons/open.png new file mode 100644 index 0000000..5103f23 Binary files /dev/null and b/icons/open.png differ diff --git a/icons/pan.png b/icons/pan.png new file mode 100644 index 0000000..f9e27c0 Binary files /dev/null and b/icons/pan.png differ diff --git a/icons/pan_1.png b/icons/pan_1.png new file mode 100644 index 0000000..7750700 Binary files /dev/null and b/icons/pan_1.png differ diff --git a/icons/save.png b/icons/save.png new file mode 100644 index 0000000..09ff1b8 Binary files /dev/null and b/icons/save.png differ diff --git a/icons/select.png b/icons/select.png new file mode 100644 index 0000000..71c01d6 Binary files /dev/null and b/icons/select.png differ diff --git a/icons/toolbox.png b/icons/toolbox.png new file mode 100644 index 0000000..30773e0 Binary files /dev/null and b/icons/toolbox.png differ diff --git a/icons/tools.png b/icons/tools.png new file mode 100644 index 0000000..e73e9f0 Binary files /dev/null and b/icons/tools.png differ diff --git a/icons/view.png b/icons/view.png new file mode 100644 index 0000000..21c0b4b Binary files /dev/null and b/icons/view.png differ diff --git a/icons/zoom_in.png b/icons/zoom_in.png new file mode 100644 index 0000000..808f651 Binary files /dev/null and b/icons/zoom_in.png differ diff --git a/icons/zoom_out.png b/icons/zoom_out.png new file mode 100644 index 0000000..fc5b0ea Binary files /dev/null and b/icons/zoom_out.png differ diff --git a/icons/zoom_to.png b/icons/zoom_to.png new file mode 100644 index 0000000..ef0e28b Binary files /dev/null and b/icons/zoom_to.png differ diff --git a/plugins/basic_change/otsu.py b/plugins/basic_change/otsu.py new file mode 100644 index 0000000..962075f --- /dev/null +++ b/plugins/basic_change/otsu.py @@ -0,0 +1,42 @@ +import numpy as np + +def OTSU(hist): + + u1=0.0#背景像素的平均灰度值 + u2=0.0#前景像素的平均灰度值 + th=0.0 + + #总的像素数目 + PixSum= np.sum(hist) + #各灰度值所占总像素数的比例 + PixRate=hist / PixSum + #统计各个灰度值的像素个数 + Max_var = 0 + #确定最大类间方差对应的阈值 + GrayScale = len(hist) + for i in range(1,len(hist)):#从1开始是为了避免w1为0. + u1_tem=0.0 + u2_tem=0.0 + #背景像素的比列 + w1=np.sum(PixRate[:i]) + #前景像素的比例 + w2=1.0-w1 + if w1==0 or w2==0: + pass + else:#背景像素的平均灰度值 + for m in range(i): + u1_tem=u1_tem+PixRate[m]*m + u1 = u1_tem * 1.0 / w1 + #前景像素的平均灰度值 + for n in range(i,GrayScale): + u2_tem = u2_tem + PixRate[n]*n + u2 = u2_tem / w2 + #print(u1) + #类间方差公式:G=w1*w2*(u1-u2)**2 + tem_var=w1*w2*np.power((u1-u2),2) + #print(tem_var) + #判断当前类间方差是否为最大值。 + if Max_var + + icons\change_detect.png + icons\cancel.svg + icons\clear.svg + icons\edit.svg + icons\exit.png + icons\export.svg + icons\font.svg + icons\full.svg + icons\create.png + icons\data_load.png + icons\delete.png + icons\document.png + icons\filter.png + icons\grid_close.png + icons\grid.png + icons\layer.png + icons\open.png + icons\pan.png + icons\pan_1.png + icons\save.png + icons\select.png + icons\toolbox.png + icons\tools.png + icons\view.png + icons\zoom_in.png + icons\zoom_out.png + icons\zoom_to.png + icons\load.svg + icons\logo.svg + icons\model.svg + icons\ok.svg + icons\outline.svg + icons\paint.svg + icons\pan.svg + icons\qt.svg + icons\settings.svg + icons\splash.png + icons\start.svg + icons\vector.svg + icons\zoomin.svg + icons\zoomout.svg + + diff --git a/rscder/gui/actions.py b/rscder/gui/actions.py index d264543..99b2e9a 100644 --- a/rscder/gui/actions.py +++ b/rscder/gui/actions.py @@ -2,7 +2,7 @@ import logging import os from pathlib import Path from PyQt5 import QtCore, QtGui, QtWidgets -from PyQt5.QtWidgets import QAction, QActionGroup, QLabel, QFileDialog +from PyQt5.QtWidgets import QAction, QActionGroup, QLabel, QFileDialog, QMenuBar from rscder.gui.project import Create from rscder.utils.project import Project from rscder.utils.misc import singleton @@ -44,19 +44,20 @@ class ActionManager(QtCore.QObject): self.menubar = None self.status_bar = None - def set_menus(self, menubar): + def set_menus(self, menubar:QMenuBar): self.menubar = menubar - self.file_menu = menubar.addMenu('&文件') - self.basic_menu = menubar.addMenu('&基本工具') - self.change_detection_menu = menubar.addMenu('&通用变化检测') - self.special_chagne_detec_menu = menubar.addMenu('&专题变化检测') + self.file_menu = menubar.addMenu( '&文件') + self.basic_menu = menubar.addMenu( '&基本工具') + self.change_detection_menu = menubar.addMenu( '&通用变化检测') + self.special_chagne_detec_menu = menubar.addMenu( '&专题变化检测') self.seg_chagne_detec_menu = menubar.addMenu('&分类后变化检测') - self.postop_menu = menubar.addMenu('&检测后处理') + self.postop_menu = menubar.addMenu( '&检测后处理') self.view_menu = menubar.addMenu('&视图') self.plugin_menu = menubar.addMenu('&插件') - self.help_menu = menubar.addMenu('&帮助') + self.help_menu = menubar.addMenu( '&帮助') + @property def menus(self): return { @@ -83,16 +84,17 @@ class ActionManager(QtCore.QObject): ''' File menu ''' - project_create = self.add_action(QAction('&工程创建', self.w_parent), 'File') - project_open = self.add_action(QAction('&打开工程', self.w_parent), 'File') - project_save = self.add_action(QAction('&保存工程', self.w_parent), 'File') - data_load = self.add_action(QAction('&数据加载', self.w_parent), 'File') - view_setting = self.add_action(QAction('&界面定制', self.w_parent), 'File') - exit_app = self.add_action(QAction('&退出', self.w_parent), 'File') + project_create = self.add_action(QAction(QtGui.QIcon( ':/icons/create.png' ), '&工程创建', self.w_parent), 'File') + project_open = self.add_action(QAction(QtGui.QIcon( ':/icons/open.png' ), '&打开工程', self.w_parent), 'File') + project_save = self.add_action(QAction(QtGui.QIcon( ':/icons/save.png' ),'&保存工程', self.w_parent), 'File') + data_load = self.add_action(QAction(QtGui.QIcon( ':/icons/data_load.png' ),'&数据加载', self.w_parent), 'File') + view_setting = self.add_action(QAction(QtGui.QIcon( ':/icons/view.png' ),'&界面定制', self.w_parent), 'File') + exit_app = self.add_action(QAction(QtGui.QIcon( ':/icons/exit.png' ),'&退出', self.w_parent), 'File') project_create.triggered.connect(self.project_create) project_open.triggered.connect(self.project_open) project_save.triggered.connect(self.project_save) data_load.triggered.connect(self.data_load) + view_setting.triggered.connect(self.view_setting) exit_app.triggered.connect(self.w_parent.close) @@ -103,9 +105,9 @@ class ActionManager(QtCore.QObject): self.file_menu.addAction(project_open) self.file_menu.addAction(project_save) self.file_menu.addAction(data_load) - self.file_menu.addAction(view_setting) + # self.file_menu.addAction(view_setting) self.file_menu.addAction(exit_app) - + self.view_menu.addAction(view_setting) if self.toolbar is not None: self.toolbar.addAction(project_create) self.toolbar.addAction(project_open) @@ -114,14 +116,14 @@ class ActionManager(QtCore.QObject): ''' Basic menu ''' - grid_line = self.add_action(QAction('&网格线', self.w_parent), 'Basic Line') + grid_line = self.add_action(QAction(QtGui.QIcon( ':/icons/grid.png' ),'&网格线', self.w_parent), 'Basic Line') grid_line.setCheckable(True) grid_line.setChecked(True) - zomm_in = self.add_action(QAction('&放大', self.w_parent), 'Basic') - zomm_out = self.add_action(QAction('&缩小', self.w_parent), 'Basic') - pan = self.add_action(QAction('&漫游', self.w_parent), 'Basic') - locate = self.add_action(QAction('&定位', self.w_parent), 'Basic') + zomm_in = self.add_action(QAction(QtGui.QIcon( ':/icons/zoom_out.png' ),'&放大', self.w_parent), 'Basic') + zomm_out = self.add_action(QAction(QtGui.QIcon( ':/icons/zoom_in.png' ),'&缩小', self.w_parent), 'Basic') + pan = self.add_action(QAction(QtGui.QIcon( ':/icons/pan_1.png' ),'&漫游', self.w_parent), 'Basic') + locate = self.add_action(QAction(QtGui.QIcon( ':/icons/zoom_to.png' ),'&定位', self.w_parent), 'Basic') pan.setCheckable(True) pan.setChecked(True) @@ -143,7 +145,7 @@ class ActionManager(QtCore.QObject): ''' Plugin menu ''' - plugin_list = self.add_action(QAction('&插件列表', self.w_parent), 'Plugin') + plugin_list = self.add_action(QAction(QtGui.QIcon( ':/icons/toolbox.png' ),'&插件列表', self.w_parent), 'Plugin') plugin_list.triggered.connect(self.plugin_list) self.plugin_menu.addAction(plugin_list) @@ -163,10 +165,10 @@ class ActionManager(QtCore.QObject): if self.status_bar is not None: corr_widget = QLabel(self.status_bar) # corr_widget.setLineWidth(200) - corr_widget.setFixedWidth(200) + corr_widget.setFixedWidth(250) self.status_bar.addWidget(corr_widget) scale_widget = QLabel(self.status_bar) - scale_widget.setFixedWidth(200) + scale_widget.setFixedWidth(250) self.status_bar.addWidget(scale_widget) self.double_map.corr_changed.connect(corr_widget.setText) self.double_map.scale_changed.connect(scale_widget.setText) diff --git a/rscder/gui/layercombox.py b/rscder/gui/layercombox.py index 8e6b2a6..6fbfbf7 100644 --- a/rscder/gui/layercombox.py +++ b/rscder/gui/layercombox.py @@ -1,15 +1,19 @@ from PyQt5.QtWidgets import QComboBox +from PyQt5.QtGui import QIcon from rscder.utils.project import Project class LayerCombox(QComboBox): def __init__(self, parent=None): super().__init__(parent) - self.addItem('---', None) for layer in Project().layers.values(): self.addItem(layer.name, layer.id) + for i in range(self.count() - 1): + self.setItemIcon(i + 1, QIcon(':/icons/layer.png')) + + self.currentIndexChanged.connect(self.on_changed) self.current_layer = None diff --git a/rscder/gui/layertree.py b/rscder/gui/layertree.py index 4e7a0d4..eec75d7 100644 --- a/rscder/gui/layertree.py +++ b/rscder/gui/layertree.py @@ -32,6 +32,7 @@ class LayerTree(QtWidgets.QWidget): self.tree.setHeaderHidden(True) # self.tree.setHeaderLabels(['图层']) self.root.setText(0,'图层') + self.root.setIcon(0,QtGui.QIcon(':/icons/layer.png')) # child1=QTreeWidgetItem() # child1.setText(0,'child1') @@ -98,6 +99,7 @@ class LayerTree(QtWidgets.QWidget): layer:PairLayer = Project().layers[layer] item_root = QtWidgets.QTreeWidgetItem(self.root) item_root.setText(0,layer.name) + item_root.setIcon(0, QtGui.QIcon(':/icons/document.png')) item_root.setData(0, Qt.UserRole, LayerTree.LAYER_TOOT) item_root.setData(0, Qt.UserRole + 1, layer.id) item_root.setCheckState(0, Qt.Checked if layer.enable else Qt.Unchecked) @@ -112,18 +114,21 @@ class LayerTree(QtWidgets.QWidget): grid_item.setText(0,'格网') grid_item.setData(0, Qt.UserRole, LayerTree.GRID) grid_item.setCheckState(0, Qt.Checked if layer.grid_enable else Qt.Unchecked) + grid_item.setIcon(0, QtGui.QIcon(':/icons/grid.png')) item1 = QtWidgets.QTreeWidgetItem(item_root) item1.setText(0, layer.l1_name) item1.setCheckState(0, Qt.Checked if layer.l1_enable else Qt.Unchecked) item1.setData(0, Qt.UserRole, LayerTree.SUB_RASTER) item1.setData(0, Qt.UserRole + 1, LayerTree.LEFT_RASTER) + item1.setIcon(0, QtGui.QIcon(':/icons/layer.png')) item2 = QtWidgets.QTreeWidgetItem(item_root) item2.setText(0, layer.l2_name) item2.setCheckState(0, Qt.Checked if layer.l2_enable else Qt.Unchecked) - item1.setData(0, Qt.UserRole, LayerTree.SUB_RASTER) - item1.setData(0, Qt.UserRole + 1, LayerTree.RIGHT_RASTER) + item2.setData(0, Qt.UserRole, LayerTree.SUB_RASTER) + item2.setData(0, Qt.UserRole + 1, LayerTree.RIGHT_RASTER) + item2.setIcon(0, QtGui.QIcon(':/icons/layer.png')) for ri, item in enumerate(layer.results): item_result = QtWidgets.QTreeWidgetItem(item_root) @@ -131,6 +136,8 @@ class LayerTree(QtWidgets.QWidget): item_result.setCheckState(0, Qt.Checked if item.enable else Qt.Unchecked) item_result.setData(0, Qt.UserRole, LayerTree.RESULT) item_result.setData(0, Qt.UserRole + 1, ri) + + item_result.setIcon(0, QtGui.QIcon(':/icons/vector.svg')) self.tree.expandAll() diff --git a/rscder/gui/mainwindow.py b/rscder/gui/mainwindow.py index b90a2ae..598f43e 100644 --- a/rscder/gui/mainwindow.py +++ b/rscder/gui/mainwindow.py @@ -22,7 +22,7 @@ class MainWindow(QMainWindow): self.setWindowTitle(QApplication.applicationName() + ' ' + str(self.current_instance)) else: self.setWindowTitle(QApplication.applicationName()) - self.setWindowIcon(QIcon(":/icons/logo.svg")) + self.setWindowIcon(QIcon(":/icons/change_detect.png")) self.setAcceptDrops(True) self.setContextMenuPolicy(Qt.CustomContextMenu) diff --git a/rscder/gui/result.py b/rscder/gui/result.py index c977156..8464cf1 100644 --- a/rscder/gui/result.py +++ b/rscder/gui/result.py @@ -2,7 +2,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt,QModelIndex, pyqtSignal from PyQt5.QtGui import QStandardItemModel, QStandardItem -from PyQt5.QtWidgets import (QTableWidgetItem, QTableWidget, QAbstractItemView, QHeaderView, QStyleFactory) +from PyQt5.QtWidgets import (QTableWidgetItem, QTableWidget, QMessageBox, QAbstractItemView, QHeaderView, QStyleFactory) from rscder.utils.project import PairLayer, Project, ResultLayer @@ -56,9 +56,16 @@ class ResultTable(QtWidgets.QWidget): y = self.tablewidget.item(row, 1).text() self.on_item_click.emit({'x':float(x), 'y':float(y)}) + def save(self): + if self.result is None: + return + self.result.save() + def on_result(self, layer_id, result_id): self.is_in_set_data = True result = Project().layers[layer_id].results[result_id] + if result != self.result: + self.save() self.result = result self.clear() self.set_data(result) diff --git a/rscder/res.qrc b/rscder/res.qrc deleted file mode 100644 index 76b52ba..0000000 --- a/rscder/res.qrc +++ /dev/null @@ -1,26 +0,0 @@ - - - icons\assessment.svg - icons\cancel.svg - icons\clear.svg - icons\edit.svg - icons\exit.svg - icons\export.svg - icons\font.svg - icons\full.svg - icons\load.svg - icons\logo.svg - icons\model.svg - icons\ok.svg - icons\outline.svg - icons\paint.svg - icons\pan.svg - icons\qt.svg - icons\settings.svg - icons\splash.png - icons\start.svg - icons\vector.svg - icons\zoomin.svg - icons\zoomout.svg - - diff --git a/rscder/utils/project.py b/rscder/utils/project.py index 761af95..506bfda 100644 --- a/rscder/utils/project.py +++ b/rscder/utils/project.py @@ -83,6 +83,8 @@ class Project(QObject): 'root': self.root, 'layers': [ layer.to_dict(None if self.file_mode == Project.ABSOLUTE_MODE else self.root) for layer in self.layers.values() ], } + for layer in self.layers.values(): + layer.save() with open(self.file, 'w') as f: yaml.safe_dump(data_dict, f) # yaml.safe_dump(data_dict, open(self.file, 'w')) @@ -129,19 +131,16 @@ class Project(QObject): else: self.message_box.error(player.msg) -class VectorLayer: - pass - class GridLayer: def set_render(self): symbol_layer = QgsSimpleLineSymbolLayer() - symbol_layer.setWidth(1) - symbol_layer.setColor(QColor.fromRgb(255,255,255, 100)) + symbol_layer.setWidth(1 * self.x_res) + symbol_layer.setColor(QColor.fromRgb(255,255,255, 200)) symbol = QgsLineSymbol() symbol.changeSymbolLayer(0, symbol_layer) - + symbol.setWidthUnit(QgsUnitTypes.RenderMapUnits) render = QgsSingleSymbolRenderer(symbol) self.lines_layer.setRenderer(render) @@ -228,6 +227,14 @@ class ResultLayer: self.enable = False self.parent = parent + def save(self): + if self.layer_type == ResultLayer.POINT: + with open(self.path, 'w') as f: + f.write('x,y,diff,status\n') + for i in range(len(self.data)): + f.write('{},{},{},{}\n'.format(self.data[i][0], self.data[i][1], self.data[i][2], int(self.data[i][3]))) + + def update(self, data): if self.layer_type == ResultLayer.POINT: row = data['row'] @@ -403,6 +410,11 @@ class PairLayer: layer.results.append(ResultLayer.from_dict(r, layer, root)) # layer.grid_layer = GridLayer.from_dict(data['grid_layer']) return layer + + def save(self): + for r in self.results: + r.save() + def __init__(self, pth1, pth2, cell_size) -> None: self.pth1 = pth1 self.pth2 = pth2