金字塔加载

This commit is contained in:
石沈昊 2022-07-01 02:07:01 +08:00
parent b97fb528fd
commit b47578c7e8
5 changed files with 426 additions and 23 deletions

View File

@ -500,4 +500,4 @@ def table_layer(pth,layer,name,send_message,dict):
result_layer.result_path=dict
# print(result_layer.result_path)
layer.layer_parent.add_result_layer(result_layer)
send_message.emit('计算完成')
send_message.emit('计算完成')

View File

@ -225,6 +225,7 @@ class ActionManager(QtCore.QObject):
if Project().is_init:
Project().save()
file_loader=loader(self.w_parent)
file_loader.setModal(True)
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')

View File

@ -1,19 +1,48 @@
from tkinter.ttk import Style
from colorsys import hls_to_rgb
import os
from osgeo import gdal
from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow, QToolBox
from PyQt5.QtWidgets import QDialog, QFileDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox
from PyQt5.QtCore import Qt, QSize, QSettings
from PyQt5.QtWidgets import QDialog, QFileDialog, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QMessageBox,QSpacerItem
from PyQt5.QtCore import Qt, QSize,QSettings,pyqtSignal,QThread
from PyQt5.QtGui import QIcon,QColor
from PyQt5 import QtGui
from threading import Thread
from rscder.utils.icons import IconInstance
from rscder.utils.setting import Settings
from rscder.gui.mapcanvas import DoubleCanvas
from qgis.gui import QgsMapCanvas
from rscder.utils.project import MultiBandRasterLayer, RasterLayer
from rscder.utils.project import MultiBandRasterLayer, Project, RasterLayer
from rscder.gui.progress_bar import MetroCircleProgress
class progressDialog(QDialog):
def __init__(self, parent=None,name='default') -> None:
super(progressDialog,self).__init__(parent)
self.setWindowTitle(name)
self.setWindowIcon(IconInstance().RASTER)
self.setFixedSize(300,80)
# self.setWindowIcon(IconInstance().RASTER)
tlayout=QVBoxLayout()
tlayout.setContentsMargins(10,0,0,0)
hlayout=QHBoxLayout()
h2layout=QHBoxLayout()
self.label=QLabel('加载影像...')
hlayout.addWidget(self.label)
hlayout.addItem(QSpacerItem(30,0))
tlayout.addLayout(hlayout)
h2layout.addWidget(MetroCircleProgress(self, radius=7))
tlayout.addLayout(h2layout)
self.setLayout(tlayout)
def setlabel(self,content:str):
self.label.setText(content)
class loader(QDialog):
signal1=pyqtSignal(str)
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.setWindowTitle('载入数据')
self.setWindowIcon(IconInstance().DATA_LOAD)
self.pyramid:bool=False
self.temp1=''
self.temp2=''
self.path1=''
self.path2=''
self.bands=['red:','green:','blue:','NIR:']
@ -41,6 +70,7 @@ class loader(QDialog):
path1_open = QPushButton('...', self)
# path1_open.setEnabled(False)
path1_open.setFixedWidth(30)
path1_open.clicked.connect(self.open_file1)
@ -50,7 +80,7 @@ class loader(QDialog):
path1_layout.addWidget(path1_input)
path1_layout.addWidget(path1_open)
labels1=[QLabel() for i in range(4)]
style1_inputs=[QLineEdit() for i in range(4)]
for i in range(4):
@ -62,7 +92,7 @@ class loader(QDialog):
style1_set = QPushButton(self.tr('确定'), self)
style1_set.setFixedWidth(40)
style1_set.clicked.connect(self.set_style1)
style1_set.setEnabled(False)
style1_layout=QHBoxLayout()
for i in range(4):
style1_layout.addWidget(labels1[i])
@ -80,6 +110,7 @@ class loader(QDialog):
path2_open = QPushButton('...', self)
path2_open.setFixedWidth(30)
# path2_open.setEnabled(False)
path2_open.clicked.connect(self.open_file2)
path2_layout=QHBoxLayout()
@ -89,7 +120,7 @@ class loader(QDialog):
labels2=[QLabel() for i in range(4)]
style2_inputs=[QLineEdit() for i in range(4)]
for i in range(4):
labels2[i].setText(self.bands[i])
@ -100,7 +131,9 @@ class loader(QDialog):
style2_set = QPushButton(self.tr('确定'), self)
style2_set.setFixedWidth(40)
style2_set.clicked.connect(self.set_style2)
style2_set.setEnabled(False)
self.open1=style1_set
self.open2=style2_set
style2_layout=QHBoxLayout()
for i in range(4):
style2_layout.addWidget(labels2[i])
@ -112,7 +145,7 @@ class loader(QDialog):
ok_button.clicked.connect(self.ok)
cancel_button.clicked.connect(self.cancel)
button_layout = QHBoxLayout()
button_layout.setDirection(QHBoxLayout.RightToLeft)
button_layout.addWidget(ok_button, 0, Qt.AlignRight)
@ -129,21 +162,91 @@ class loader(QDialog):
def open_file1(self):
path1 = QFileDialog.getOpenFileNames(self, '打开数据1', Settings.General().last_path, '*.*')
if path1:
self.path1 = path1[0][0]
self.path1_input.setText(self.path1)
self.left_layer=MultiBandRasterLayer(path=self.path1)
self.mapcanva1.setLayers([self.left_layer.layer])
self.mapcanva1.zoomToFeatureExtent(self.left_layer.layer.extent())
if path1[0]!='':
try:
self.path1 = path1[0][0]
self.path1_input.setText(self.path1)
result=QMessageBox.question(self, '提示', '是否创建图像金字塔', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) #默认关闭界面选择No
if result==QMessageBox.Yes:
progress1=progressDialog(self,'加载时相一')
progress1.setModal(False)
self.temp1=os.path.join(Project().other_path,'temp1.tif')
t1=GdalPreviewImage(self.path1,self.temp1,1024,self)
# t1.started.connect(progress1.show)
t1.finished.connect(self.loadfile1)
t1.finished.connect(lambda :progress1.setlabel('创建影像金字塔..'))
t2=build_pyramids_overviews(self.path1,self)
t2.finished.connect(progress1.hide)
t1.start()
t1.finished.connect(t2.start)
# t2.start()
progress1.show()
else:
progress1=progressDialog(self,'加载时相一')
progress1.setModal(False)
self.temp1=os.path.join(Project().other_path,'temp1.tif')
t1=GdalPreviewImage(self.path1,self.temp1,1024)
# t1.started.connect(progress1.show)
t1.finished.connect(self.loadfile1)
t1.finished.connect(progress1.hide)
t1.start()
progress1.show()
except:
return
def loadfile1(self):
try:
self.left_layer=MultiBandRasterLayer(path=self.temp1)
self.mapcanva1.setLayers([self.left_layer.layer])
self.mapcanva1.zoomToFeatureExtent(self.left_layer.layer.extent())
self.open1.setEnabled(True)
except:
return
def open_file2(self):
path2 = QFileDialog.getOpenFileNames(self, '打开数据2', Settings.General().last_path, '*.*')
if path2:
if path2[0]!='':
self.path2 = path2[0][0]
self.path2_input.setText(self.path2)
self.right_layer=MultiBandRasterLayer(path=self.path2)
self.mapcanva2.setLayers([self.right_layer.layer])
self.mapcanva2.zoomToFeatureExtent(self.right_layer.layer.extent())
result=QMessageBox.question(self, '提示', '是否创建图像金字塔', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) #默认关闭界面选择No
if result==QMessageBox.Yes:
progress2=progressDialog(self,'加载时相二')
progress2.setModal(False)
# progress1.show
self.temp2=os.path.join(Project().other_path,'temp2.tif')
t1=GdalPreviewImage(self.path2,self.temp2,1024,self)
# t1.started.connect(progress1.show)
t1.finished.connect(self.loadfile2)
t1.finished.connect(lambda :progress2.setlabel('创建影像金字塔..'))
t2=build_pyramids_overviews(self.path2,self)
t2.finished.connect(progress2.hide)
t1.start()
t1.finished.connect(t2.start)
progress2.show()
else:
progress2=progressDialog(self,'加载时相二')
progress2.setModal(False)
self.temp2=os.path.join(Project().other_path,'temp2.tif')
t1=GdalPreviewImage(self.path2,self.temp2,1024)
# t1.started.connect(progress1.show)
t1.finished.connect(self.loadfile2)
t1.finished.connect(progress2.hide)
t1.start()
progress2.show()
def loadfile2(self):
try:
self.right_layer=MultiBandRasterLayer(path=self.temp2)
self.mapcanva2.setLayers([self.right_layer.layer])
self.mapcanva2.zoomToFeatureExtent(self.right_layer.layer.extent())
self.open2.setEnabled(True)
except:
return
def ok(self):
self.bandsorder1=[int(q.text()) for q in self.style1_inputs ]
self.style1={'r':self.bandsorder1[0],'g':self.bandsorder1[1],'b':self.bandsorder1[2],'NIR':self.bandsorder1[3]}
@ -161,6 +264,9 @@ class loader(QDialog):
def cancel(self):
self.reject()
def open_alg(self,path):
pass
def set_style1(self):
self.bandsorder1=[int(q.text()) for q in self.style1_inputs ]
self.style1={'r':self.bandsorder1[0],'g':self.bandsorder1[1],'b':self.bandsorder1[2],'NIR':self.bandsorder1[3]}
@ -169,4 +275,90 @@ class loader(QDialog):
def set_style2(self):
self.bandsorder2=[int(q.text()) for q in self.style2_inputs ]
self.style2={'r':self.bandsorder2[0],'g':self.bandsorder2[1],'b':self.bandsorder2[2],'NIR':self.bandsorder2[3]}
self.right_layer.set_stlye(self.style2)
self.right_layer.set_stlye(self.style2)
class GdalPreviewImage(QThread):
def __init__(self,srcFile,tarFilename,width=1024.0,parent=None) -> None:
super(GdalPreviewImage,self).__init__(parent)
self.srcFile=srcFile
self.tarFilename=tarFilename
self.width=width
def run(self):
try:
srcFile=self.srcFile
tarFilename=self.tarFilename
width=self.width
p=tarFilename
dataset = gdal.Open(srcFile, gdal.GA_ReadOnly)
srcProjection = dataset.GetProjection()
srcGeoTransform = dataset.GetGeoTransform()
srcWidth = dataset.RasterXSize
srcHeight = dataset.RasterYSize
srcBandCount = dataset.RasterCount
# srcNoDatas = [
# dataset.GetRasterBand(bandIndex).GetNoDataValue()
# for bandIndex in range(1, srcBandCount+1)
# ]
# print(srcNoDatas)
srcBandDataType = dataset.GetRasterBand(1).DataType
# 创建重采样后的栅格
outFilePath = p
resampleFactor=width/srcWidth
driver = gdal.GetDriverByName('GTiff')
outWidth = int(srcWidth * resampleFactor)
outHeight = int(srcHeight * resampleFactor)
outDataset = driver.Create(
outFilePath,
outWidth,
outHeight,
srcBandCount,
srcBandDataType
)
print(outDataset)
geoTransforms = list(srcGeoTransform)
geoTransforms[1] = geoTransforms[1]/resampleFactor
geoTransforms[5] = geoTransforms[5]/resampleFactor
outGeoTransform = tuple(geoTransforms)
outDataset.SetGeoTransform(outGeoTransform)
outDataset.SetProjection(srcProjection)
# for bandIndex in range(1, srcBandCount+1):
# band = outDataset.GetRasterBand(bandIndex)
# band.SetNoDataValue(srcNoDatas[bandIndex-1])
gdal.ReprojectImage(
dataset,
outDataset,
srcProjection,
srcProjection,
gdal.gdalconst.GRA_NearestNeighbour,
0.0, 0.0,
)
del outDataset
except:
pass
# return outFilePath
class build_pyramids_overviews(QThread):
def __init__(self,filename,parent=None) -> None:
super(build_pyramids_overviews,self).__init__(parent)
self.filename=filename
def run(self):
try:
filename=self.filename
image:gdal.Dataset = gdal.Open(filename, 0)
# 如果第二个参数设置为0则金字塔文件建立在外面
# 如果第二个参数缺省或者为1则金字塔文件建立在文件内
gdal.SetConfigOption('COMPRESS_OVERVIEW', 'DEFLATE')
ov_list = [2, 4,6, 8, 12,16,24, 32, 48,64,96,128]
image.BuildOverviews("NEAREST", len(ov_list),overviewlist=ov_list)
del image
except:
pass
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = progressDialog()
w.show()
sys.exit(app.exec_())

