diff --git a/plugins/In_one/main.py b/plugins/In_one/main.py index c6f47ce..f2ccb3f 100644 --- a/plugins/In_one/main.py +++ b/plugins/In_one/main.py @@ -241,6 +241,7 @@ class InOnePlugin(BasicPlugin): pth2=Meanfilter(w.x_size_input.text(),w.y_size_input.text(),w.layer_combox.layer2) self.send_message.emit('均值滤波图像{}'.format(w.layer_combox.layer2.name)) name=name+'_mean_filter' + dict['预处理']=['均值滤波','|'.format(pth1,pth2)] else: pass @@ -248,18 +249,18 @@ class InOnePlugin(BasicPlugin): if w.cd_select.choose==self.cd[0]: cdpth=basic_cd(pth1,pth2,w.layer_combox.layer1.layer_parent,self.send_message) name += '_basic_cd' - #dict[name]=cdpth + dict['变化检测算法']=['差分法',cdpth] else: pass thpth=None if w.threshold_select.choose==self.threshold[0]: - thpth=otsu(cdpth,w.layer_combox.layer1.layer_parent.name,self.send_message) + thpth,gap=otsu(cdpth,w.layer_combox.layer1.layer_parent.name,self.send_message) name+='_otsu' - dict[name]=thpth + dict['后处理']=['OTSU阈值',gap,cdpth] elif w.threshold_select.choose=='手动阈值': thpth=thresh(cdpth,float(w.threshold_input.text()),w.layer_combox.layer1.layer_parent.name,self.send_message) - dict[name+'_thresh_{:.1f}'.format(float(w.threshold_input.text()))] + dict['后处理']=['手动阈值',[float(w.threshold_input.text())],thpth] else: pass @@ -417,7 +418,7 @@ def otsu(pth,name,send_message): out_ds = None ds = None send_message.emit('OTSU阈值完成') - return out_th + return out_th,gap #otsu_layer = SingleBandRasterLayer(path = out_th, style_info={}) #layer.layer_parent.add_result_layer(otsu_layer) @@ -496,8 +497,7 @@ def table_layer(pth,layer,name,send_message,dict): center_y = center_y * geo[5] + geo [3] f.write(f'{center_x},{center_y},{block_data_xy.mean() * 100},{int(block_data_xy.mean() > 0.5)}\n') - result_layer = ResultPointLayer(out_csv, enable=True, proj=layer.proj, geo=layer.geo) - result_layer.result_path=dict + result_layer = ResultPointLayer(out_csv, enable=True, proj=layer.proj, geo=layer.geo,result_path=dict) # print(result_layer.result_path) layer.layer_parent.add_result_layer(result_layer) send_message.emit('计算完成') diff --git a/rscder/gui/info.py b/rscder/gui/info.py new file mode 100644 index 0000000..551dbd1 --- /dev/null +++ b/rscder/gui/info.py @@ -0,0 +1,29 @@ +from distutils.log import info +from PyQt5.QtWidgets import QHBoxLayout,QDialog,QLabel,QVBoxLayout +from PyQt5.QtGui import QColor, QDragEnterEvent, QDropEvent,QPixmap +from PyQt5.QtCore import QSize,Qt +import yaml + + + +class InfoBox(QDialog): + def __init__(self,infodic:dict,parent=None): + super(InfoBox,self).__init__(parent=parent) + v=QVBoxLayout() + if 'prewmap' in infodic.keys(): + + pmap=infodic.pop('prewmap') + label=QLabel(yaml.dump(infodic,allow_unicode=True,sort_keys=False)) + label.setWordWrap(True)#过长自动换行,主要是wkt过长 + v.addWidget(label) + + maplabel=QLabel() + maplabel.setPixmap(QPixmap.fromImage(pmap)) + v.addWidget(maplabel,0,Qt.AlignHCenter) + else: + label=QLabel(yaml.dump(infodic,allow_unicode=True,sort_keys=False)) + label.setWordWrap(True)#过长自动换行,主要是wkt过长 + v.addWidget(label) + self.setLayout(v) + self.show() + \ No newline at end of file diff --git a/rscder/utils/project.py b/rscder/utils/project.py index d651a21..67754c0 100644 --- a/rscder/utils/project.py +++ b/rscder/utils/project.py @@ -1,16 +1,21 @@ from cgitb import enable from collections import OrderedDict +from email.message import Message +import imp import inspect import os from pathlib import Path +from pydoc import render_doc import shutil +from statistics import stdev from threading import Thread from time import sleep, time from typing import Dict, List import uuid import numpy as np -from osgeo import gdal, gdal_array +from osgeo import gdal, gdal_array,osr from rscder.utils.icons import IconInstance +from rscder.gui.info import InfoBox from rscder.utils.setting import Settings from qgis.core import (\ QgsRasterLayer, QgsMarkerSymbol, QgsUnitTypes, @@ -19,12 +24,12 @@ from qgis.core import (\ 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.QtCore import QObject, pyqtSignal, Qt, QThread,QSize +from PyQt5.QtWidgets import QTreeWidgetItem, QAction,QMessageBox from PyQt5.QtGui import QColor, QIcon, QFont import yaml -from .misc import singleton +from .misc import singleton def relative_path(path: str, root:str) -> str: return os.path.relpath(path, root) @@ -318,8 +323,22 @@ class BasicLayer(QObject): del_action.triggered.connect(del_layer) actions.append(del_action) + if self.info: + show_info=QAction(IconInstance().HELP,'属性信息') + actions.append(show_info) + def showIofn(info): + #print(info) + a=InfoBox(info) + a.exec_() + + show_info.triggered.connect(lambda :showIofn(self.info)) return actions + return actions + @property + def info(self): + return None + class GridLayer(BasicLayer): def set_render(self): @@ -390,7 +409,7 @@ class GridLayer(BasicLayer): 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}): + def __init__(self, name=None, enable=False, path=None, view_mode=BasicLayer.BOATH_VIEW,style_info={'r':3,'g':2,'b':1,'NIR':0}): if name is None: name = os.path.splitext(os.path.basename(path))[0] super().__init__(name, enable, IconInstance().RASTER, path, BasicLayer.IN_FILE, view_mode) @@ -438,11 +457,44 @@ class RasterLayer(BasicLayer): return s def apply_style(self): pass + + @property + def bandinfo(self): + ds :gdal.Dataset= gdal.Open(self.path) + bands=ds.RasterCount + bandinfo_={} + for i in range(1,bands+1) : + min,max,mean,stdev=ds.GetRasterBand(i).ComputeStatistics(True) + bandinfo_['波段{}'.format(i)]=['最小值:{}'.format(min),'最大值:{}'.format(max),'均值:{}'.format(mean),'方差:{}'.format(stdev)] + ds=None + return bandinfo_ def set_stlye(self,style_info): self.style_info=style_info self.apply_style() + @property + def info(self): + #基础属性 + basic={} + basic['文件名']=self.path + + basic['文件大小']="{} Mb".format(os.path.getsize(self.path)//(1024*1024)) + basic['波段信息']=self.bandinfo + #渲染属性 + render=self.style_info + + mapinfo={ + '基础属性':basic, + '渲染属性':render, + 'prewmap':self.preview + } + return mapinfo + @property + def preview(self,width=400): + w=self.layer.width() + h=self.layer.height() + return self.layer.previewAsImage(QSize(width,int(width*h/w))) class MultiBandRasterLayer(RasterLayer): @@ -450,7 +502,10 @@ class MultiBandRasterLayer(RasterLayer): renderer=QgsMultiBandColorRenderer(self.layer.dataProvider(),self.style_info['r'],self.style_info['g'],self.style_info['b']) self.layer.setRenderer(renderer) self.layer.triggerRepaint() - + # @property + # def info(self): + # mapinfo=super().info + # mapinfo['渲染属性']['波段']='单波段' class SingleBandRasterLayer(RasterLayer): def apply_style(self): @@ -463,7 +518,7 @@ class VectorLayer(BasicLayer): class ResultPointLayer(BasicLayer): - def __init__(self, path, name=None, enable = False, proj = None, geo = None,result_path={},dsort=False ): + def __init__(self, path, name=None, enable = False, proj = None, geo = None,result_path={},dsort=False): if name is None: name = os.path.splitext(os.path.basename(path))[0] super().__init__(name, enable, icon=IconInstance().VECTOR, path=path, path_mode = BasicLayer.IN_FILE, view_mode=BasicLayer.BOATH_VIEW ) @@ -471,8 +526,8 @@ class ResultPointLayer(BasicLayer): self.wkt = proj self.geo = geo self.dsort=dsort - self.result_path=result_path - + self.result_path:dict=result_path + # self.methods= self.load_point_file() def save(self): @@ -619,8 +674,23 @@ class ResultPointLayer(BasicLayer): return actions # def load_file(self, path): + + @property + def info(self): + #基础属性 + basic={} + basic['文件路径']=self.path + #中间算法信息: + methods={ k:v[0] for k ,v in self.result_path.items()} + basic['变化检测算法']=methods + #渲染信息 + render={} + render['标注字体大小']=2 + render['标注颜色']='#ffff00' + render['阈值']=self.result_path['后处理'][1] + return {'基础属性':basic,'渲染属性':render} class PairLayer(BasicLayer): def __init__(self, pth1, pth2,style_info1,style_info2) -> None: @@ -694,7 +764,41 @@ class PairLayer(BasicLayer): ) return data + @property + def info(self): + + ds= gdal.Open(self.main_l1.path) + srs= osr.SpatialReference(ds.GetProjectionRef()) + metadata={} + # 空间参考系统 + metadata['proj4'] = srs.ExportToProj4() + metadata['wkt'] = srs.ExportToWkt() + # 地理坐标系 + metadata['geocs'] = srs.GetAttrValue('GEOGCS') + metadata['uom'] = srs.GetAttrValue('UNIT') + # 投影坐标系 + metadata['projcs'] = srs.GetAttrValue('PROJCS') # if projected + metadata['epsg'] = srs.GetAuthorityCode(None) + ds=None + #格网信息 + gridData={} + gridData['格网大小']='{}像素'.format(self.grid.cell_size) + gridData['格网线']=['宽度:1像素', '颜色:白色'] + + #公共掩模 + maskData={} + + + mapinfo={ + '坐标系':metadata, + '格网':gridData, + '公共掩膜':maskData + } + + return mapinfo + + @staticmethod def from_dict(data): player = PairLayer(data['pth1'], data['pth2'], data['style_info1'], data['style_info2'])