流程拆分

This commit is contained in:
copper 2022-05-26 16:15:19 +08:00
parent 522548a151
commit d30cf3b65c
11 changed files with 237 additions and 68 deletions

View File

@ -5,19 +5,18 @@ 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, PairLayer, ResultPointLayer, RasterLayer
from rscder.utils.project import BasicLayer, Project, RasterLayer
from rscder.gui.layercombox import PairLayerCombox
from osgeo import gdal, gdal_array
from osgeo import gdal
from threading import Thread
import numpy as np
from basic_change.otsu import OTSU
class MyDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle('BasicChange')
self.setWindowTitle('差分法')
self.setWindowIcon(QIcon(":/icons/logo.png"))
self.setFixedWidth(500)
@ -27,11 +26,11 @@ class MyDialog(QDialog):
# self.number_input = QLineEdit(self)
self.ok_button = QPushButton('OK', self)
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)
@ -41,7 +40,7 @@ class MyDialog(QDialog):
self.main_layout = QVBoxLayout()
self.main_layout.addWidget(self.layer_select)
# self.main_layout.addWidget(self.number_input)
self.main_layout.addLayout(self.button_layout)
self.setLayout(self.main_layout)
@ -82,10 +81,9 @@ class BasicMethod(BasicPlugin):
self.message_send.connect(self.send_message)
self.gap = 250
def setup(self):
self.basic_diff_method.setEnabled(True)
self.otsu_method.setEnabled(True)
def send_message(self, s):
self.message_box.info(s)
@ -111,8 +109,6 @@ class BasicMethod(BasicPlugin):
band = ds1.RasterCount
yblocks = ysize // cell_size[1]
geo = ds1.GetGeoTransform()
driver = gdal.GetDriverByName('GTiff')
out_tif = os.path.join(Project().cmi_path, 'temp.tif')
out_ds = driver.Create(out_tif, xsize, ysize, 1, gdal.GDT_Float32)
@ -151,11 +147,11 @@ class BasicMethod(BasicPlugin):
self.message_send.emit('归一化概率中...')
temp_in_ds = gdal.Open(out_tif)
out_normal_tif = os.path.join(Project().cmi_path, '{}-{}.tif'.format(layer1.layer_parent.name, int(np.random.rand() * 100000)))
out_normal_tif = os.path.join(Project().cmi_path, '{}_{}_cmi.tif'.format(layer1.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(ds1.GetGeoTransform())
out_normal_ds.SetProjection(ds1.GetProjection())
hist = np.zeros(256, dtype=np.int32)
# 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:
@ -167,57 +163,21 @@ class BasicMethod(BasicPlugin):
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)
# hist_t, _ = np.histogram(block_data, bins=256, range=(0, 256))
# hist += hist_t
# print(hist)
del temp_in_ds
try:
os.remove(out_tif)
except:
pass
self.gap = OTSU(hist)
self.message_send.emit('OTSU' + str(self.gap))
out_normal_ds.FlushCache()
del out_normal_ds
self.message_send.emit('完成归一化概率')
self.message_send.emit('计算变化表格中...')
out_csv = os.path.join(Project().bcdm_path, '{}-{}.csv'.format(layer1.layer_parent.name, int(np.random.rand() * 100000)))
xblocks = xsize // cell_size[0]
normal_in_ds = gdal.Open(out_normal_tif)
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 = normal_in_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() > self.gap:
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() / 255 * 100},1\n')
point_result_lalyer = ResultPointLayer(out_csv, enable=False, proj = layer1.proj, geo = layer1.geo)
raster_result_layer = RasterLayer(None, True, out_normal_tif, BasicLayer.BOATH_VIEW)
layer1.layer_parent.add_result_layer(point_result_lalyer)
# layer1.layer_parent.add_result_layer(point_result_lalyer)
layer1.layer_parent.add_result_layer(raster_result_layer)
self.message_send.emit('完成计算变化表格')
# self.message_send.emit('完成计算变化表格')
self.message_send.emit('差分法计算完成')
@ -232,8 +192,6 @@ class BasicMethod(BasicPlugin):
return
# layer:PairLayer = list(self.project.layers.values())[0]
t = Thread(target=self.run_basic_diff_alg, args=(layer1, layer2))
t.start()

View File

@ -0,0 +1 @@
from evaluation.main import *

View File

