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()