一、Pycharm配置PyQt5。
配置方法件上一篇文章。
二、打开Qt Designer添加所需的控件。
这里创建的是MainWindow,添加的控件如上图,这里可以给添加的按钮修改名字,以便后续调用。点击保存并重新命名项目就会出现如下的.ui文件
三、右键生成的.ui文件,点击Qt里面的PyUIC生成相应的.py文件
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(50, 100, 231, 191))
self.label.setStyleSheet("background-color: rgb(255, 255, 255);")
self.label.setObjectName("label")
self.handlePictureBtn = QtWidgets.QPushButton(self.centralwidget)
self.handlePictureBtn.setGeometry(QtCore.QRect(460, 110, 112, 34))
self.handlePictureBtn.setObjectName("handlePictureBtn")
self.recogBtn = QtWidgets.QPushButton(self.centralwidget)
self.recogBtn.setGeometry(QtCore.QRect(460, 260, 112, 34))
self.recogBtn.setObjectName("recogBtn")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(390, 350, 251, 131))
self.textEdit.setObjectName("textEdit")
self.loadPictureBtn = QtWidgets.QPushButton(self.centralwidget)
self.loadPictureBtn.setGeometry(QtCore.QRect(110, 310, 112, 34))
self.loadPictureBtn.setObjectName("loadPictureBtn")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 30))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", " 图片"))
self.handlePictureBtn.setText(_translate("MainWindow", "处理图片"))
self.recogBtn.setText(_translate("MainWindow", "开始识别"))
self.loadPictureBtn.setText(_translate("MainWindow", "加载图片"))
文件中的代码如上所示,这是ui设计的代码,关于每个控件的逻辑实现的建议新建一个.py文件。
四、新建.py文件编写每个控件的逻辑实现。
这里我新建了一个recognition.py文件。
首先应保存好训练好的模型,这里就可以加载,我使用的是LinearSVC模型。
模型的保存和加载可以使用pickle。
为了显示图片,需要一个没有任何图片转换的数据集。
为了后续图像的识别任务,还需要一个实现了图片转换的数据集,除此以外为了得到符合模型识别的输入,需要将测试图像通过一遍已经训练好的网络,这里卷积层的参数可以直接调用保存的参数数据。
conv层参数的保存可以使用:torch.save(conv.state_dict(), "conv.parameter")
conv层参数的调用可以使用:conv.load_state_dict(torch.load("conv.parameter"))
最后可以使用模型预测图像类别,并在textEdit中显示出来。
import sys
import torch
from PyQt5.QtGui import QPixmap
from torchvision.datasets import ImageFolder
from SpykeTorch import snn, utils
from mainWindow import Ui_MainWindow
from PyQt5.QtWidgets import *
import pickle
import cv2
import dill
import random
import torchvision.transforms as transforms
import SpykeTorch.functional as sf
import numpy as np
# 图片转换
kernels = [ utils.GaborKernel(window_size = 3, orientation = 45+22.5),
utils.GaborKernel(3, 90+22.5),
utils.GaborKernel(3, 135+22.5),
utils.GaborKernel(3, 180+22.5)]
filter = utils.Filter(kernels, use_abs = True)
def time_dim(input):
return input.unsqueeze(0)
transform = transforms.Compose(
[transforms.Grayscale(),
transforms.ToTensor(),
time_dim,
filter,
sf.pointwise_inhibition,
utils.Intensity2Latency(number_of_spike_bins = 15, to_spike = True)])
# 显示图片
dataset = ImageFolder("dataset/eth")
# 处理图片
dataset_transfrom = ImageFolder("dataset/eth", transform)
class recognition(Ui_MainWindow, QMainWindow):
def __init__(self, parent=None):
super(recognition, self).__init__(parent)
self.setupUi(self)
# 槽函数
self.loadPictureBtn.clicked.connect(self.loadPicture)
self.handlePictureBtn.clicked.connect(self.handlePicture)
self.recogBtn.clicked.connect(self.showResult)
# 加载模型
self.clf_spike = pickle.load(open("clf_spike_model", "rb"))
self.clf_pot = pickle.load(open("clf_pot_model", "rb"))
def loadPicture(self):
# 随机选取数据集中的一张图片识别
self.sample_idx = random.randint(0, len(dataset) - 1)
self.label.setPixmap(QPixmap(dataset.imgs[self.sample_idx][0]))
# 图片大小与label适应,否则图片可能显示不全
self.label.setScaledContents(True)
def handlePicture(self):
# 处理测试图片
pool = snn.Pooling(kernel_size=3, stride=2)
conv = snn.Convolution(in_channels=4, out_channels=20, kernel_size=30)
conv.load_state_dict(torch.load("conv.parameter"))
x = dataset_transfrom[self.sample_idx][0]
t = dataset_transfrom[self.sample_idx][1]
x = pool(x)
p = conv(x)
o = sf.fire(p, 20)
self.test_x_spike = np.array(o.reshape(-1).cpu().numpy()).reshape(1,-1)
self.test_x_pot = np.array(p.reshape(-1).cpu().numpy()).reshape(1,-1)
self.test_y = t
self.textEdit.setText("测试图片处理完毕")
def showResult(self):
predict_spike = self.clf_spike.predict(self.test_x_spike)
predict_pot = self.clf_pot.predict(self.test_x_pot)
if predict_spike[0] == 0:
self.textEdit.append("利用脉冲信息的预测结果为:杯子")
else:
self.textEdit.append("利用脉冲信息的预测结果为:狗")
if predict_pot[0] == 0:
self.textEdit.append("利用电位信息的预测结果为:杯子")
else:
self.textEdit.append("利用电位信息的预测结果为:狗")
if self.test_y == 0:
self.textEdit.append("该图像的标签为:杯子")
else:
self.textEdit.append("该图像的标签为:狗")
if __name__ == '__main__':
app = QApplication(sys.argv)
recog = recognition()
recog.show()
sys.exit(app.exec_())