@ -0,0 +1,36 @@
from rscder.plugins.basic import BasicPlugin
from PyQt5.QtWidgets import QAction, QDialog, QHBoxLayout, QVBoxLayout, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
class EvalutationDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle('精度评估')
self.setWindowIcon(QIcon(":/icons/logo.png"))
self.setFixedWidth(500)
self.ok_button = QPushButton('OK', 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.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(self.button_layout)
self.setLayout(self.main_layout)
def on_ok(self):
self.accept()
def on_cancel(self):
self.reject()

View File

View File

@ -0,0 +1 @@
from table_result.main import *

View File

@ -0,0 +1 @@
from threshold.main import *

157
plugins/threshold/main.py Normal file
View File

@ -0,0 +1,157 @@
import os
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 PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from rscder.gui.layercombox import RasterLayerCombox
from rscder.utils.project import Project, RasterLayer
from threshold.otsu import OTSU
class OTSUDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle('OTSU阈值')
self.setWindowIcon(QIcon(":/icons/logo.png"))
self.setFixedWidth(500)
self.layercombox = RasterLayerCombox(self)
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.addWidget(self.layercombox)
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 OTSUPlugin(BasicPlugin):
@staticmethod
def info():
return {
"name": "OTSU",
"description": "OTSU阈值",
"author": "rscder",
"version": "1.0.0"
}
def set_action(self):
self.action = QAction('OTSU阈值', self.mainwindow)
self.action.triggered.connect(self.run)
ActionManager().postop_menu.addAction(self.action)
def run(self):
dialog = OTSUDialog(self.mainwindow)
if dialog.exec_() == QDialog.Accepted:
pass
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:
self.message_box.error('请选择符合要求的图层')
return
hist = np.zeros(256, dtype=np.int)
xsize = ds.RasterXSize
ysize = ds.RasterYSize
max_pixels = 1e7
max_rows = max_pixels // xsize
if max_rows < 1:
max_rows = 1
if max_rows > ysize:
max_rows = ysize
block_count = ysize // max_rows + 1
for i in range(block_count):
start_row = i * max_rows
end_row = min((i + 1) * max_rows, ysize)
block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
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))
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)
out_ds.SetGeoTransform(ds.GetGeoTransform())
out_ds.SetProjection(ds.GetProjection())
out_band = out_ds.GetRasterBand(1)
for i in range(block_count):
start_row = i * max_rows
end_row = min((i + 1) * max_rows, ysize)
block = band.ReadAsArray(0, start_row, xsize, end_row - start_row)
out_band.WriteArray(block > gap, 0, start_row)
out_band.FlushCache()
out_ds = None
ds = None
self.message_box.info('OTSU阈值完成')
otsu_layer = RasterLayer(path = out_th, style_info={})
# otsu_method = QAction('OTSU阈值分割')
# postop_menu = self.ctx['postop_menu']
# postop_menu.addAction(otsu_method)
# otsu_method.setEnabled(False)
# point_result_lalyer = ResultPointLayer(out_csv, enable=False, proj = layer1.proj, geo = layer1.geo)
# self.gap = OTSU(hist)
# self.message_send.emit('OTSU' + str(self.gap))
# out_normal_ds.FlushCache()
# del out_normal_ds
# self.message_send.emit('完成归一化概率')
# self.message_send.emit('计算变化表格中...')
# out_csv = os.path.join(Project().bcdm_path, '{}-{}.csv'.format(layer1.layer_parent.name, int(np.random.rand() * 100000)))
# xblocks = xsize // cell_size[0]
# normal_in_ds = gdal.Open(out_normal_tif)
# 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 = normal_in_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() > self.gap:
# 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() / 255 * 100},1\n')

View File

@ -57,8 +57,6 @@ class ActionManager(QtCore.QObject):
self.plugin_menu = menubar.addMenu('&插件')
self.help_menu = menubar.addMenu( '&帮助')
@property
def menus(self):
return {
@ -216,8 +214,7 @@ class ActionManager(QtCore.QObject):
Project().clear()
parent = str(Path(project_file[0]).parent)
Settings.General().last_path = parent
name = os.path.basename(project_file[0])
Project().setup(parent, name)
Project().setup(project_file[0])
def project_save(self):
if Project().is_init:
@ -230,12 +227,7 @@ class ActionManager(QtCore.QObject):
if(file_loader.exec_()):
Project().add_layer(file_loader.path1,file_loader.path2,file_loader.style1,file_loader.style2)
self.message_box.info('Data loaded')
# file_open = QFileDialog.getOpenFileNames(self.w_parent, '打开数据', Settings.General().last_path, '*.*')
# if file_open[0] != '':
# if len(file_open[0]) != 2:
# self.message_box.warning('请选择两个数据文件')
# return
# Project().add_layer(file_open[0][0], file_open[0][1])
def view_setting(self):

View File

@ -11,7 +11,7 @@ from rscder.utils.project import RasterLayer
class loader(QDialog):
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.setWindowTitle('Load Data')
self.setWindowTitle('载入数据')
self.setWindowIcon(QIcon(":/icons/data_load.png"))
self.path1=''
self.path2=''

View File

@ -12,7 +12,13 @@ import numpy as np
from osgeo import gdal, gdal_array
from rscder.utils.icons import IconInstance
from rscder.utils.setting import Settings
from qgis.core import QgsRasterLayer, QgsMarkerSymbol, QgsUnitTypes, QgsCategorizedSymbolRenderer, QgsRendererCategory, QgsPalLayerSettings, QgsRuleBasedLabeling, QgsTextFormat, QgsLineSymbol, QgsSingleSymbolRenderer, QgsSimpleLineSymbolLayer, QgsVectorLayer, QgsCoordinateReferenceSystem, QgsFeature, QgsGeometry, QgsPointXY,QgsMultiBandColorRenderer
from qgis.core import (\
QgsRasterLayer, QgsMarkerSymbol, QgsUnitTypes,
QgsCategorizedSymbolRenderer, QgsRendererCategory,
QgsPalLayerSettings, QgsRuleBasedLabeling, QgsTextFormat,
QgsLineSymbol, QgsSingleSymbolRenderer, QgsSimpleLineSymbolLayer,
QgsVectorLayer, QgsCoordinateReferenceSystem, QgsFeature,
QgsGeometry, QgsPointXY, QgsMultiBandColorRenderer)
from PyQt5.QtCore import QObject, pyqtSignal, Qt, QThread
from PyQt5.QtWidgets import QTreeWidgetItem, QAction
from PyQt5.QtGui import QColor, QIcon, QFont
@ -375,6 +381,8 @@ class GridLayer(BasicLayer):
self.set_render()
class RasterLayer(BasicLayer):
def __init__(self, name=None, enable=False, path=None, view_mode=BasicLayer.BOATH_VIEW,style_info={'r':3,'g':2,'b':1,'NIR':3}):
@ -430,6 +438,21 @@ class RasterLayer(BasicLayer):
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)
self.layer.setRenderer(renderer)
self.layer.triggerRepaint()
class VectorLayer(BasicLayer):
pass