0%

PyQt 打造的图像预览软件

寒假某天下午的突发奇想,想实现一款图像预览软件。大概思路是:在软件的左侧点击图片,软件的右侧就能实时预览图片,因为感觉这个功能有一定的应用场景,所以实现了一下。

简单说一下设计思路吧,代码没啥难度:

  1. 使用 GridLayout 手动布局提升美感,左侧是文件列表,右侧是图片预览
  2. 当从左侧文件列表点击文件时,判断点击的文件是否为图像类型,如果是,右侧显示图像。关于如何显示高清图像,可以参考我之前的博客
  3. 文件列表使用 QTreeViewQListView 实现,QTreeView 负责显示文件夹层级关系,QListView 负责显示文件。两者都挂载文件模型。
  4. Qt 的使用就是学会基础操作后大量翻阅官方库的过程。

可以看到里面还有加载模型、识别等按钮,也能猜出来这是深度学习应用的软件。

程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import sys, time
from PyQt5.QtWidgets import (QMainWindow, QWidget, QGridLayout, QApplication,
QPushButton, QStatusBar, QProgressBar, QLabel,
QTreeView, QListView, QFileSystemModel, QLineEdit,
QInputDialog, QFileDialog, QTextEdit, QMessageBox)
from PyQt5.QtCore import QDir
import os
from PyQt5.QtGui import QPixmap, QFont
from PyQt5.Qt import QSize, QImageReader
import qdarkstyle


class SecondWindow(QWidget):

def __init__(self, msg):
super(SecondWindow, self).__init__()
self.resize(400, 400)
self.move(200, 200)

layout = QGridLayout()
self.info = QTextEdit()
layout.addWidget(self.info)
self.info.setText(msg)
self.setLayout(layout)
self.setWindowTitle('详细信息')


class mainwindow(QMainWindow):

def __init__(self):
super(mainwindow, self).__init__()

self.setWindowTitle("天然草地类型识别系统")

# 显示正在加载
self.status = QStatusBar()
self.status.setStyleSheet('QStatusBar::item {border: none;}')
self.setStatusBar(self.status)

self.progressBar = QProgressBar()
self.label = QLabel()
self.label.setText("加载中,请稍后... ")
self.status.addPermanentWidget(self.label, stretch=2)
self.status.addPermanentWidget(self.progressBar, stretch=4)
self.progressBar.setRange(0, 100)
self.progressBar.setMinimum(0)
self.progressBar.setMaximum(0)
self.statusBar().setVisible(False)

self.setMinimumSize(1500, 720)

layout = QGridLayout()
w = QWidget()
w.setLayout(layout)
self.setCentralWidget(w)

# 文件树
self.treeview = QTreeView()
self.listview = QListView()
layout.addWidget(self.treeview, 0, 0, 7, 2)
layout.addWidget(self.listview, 0, 2, 7, 2)

path = QDir.rootPath()

self.dirModel = QFileSystemModel()
self.dirModel.setRootPath(QDir.rootPath())
self.dirModel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)

self.fileModel = QFileSystemModel()
self.fileModel.setFilter(QDir.NoDotAndDotDot | QDir.Files)

self.treeview.setModel(self.dirModel)
self.listview.setModel(self.fileModel)

self.treeview.setRootIndex(self.dirModel.index(path))
self.listview.setRootIndex(self.fileModel.index(path))

self.treeview.clicked.connect(self.on_clicked)
self.listview.clicked.connect(self.run_model)

self.treeview.hideColumn(1)
self.treeview.hideColumn(2)
self.treeview.hideColumn(3)

# 显示图片
self.image_label = QLabel()
self.image_label.setMinimumSize(800, 700)
layout.addWidget(self.image_label, 0, 4, 5, 10)

# 加载模型
btn = QPushButton("加载模型")
layout.addWidget(btn, 7, 0, 1, 2)
btn.clicked.connect(self.load_model)

more_btn = QPushButton("详细信息")
layout.addWidget(more_btn, 7, 14, 1, 1)
more_btn.clicked.connect(self.show_info)

reco_btn = QPushButton("识别")
layout.addWidget(reco_btn, 7, 2, 1, 1)
reco_btn.clicked.connect(self.predict)

clear_btn = QPushButton("清空")
layout.addWidget(clear_btn, 7, 3, 1, 1)
clear_btn.clicked.connect(self.clear)

# 预测结果
self.res = QLineEdit()
self.res.setReadOnly(True)
layout.addWidget(self.res, 7, 4, 1, 10)

self.model = None
self.fname = None

def clear(self):
self.res.clear()
self.image_label.setVisible(False)

def show_info(self):
if self.fname is not None:
# 调用你的图片信息代码,我这里没对应的 excel
# 详细信息赋值给 msg 即可
msg = "详细信息"
self.child = SecondWindow(msg)
self.child.show()

# 当选中图片的时候,直接进行预测
def run_model(self):
self.image_label.setVisible(True)
idx = self.listview.currentIndex()
fname = self.fileModel.filePath(idx)
img_type = fname.split('.')[-1]
# 判断下是不是图片
if img_type in ["png", "jpg"]:
img = QImageReader(fname)
scale = self.image_label.width() / img.size().width()
height = int(img.size().height() * scale)
img.setScaledSize(QSize(self.image_label.width(), height))
img = img.read()
pixmap = QPixmap(img)
self.image_label.setPixmap(pixmap)
self.fname = fname

# 测试代码放在这里
def predict(self):
if self.fname is not None:
# y = self.model(x)
# y = str(y)
self.res.setText("cls 1: 0.9, cls 2: 0.8, cls 3: 0.9")
# res = self.model(img)
# self.res.setText(res)
else:
msgBox = QMessageBox()
msgBox.setIcon(QMessageBox.Warning)
msgBox.warning(self, "警告", "请选择图片后再预测")

def on_clicked(self, index):
path = self.dirModel.fileInfo(index).absoluteFilePath()
self.listview.setRootIndex(self.fileModel.setRootPath(path))

# 加载模型的代码
def load_model(self):
self.status.setVisible(True)
file_filter = 'PKL File (*.pt *.pth *.pkl)'
response = QFileDialog.getOpenFileName(
parent=self,
caption='Select a data file',
directory=os.getcwd(),
filter=file_filter,
)
pth_file, _ = response
# torch load model
# self.model.load_state_dict(torch.load(pth_file))
self.status.setVisible(False)


if __name__ == '__main__':
app = QApplication([])
dark_stylesheet = qdarkstyle.load_stylesheet_pyqt5()
# 如果想美化就取消注释
# app.setStyleSheet(dark_stylesheet)
m = mainwindow()
m.show()
sys.exit(app.exec())
感谢上学期间打赏我的朋友们。赛博乞讨:我,秦始皇,打钱。

欢迎订阅我的文章