210
rscder/gui/progress_bar.py Normal file
View File

@ -0,0 +1,210 @@
"""
Created on 2018年9月日
@author: Irony
@site: https://pyqt.site , https://github.com/PyQt5
@email: 892768447@qq.com
@file: MetroCircleProgress
@description:
"""
try:
from PyQt5.QtCore import QSequentialAnimationGroup, QPauseAnimation, QPropertyAnimation, \
QParallelAnimationGroup, QObject, QSize, Qt, QRectF, pyqtSignal, pyqtProperty
from PyQt5.QtGui import QPainter, QColor
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout,QDialog,QHBoxLayout,QLabel,QSpacerItem
except ImportError:
from PySide2.QtCore import QSequentialAnimationGroup, QPauseAnimation, QPropertyAnimation, \
QParallelAnimationGroup, QObject, QSize, Qt, QRectF, Signal as pyqtSignal, Property as pyqtProperty
from PySide2.QtGui import QPainter, QColor
from PySide2.QtWidgets import QApplication, QWidget, QVBoxLayout
class CircleItem(QObject):
X = 0 # x坐标
Opacity = 1 # 透明度0~1
valueChanged = pyqtSignal()
@pyqtProperty(float)
def x(self) -> float:
return self.X
@x.setter
def x(self, x: float):
self.X = x
self.valueChanged.emit()
@pyqtProperty(float)
def opacity(self) -> float:
return self.Opacity
@opacity.setter
def opacity(self, opacity: float):
self.Opacity = opacity
def qBound(miv, cv, mxv):
return max(min(cv, mxv), miv)
class MetroCircleProgress(QWidget):
Radius = 5 # 半径
Color = QColor(24, 189, 155) # 圆圈颜色
BackgroundColor = QColor(Qt.transparent) # 背景颜色
def __init__(self, *args, radius=5, color=QColor(24, 189, 155),
backgroundColor=QColor(Qt.transparent), **kwargs):
super(MetroCircleProgress, self).__init__(*args, **kwargs)
self.Radius = radius
self.Color = color
self.BackgroundColor = backgroundColor
self._items = []
self._initAnimations()
@pyqtProperty(int)
def radius(self) -> int:
return self.Radius
@radius.setter
def radius(self, radius: int):
if self.Radius != radius:
self.Radius = radius
self.update()
@pyqtProperty(QColor)
def color(self) -> QColor:
return self.Color
@color.setter
def color(self, color: QColor):
if self.Color != color:
self.Color = color
self.update()
@pyqtProperty(QColor)
def backgroundColor(self) -> QColor:
return self.BackgroundColor
@backgroundColor.setter
def backgroundColor(self, backgroundColor: QColor):
if self.BackgroundColor != backgroundColor:
self.BackgroundColor = backgroundColor
self.update()
def paintEvent(self, event):
super(MetroCircleProgress, self).paintEvent(event)
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.fillRect(self.rect(), self.BackgroundColor)
painter.setPen(Qt.NoPen)
for item, _ in self._items:
painter.save()
color = self.Color.toRgb()
color.setAlphaF(item.opacity)
painter.setBrush(color)
# 5<= radius <=10
radius = qBound(self.Radius, self.Radius / 200 *
self.height(), 2 * self.Radius)
diameter = 2 * radius
painter.drawRoundedRect(
QRectF(
item.x / 100 * self.width() - diameter,
(self.height() - radius) / 2,
diameter, diameter
), radius, radius)
painter.restore()
def _initAnimations(self):
for index in range(5): # 5个小圆
item = CircleItem(self)
item.valueChanged.connect(self.update)
# 串行动画组
seqAnimation = QSequentialAnimationGroup(self)
seqAnimation.setLoopCount(-1)
self._items.append((item, seqAnimation))
# 暂停延迟动画
seqAnimation.addAnimation(QPauseAnimation(150 * index, self))
# 加速,并行动画组1
parAnimation1 = QParallelAnimationGroup(self)
# 透明度
parAnimation1.addAnimation(QPropertyAnimation(
item, b'opacity', self, duration=400, startValue=0, endValue=1.0))
# x坐标
parAnimation1.addAnimation(QPropertyAnimation(
item, b'x', self, duration=400, startValue=0, endValue=25.0))
seqAnimation.addAnimation(parAnimation1)
##
# 匀速
seqAnimation.addAnimation(QPropertyAnimation(
item, b'x', self, duration=2000, startValue=25.0, endValue=75.0))
# 加速,并行动画组2
parAnimation2 = QParallelAnimationGroup(self)
# 透明度
parAnimation2.addAnimation(QPropertyAnimation(
item, b'opacity', self, duration=400, startValue=1.0, endValue=0))
# x坐标
parAnimation2.addAnimation(QPropertyAnimation(
item, b'x', self, duration=400, startValue=75.0, endValue=100.0))
seqAnimation.addAnimation(parAnimation2)
##
# 暂停延迟动画
seqAnimation.addAnimation(
QPauseAnimation((5 - index - 1) * 150, self))
for _, animation in self._items:
animation.start()
def sizeHint(self):
return QSize(100, self.Radius * 2)
class Window(QWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.resize(800, 600)
layout = QVBoxLayout(self, spacing=0)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(MetroCircleProgress(self))
layout.addWidget(MetroCircleProgress(self, radius=10))
layout.addWidget(MetroCircleProgress(self, styleSheet="""
qproperty-color: rgb(255, 0, 0);
"""))
layout.addWidget(MetroCircleProgress(self, styleSheet="""
qproperty-color: rgb(0, 0, 255);
qproperty-backgroundColor: rgba(180, 180, 180, 180);
"""))
class progressDialog(QDialog):
def __init__(self, parent=None,name='default') -> None:
super().__init__(parent)
self.setWindowTitle(name)
self.setFixedSize(300,80)
# self.setWindowIcon(IconInstance().RASTER)
tlayout=QVBoxLayout()
tlayout.setContentsMargins(10,0,0,0)
hlayout=QHBoxLayout()
h2layout=QHBoxLayout()
self.label=QLabel('加载影像...')
hlayout.addWidget(self.label)
hlayout.addItem(QSpacerItem(30,0))
tlayout.addLayout(hlayout)
h2layout.addWidget(MetroCircleProgress(self, radius=7))
tlayout.addLayout(h2layout)
self.setLayout(tlayout)
def setlabel(self,content:str):
self.label.setText(content)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = progressDialog()
w.show()
sys.exit(app.exec_())

View File

@ -102,7 +102,7 @@ class Create(QDialog):
main_layout.addLayout(button_layout)
self.setLayout(main_layout)
def open_file(self):
file = QFileDialog.getExistingDirectory(self, '选择文件夹', self.file)