pyqt 搭建深度学习训练界面(二)

news2024/11/23 8:25:05

炼丹软件
在这里插入图片描述

github链接:

有需要联系我

requirements:

测试在ubuntu18.04和Windows均可运行

ubuntu18.04

OS: Ubuntu 18.04.6 LTS
Python version: 3.7 (64-bit runtime)
Is CUDA available: True
CUDA runtime version: 11.1.74
GPU models and configuration: GPU 0: NVIDIA GeForce RTX 3090 Ti
Nvidia driver version: 510.108.03

安装可能存在的问题:

No module named ‘kornia’

pip install kornia==0.5

注: 不带版本号会默认下载新的torch

No module named ‘PyQt5.QtChart’
需单独安装

popip install pyqtchart

ModuleNotFoundError: No module named ‘qt_material’

ModuleNotFoundError: No module named ‘jinja2’

pip install jinja2

主函数

if __name__ == '__main__':
    # multiprocessing.freeze_support()
    # initialize QApplication
    app = QApplication(sys.argv)
    # set style
    app.setStyleSheet(StyleSheet)
    # set the launch 
    global splash
    splash = GifSplashScreen()
    splash.show()

    m_window = MainCode()
    apply_stylesheet(app, theme='dark_blue.xml') #, invert_secondary=True)
    m_window.show()
    sys.exit(app.exec_())

启动界面

通常在主界面加载完成之前提供一个启动界面,减少主程序加载过程用户的等待

# 启动界面
class GifSplashScreen(QSplashScreen):
    def __init__(self, *args, **kwargs):
        super(GifSplashScreen, self).__init__(*args, **kwargs)
        self.movie = QMovie('./Lib/splash.gif')
        self.movie.frameChanged.connect(self.onFrameChanged)
        self.movie.start()

    def onFrameChanged(self, _):
        self.setPixmap(self.movie.currentPixmap())

    def finish(self, widget):
        self.movie.stop()
        super(GifSplashScreen, self).finish(widget)

主界面设计

利用QtDesigner来设计界面,通过Pycharm外部工具PyUIC转化成py文件


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1000, 800)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("./icon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.toolBox = QtWidgets.QToolBox(self.centralwidget)
        self.toolBox.setMaximumSize(QtCore.QSize(200, 16777215))
        self.toolBox.setObjectName("toolBox")
        self.m_First = QtWidgets.QWidget()
        self.m_First.setGeometry(QtCore.QRect(0, 0, 200, 597))
        self.m_First.setObjectName("m_First")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.m_First)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.m_ImageDirBtn = QtWidgets.QPushButton(self.m_First)
        self.m_ImageDirBtn.setObjectName("m_ImageDirBtn")
        self.horizontalLayout_2.addWidget(self.m_ImageDirBtn)
        self.toolBox.addItem(self.m_First, "")
        self.m_Second = QtWidgets.QWidget()
        self.m_Second.setGeometry(QtCore.QRect(0, 0, 200, 597))
        self.m_Second.setObjectName("m_Second")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.m_Second)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.m_SetTrainPareBtn = QtWidgets.QPushButton(self.m_Second)
        self.m_SetTrainPareBtn.setObjectName("m_SetTrainPareBtn")
        self.horizontalLayout_3.addWidget(self.m_SetTrainPareBtn)
        self.toolBox.addItem(self.m_Second, "")
        self.m_Third = QtWidgets.QWidget()
        self.m_Third.setGeometry(QtCore.QRect(0, 0, 200, 597))
        self.m_Third.setObjectName("m_Third")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.m_Third)
        self.verticalLayout.setObjectName("verticalLayout")
        self.m_StartTrainBtn = QtWidgets.QPushButton(self.m_Third)
        self.m_StartTrainBtn.setObjectName("m_StartTrainBtn")
        self.verticalLayout.addWidget(self.m_StartTrainBtn)
        self.toolBox.addItem(self.m_Third, "")
        self.m_Forth = QtWidgets.QWidget()
        self.m_Forth.setGeometry(QtCore.QRect(0, 0, 200, 597))
        self.m_Forth.setObjectName("m_Forth")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.m_Forth)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.m_DetectSinglePicBtn = QtWidgets.QPushButton(self.m_Forth)
        self.m_DetectSinglePicBtn.setObjectName("m_DetectSinglePicBtn")
        self.verticalLayout_2.addWidget(self.m_DetectSinglePicBtn)
        self.toolBox.addItem(self.m_Forth, "")
        self.m_fifth = QtWidgets.QWidget()
        self.m_fifth.setObjectName("m_fifth")
        self.m_convertModel = QtWidgets.QPushButton(self.m_fifth)
        self.m_convertModel.setGeometry(QtCore.QRect(50, 180, 75, 23))
        self.m_convertModel.setObjectName("m_convertModel")
        self.toolBox.addItem(self.m_fifth, "")
        self.horizontalLayout.addWidget(self.toolBox)
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setObjectName("tabWidget")
        self.home_page = QtWidgets.QWidget()
        self.home_page.setObjectName("home_page")
        self.gridLayout_8 = QtWidgets.QGridLayout(self.home_page)
        self.gridLayout_8.setObjectName("gridLayout_8")
        self.m_homePagelabel = QtWidgets.QLabel(self.home_page)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.m_homePagelabel.sizePolicy().hasHeightForWidth())
        self.m_homePagelabel.setSizePolicy(sizePolicy)
        self.m_homePagelabel.setObjectName("m_homePagelabel")
        self.gridLayout_8.addWidget(self.m_homePagelabel, 0, 0, 1, 1)
        self.tabWidget.addTab(self.home_page, "")
        self.m_FirstW = QtWidgets.QWidget()
        self.m_FirstW.setObjectName("m_FirstW")
        self.gridLayout = QtWidgets.QGridLayout(self.m_FirstW)
        self.gridLayout.setObjectName("gridLayout")
        self.le_imageDir = QtWidgets.QLineEdit(self.m_FirstW)
        self.le_imageDir.setObjectName("le_imageDir")
        self.gridLayout.addWidget(self.le_imageDir, 0, 0, 1, 1)
        self.tableImgList = QtWidgets.QTableWidget(self.m_FirstW)
        self.tableImgList.setMaximumSize(QtCore.QSize(300, 16777215))
        self.tableImgList.setObjectName("tableImgList")
        self.tableImgList.setColumnCount(0)
        self.tableImgList.setRowCount(0)
        self.gridLayout.addWidget(self.tableImgList, 1, 1, 1, 1)
        self.la_image = QtWidgets.QLabel(self.m_FirstW)
        self.la_image.setObjectName("la_image")
        self.gridLayout.addWidget(self.la_image, 1, 0, 1, 1)
        self.tabWidget.addTab(self.m_FirstW, "")
        self.m_SecondW = QtWidgets.QWidget()
        self.m_SecondW.setObjectName("m_SecondW")
        self.gridLayout_5 = QtWidgets.QGridLayout(self.m_SecondW)
        self.gridLayout_5.setObjectName("gridLayout_5")
        self.m_MaxIterationL = QtWidgets.QLabel(self.m_SecondW)
        self.m_MaxIterationL.setObjectName("m_MaxIterationL")
        self.gridLayout_5.addWidget(self.m_MaxIterationL, 0, 0, 1, 1)
        self.m_MaxIterationEd = QtWidgets.QLineEdit(self.m_SecondW)
        self.m_MaxIterationEd.setObjectName("m_MaxIterationEd")
        self.gridLayout_5.addWidget(self.m_MaxIterationEd, 0, 1, 1, 1)
        self.m_BathSizeL = QtWidgets.QLabel(self.m_SecondW)
        self.m_BathSizeL.setObjectName("m_BathSizeL")
        self.gridLayout_5.addWidget(self.m_BathSizeL, 1, 0, 1, 1)
        self.m_BathSizeEd = QtWidgets.QLineEdit(self.m_SecondW)
        self.m_BathSizeEd.setObjectName("m_BathSizeEd")
        self.gridLayout_5.addWidget(self.m_BathSizeEd, 1, 1, 1, 1)
        self.m_ImageSizeL = QtWidgets.QLabel(self.m_SecondW)
        self.m_ImageSizeL.setObjectName("m_ImageSizeL")
        self.gridLayout_5.addWidget(self.m_ImageSizeL, 2, 0, 1, 1)
        self.m_ImageSizeEd = QtWidgets.QLineEdit(self.m_SecondW)
        self.m_ImageSizeEd.setObjectName("m_ImageSizeEd")
        self.gridLayout_5.addWidget(self.m_ImageSizeEd, 2, 1, 1, 1)
        self.m_ValidationRatioL = QtWidgets.QLabel(self.m_SecondW)
        self.m_ValidationRatioL.setObjectName("m_ValidationRatioL")
        self.gridLayout_5.addWidget(self.m_ValidationRatioL, 3, 0, 1, 1)
        self.m_ValidationRatioEd = QtWidgets.QLineEdit(self.m_SecondW)
        self.m_ValidationRatioEd.setObjectName("m_ValidationRatioEd")
        self.gridLayout_5.addWidget(self.m_ValidationRatioEd, 3, 1, 1, 1)
        self.m_LearningRateL = QtWidgets.QLabel(self.m_SecondW)
        self.m_LearningRateL.setObjectName("m_LearningRateL")
        self.gridLayout_5.addWidget(self.m_LearningRateL, 4, 0, 1, 1)
        self.m_LearningRateEd = QtWidgets.QLineEdit(self.m_SecondW)
        self.m_LearningRateEd.setObjectName("m_LearningRateEd")
        self.gridLayout_5.addWidget(self.m_LearningRateEd, 4, 1, 1, 1)
        self.m_WeightDecayL = QtWidgets.QLabel(self.m_SecondW)
        self.m_WeightDecayL.setObjectName("m_WeightDecayL")
        self.gridLayout_5.addWidget(self.m_WeightDecayL, 5, 0, 1, 1)
        self.m_WeightDecayEd = QtWidgets.QLineEdit(self.m_SecondW)
        self.m_WeightDecayEd.setObjectName("m_WeightDecayEd")
        self.gridLayout_5.addWidget(self.m_WeightDecayEd, 5, 1, 1, 1)
        self.m_isCuda = QtWidgets.QCheckBox(self.m_SecondW)
        self.m_isCuda.setObjectName("m_isCuda")
        self.gridLayout_5.addWidget(self.m_isCuda, 6, 0, 1, 1)
        self.m_OkBtn = QtWidgets.QPushButton(self.m_SecondW)
        self.m_OkBtn.setObjectName("m_OkBtn")
        self.gridLayout_5.addWidget(self.m_OkBtn, 7, 1, 1, 1)
        self.tabWidget.addTab(self.m_SecondW, "")
        self.m_ThirdW = QtWidgets.QWidget()
        self.m_ThirdW.setObjectName("m_ThirdW")
        self.gridLayout_7 = QtWidgets.QGridLayout(self.m_ThirdW)
        self.gridLayout_7.setObjectName("gridLayout_7")
        self.m_trainwidget = QtWidgets.QWidget(self.m_ThirdW)
        self.m_trainwidget.setObjectName("m_trainwidget")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.m_trainwidget)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.m_initModelBtn = QtWidgets.QPushButton(self.m_trainwidget)
        self.m_initModelBtn.setObjectName("m_initModelBtn")
        self.gridLayout_2.addWidget(self.m_initModelBtn, 0, 0, 1, 1)
        self.m_startTrainBtn = QtWidgets.QPushButton(self.m_trainwidget)
        self.m_startTrainBtn.setObjectName("m_startTrainBtn")
        self.gridLayout_2.addWidget(self.m_startTrainBtn, 0, 1, 1, 1)
        self.m_pauseTrainBtn = QtWidgets.QPushButton(self.m_trainwidget)
        self.m_pauseTrainBtn.setObjectName("m_pauseTrainBtn")
        self.gridLayout_2.addWidget(self.m_pauseTrainBtn, 1, 0, 1, 1)
        self.m_resumTrainBtn = QtWidgets.QPushButton(self.m_trainwidget)
        self.m_resumTrainBtn.setObjectName("m_resumTrainBtn")
        self.gridLayout_2.addWidget(self.m_resumTrainBtn, 1, 1, 1, 1)
        self.m_stopTrainBtn = QtWidgets.QPushButton(self.m_trainwidget)
        self.m_stopTrainBtn.setObjectName("m_stopTrainBtn")
        self.gridLayout_2.addWidget(self.m_stopTrainBtn, 2, 0, 1, 1)
        self.gridLayout_7.addWidget(self.m_trainwidget, 0, 1, 1, 1)
        self.m_savemodelWidget = QtWidgets.QWidget(self.m_ThirdW)
        self.m_savemodelWidget.setMinimumSize(QtCore.QSize(0, 100))
        self.m_savemodelWidget.setMaximumSize(QtCore.QSize(16777215, 100))
        self.m_savemodelWidget.setObjectName("m_savemodelWidget")
        self.gridLayout_3 = QtWidgets.QGridLayout(self.m_savemodelWidget)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.m_modelSaveEd = QtWidgets.QLineEdit(self.m_savemodelWidget)
        self.m_modelSaveEd.setObjectName("m_modelSaveEd")
        self.gridLayout_3.addWidget(self.m_modelSaveEd, 0, 1, 1, 1)
        self.m_modelSaveBtn = QtWidgets.QPushButton(self.m_savemodelWidget)
        self.m_modelSaveBtn.setObjectName("m_modelSaveBtn")
        self.gridLayout_3.addWidget(self.m_modelSaveBtn, 0, 3, 1, 1)
        self.m_modelSaveL = QtWidgets.QLabel(self.m_savemodelWidget)
        self.m_modelSaveL.setObjectName("m_modelSaveL")
        self.gridLayout_3.addWidget(self.m_modelSaveL, 0, 0, 1, 1)
        self.gridLayout_7.addWidget(self.m_savemodelWidget, 0, 0, 1, 1)
        self.m_modelTrainProcesssbar = QtWidgets.QProgressBar(self.m_ThirdW)
        self.m_modelTrainProcesssbar.setProperty("value", 24)
        self.m_modelTrainProcesssbar.setObjectName("m_modelTrainProcesssbar")
        self.gridLayout_7.addWidget(self.m_modelTrainProcesssbar, 1, 0, 1, 2)
        self.textBrowser = QtWidgets.QTextBrowser(self.m_ThirdW)
        self.textBrowser.setObjectName("textBrowser")
        self.gridLayout_7.addWidget(self.textBrowser, 3, 0, 1, 2)
        self.tabWidget.addTab(self.m_ThirdW, "")
        self.m_ForthW = QtWidgets.QWidget()
        self.m_ForthW.setObjectName("m_ForthW")
        self.gridLayout_6 = QtWidgets.QGridLayout(self.m_ForthW)
        self.gridLayout_6.setObjectName("gridLayout_6")
        self.m_loadmodelwidget = QtWidgets.QWidget(self.m_ForthW)
        self.m_loadmodelwidget.setMinimumSize(QtCore.QSize(0, 50))
        self.m_loadmodelwidget.setMaximumSize(QtCore.QSize(16777215, 50))
        self.m_loadmodelwidget.setObjectName("m_loadmodelwidget")
        self.gridLayout_4 = QtWidgets.QGridLayout(self.m_loadmodelwidget)
        self.gridLayout_4.setObjectName("gridLayout_4")
        self.m_loadmodelBtn = QtWidgets.QPushButton(self.m_loadmodelwidget)
        self.m_loadmodelBtn.setObjectName("m_loadmodelBtn")
        self.gridLayout_4.addWidget(self.m_loadmodelBtn, 0, 0, 1, 1)
        self.m_loadmodelEd = QtWidgets.QLineEdit(self.m_loadmodelwidget)
        self.m_loadmodelEd.setObjectName("m_loadmodelEd")
        self.gridLayout_4.addWidget(self.m_loadmodelEd, 0, 1, 1, 1)
        self.gridLayout_6.addWidget(self.m_loadmodelwidget, 0, 0, 1, 1)
        self.la_result = QtWidgets.QLabel(self.m_ForthW)
        self.la_result.setObjectName("la_result")
        self.gridLayout_6.addWidget(self.la_result, 1, 0, 1, 1)
        self.tabWidget.addTab(self.m_ForthW, "")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.gridLayout_9 = QtWidgets.QGridLayout(self.tab)
        self.gridLayout_9.setObjectName("gridLayout_9")
        self.m_choosemodelEd = QtWidgets.QLineEdit(self.tab)
        self.m_choosemodelEd.setObjectName("m_choosemodelEd")
        self.gridLayout_9.addWidget(self.m_choosemodelEd, 0, 0, 1, 1)
        self.m_choosemodelBtn = QtWidgets.QPushButton(self.tab)
        self.m_choosemodelBtn.setObjectName("m_choosemodelBtn")
        self.gridLayout_9.addWidget(self.m_choosemodelBtn, 1, 0, 1, 1)
        self.m_starttransformBtn = QtWidgets.QPushButton(self.tab)
        self.m_starttransformBtn.setObjectName("m_starttransformBtn")
        self.gridLayout_9.addWidget(self.m_starttransformBtn, 2, 0, 1, 1)
        self.tabWidget.addTab(self.tab, "")
        self.horizontalLayout.addWidget(self.tabWidget)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1000, 22))
        self.menubar.setObjectName("menubar")
        self.openmenu = QtWidgets.QMenu(self.menubar)
        self.openmenu.setObjectName("openmenu")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.toolBar = QtWidgets.QToolBar(MainWindow)
        self.toolBar.setObjectName("toolBar")
        MainWindow.addToolBar(QtCore.Qt.BottomToolBarArea, self.toolBar)
        self.menubar.addAction(self.openmenu.menuAction())

        self.retranslateUi(MainWindow)
        self.toolBox.setCurrentIndex(4)
        self.tabWidget.setCurrentIndex(5)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "训练界面"))
        self.m_ImageDirBtn.setText(_translate("MainWindow", "选择图像路径"))
        self.toolBox.setItemText(self.toolBox.indexOf(self.m_First), _translate("MainWindow", "第一步"))
        self.m_SetTrainPareBtn.setText(_translate("MainWindow", "设置训练参数"))
        self.toolBox.setItemText(self.toolBox.indexOf(self.m_Second), _translate("MainWindow", "第二步"))
        self.m_StartTrainBtn.setText(_translate("MainWindow", "开始训练"))
        self.toolBox.setItemText(self.toolBox.indexOf(self.m_Third), _translate("MainWindow", "第三步"))
        self.m_DetectSinglePicBtn.setText(_translate("MainWindow", "检测图像"))
        self.toolBox.setItemText(self.toolBox.indexOf(self.m_Forth), _translate("MainWindow", "第四步"))
        self.m_convertModel.setText(_translate("MainWindow", "模型转换"))
        self.toolBox.setItemText(self.toolBox.indexOf(self.m_fifth), _translate("MainWindow", "第五步"))
        self.m_homePagelabel.setText(_translate("MainWindow", "TextLabel"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.home_page), _translate("MainWindow", "home"))
        self.la_image.setText(_translate("MainWindow", "TextLabel"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.m_FirstW), _translate("MainWindow", "第一步"))
        self.m_MaxIterationL.setText(_translate("MainWindow", "最大训练次数:"))
        self.m_BathSizeL.setText(_translate("MainWindow", "batch_size(批尺寸)"))
        self.m_ImageSizeL.setText(_translate("MainWindow", "图像尺寸"))
        self.m_ValidationRatioL.setText(_translate("MainWindow", "验证集比例"))
        self.m_LearningRateL.setText(_translate("MainWindow", "学习率"))
        self.m_WeightDecayL.setText(_translate("MainWindow", "权重衰减系数:"))
        self.m_isCuda.setText(_translate("MainWindow", "是否使用显卡训练"))
        self.m_OkBtn.setText(_translate("MainWindow", "OK"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.m_SecondW), _translate("MainWindow", "第二步"))
        self.m_initModelBtn.setText(_translate("MainWindow", "初始化"))
        self.m_startTrainBtn.setText(_translate("MainWindow", "开始训练"))
        self.m_pauseTrainBtn.setText(_translate("MainWindow", "暂停训练"))
        self.m_resumTrainBtn.setText(_translate("MainWindow", "继续训练"))
        self.m_stopTrainBtn.setText(_translate("MainWindow", "停止训练"))
        self.m_modelSaveBtn.setText(_translate("MainWindow", "选择路径"))
        self.m_modelSaveL.setText(_translate("MainWindow", "模型保存位置:"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.m_ThirdW), _translate("MainWindow", "第三步"))
        self.m_loadmodelBtn.setText(_translate("MainWindow", "加载模型:"))
        self.la_result.setText(_translate("MainWindow", "TextLabel"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.m_ForthW), _translate("MainWindow", "第四步"))
        self.m_choosemodelBtn.setText(_translate("MainWindow", "选择模型文件"))
        self.m_starttransformBtn.setText(_translate("MainWindow", "转换"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "第五步"))
        self.openmenu.setTitle(_translate("MainWindow", "打开"))
        self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))

训练参数类设置

class trainParameter():
    def __init__(self):
        self.epochs = 0
        self.batch_size = 0
        self.image_size = 0
        self.validation_ratio = 0
        self.lr = 0
        self.dw = 0
        self.Cuda = False
        self.kl_weights = 1.0
        self.l2_weights = 1.0
        self.gms_weights = 1.0
        self.ssim_weights = 1.0

多线程设置

class Thread(QThread):
    valueChange = pyqtSignal(int)
    textChange = pyqtSignal(int, str)
    def __init__(self, open_dir, train_parameters, save_dir):
        super(Thread, self).__init__()
        self._isPause = False
        self._isStop = False
        self._value = 0
        self.cond = QWaitCondition()
        self.mutex = QMutex()
        self.train = train_parameters
        self.open_dir = open_dir
        self.save_dir = save_dir
        self.xnet = XNet(self.open_dir, self.train, self.save_dir)

    def pause(self):
        self._isPause = True

    def stop(self):
        self._isStop = True

    def resume(self):
        self._isPause = False
        self.cond.wakeAll()

    def run(self):
        for epoch in range(1, self.train.epochs + 1):
            self.valueChange.emit(epoch)
            self.mutex.lock()  # 加锁
            if self._isPause:
                self.cond.wait(self.mutex)
            if self._isStop:
                return
            QApplication.processEvents()  # 实时刷新显示
            loss_avg = self.xnet.train_one_epoch()
            if np.isnan(loss_avg):
                loss_avg = 1e6

            # self.valueChanged.emit(loss_avg)



            print('Train Epoch: {} loss: {:.6f}'.format(epoch, loss_avg))
            self.textChange.emit(epoch, str(loss_avg))
            if epoch % 50 == 0:
                self.xnet.save_model(epoch)  # 保存权重
            self.mutex.unlock()

主界面功能

class MainCode(QMainWindow, Ui_MainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        for i in range(2):
            sleep(1)
            splash.showMessage('加载进度: %d' % i, Qt.AlignHCenter | Qt.AlignBottom, Qt.white)
            QApplication.instance().processEvents()

        splash.showMessage('初始化完成', Qt.AlignHCenter | Qt.AlignBottom, Qt.white)
        splash.finish(self)

        self.train = trainParameter()
        self.cwd = os.getcwd()  # return current workdir


        self.initUi()

背景图片展示

    def showHomepage(self):
        imgName = "./Lib/train.jpeg"
        # print(imgName)
        jpg = QPixmap(imgName).scaled(self.m_homePagelabel.width(), self.m_homePagelabel.height())
        # 显示原图
        self.m_homePagelabel.setPixmap(jpg)
        self.m_homePagelabel.setScaledContents(True)

右下角显示北京时间

   # 获取当前时间
    def showCurrentTime(self, timeLabel):
        # 获取系统当前时间
        time = QDateTime.currentDateTime()
        # 设置系统时间的显示格式
        timeDisplay = time.toString('yyyy-MM-dd hh:mm:ss dddd')
        timeLabel.setText(timeDisplay)

    # 状态栏显示时间
    def statusShowTime(self):
        self.timer = QTimer()
        self.timeLabel = QLabel()
        self.statusbar.addPermanentWidget(self.timeLabel, 0)
        self.timer.timeout.connect(lambda: self.showCurrentTime(self.timeLabel))  # 这个通过调用槽函数来刷新时间

        self.timer.start(1000)  # 每隔一秒刷新一次,这里设置为1000ms  即1s

选择图像路径并显示在列表中

   def openfiledir(self):
        openfile_dir = QFileDialog.getExistingDirectory(self.centralwidget, "选择路径", self.cwd)
        # print(openfile_dir)
        self.le_imageDir.setText(openfile_dir)
        # self.le_imageDir.setReadOnly()
        # 寻找路径下以*jpg结尾的图像,放进列表中
        imgdir = QDir(openfile_dir)
        if not imgdir.exists():
            return

        imgList = imgdir.entryList(['*.bmp', '*.jpg', '*.png'],
                                   QtCore.QDir.NoFilter,
                                   QtCore.QDir.Name | QtCore.QDir.IgnoreCase)
        cnt = len(imgList)
        self.tableImgList.clear()
        self.tableImgList.setRowCount(cnt)
        self.tableImgList.setColumnCount(2)
        for i in range(0, cnt):
            self.tableImgList.setItem(i, 0, QTableWidgetItem(imgList[i]))
            self.tableImgList.setItem(i, 1, QTableWidgetItem(imgList[i]))
        #    #  ui->preFileList->setItem(i,0,new QTableWidgetItem(QString::number(i+1)));
        #     ui->preFileList->setItem(i,1,new QTableWidgetItem(m_fileNameList[i]));
        self.tableImgList.setEditTriggers(QAbstractItemView.NoEditTriggers)  #禁止编辑
        # 取列表的第一张
        if cnt > 0:
            imgName = openfile_dir +"/" + imgList[0]
            # print(imgName)
            jpg = QPixmap(imgName).scaled(self.la_image.width(), self.la_image.height())
            # 显示原图
            self.la_image.setPixmap(jpg)

        self.tabWidget.setCurrentIndex(1)

点击列表切换图像

    def drawImage(self):   # 点击列表中的图像并显示

        open_dir = self.le_imageDir.text()
        if len(open_dir) == 0:
            return
        # print(open_dir)
        imgFile = open_dir + "/" + self.tableImgList.currentItem().text()
        # self.tableImgList.currentItem().background(QBrush(QColor(255, 0, 0)))  # 设置选中的单元格颜色
        jpg = QPixmap(imgFile).scaled(self.la_image.width(), self.la_image.height())
        # 显示原图
        self.la_image.setPixmap(jpg)

读取配置文件

支持使用默认配置及手动输入

# 读取配置文件
    def readConfig(self):
        import yaml
        config = "./config.yaml"
        with open(config, 'r', encoding='utf8') as file:
            d = yaml.safe_load(file.read())
        self.m_MaxIterationEd.setText(str(d['epochs']))
        # print(self.train.epochs)
        self.m_BathSizeEd.setText(str(d['batch_size']))
        self.m_ImageSizeEd.setText(str(d['image_size']))
        self.m_ValidationRatioEd.setText(str(d['validation_ratio']))
        self.m_LearningRateEd.setText(str(d['lr']))
        self.m_WeightDecayEd.setText(str(d['dw']))
        if d['CUDA']:
            self.m_isCuda.setChecked(True)
        self.m_modelSaveEd.setText(d['save_dir'])
        if not os.path.exists(d['save_dir']):
            os.mkdir(d['save_dir'])

手动修改训练超参数

def finishSetting(self):
        # 判断不能漏填

        if len(self.m_MaxIterationEd.text()) == 0:
            QMessageBox.information(self, '警告', '训练次数不能为空')
            return

        if len(self.m_BathSizeEd.text()) == 0:
            QMessageBox.information(self, '警告', '批尺寸不能为空')
            return
        if len(self.m_ImageSizeEd.text()) == 0:
            QMessageBox.information(self, '警告', '图像尺寸不能为空')
            return

        if len(self.m_ValidationRatioEd.text()) == 0:
            QMessageBox.information(self, '警告', '验证集比例不能为空')
            return

        if len(self.m_LearningRateEd.text()) == 0:
            QMessageBox.information(self, '警告', '学习率不能为空')
            return
        if len(self.m_WeightDecayEd.text()) == 0:
            QMessageBox.information(self, '警告', '权重衰减系数不能为空')
            return

        self.train.epochs = int(self.m_MaxIterationEd.text())
        self.train.batch_size = int(self.m_BathSizeEd.text())
        self.train.image_size = int(self.m_ImageSizeEd.text())
        self.train.validation_ratio = float(self.m_ValidationRatioEd.text())
        self.train.lr = float(self.m_LearningRateEd.text())
        self.train.dw = float(self.m_WeightDecayEd.text())
        self.train.Cuda = self.m_isCuda.isChecked()

        # 将内容写到文本文档中
        reply = QMessageBox.information(self, "通知", "参数配置完成", QMessageBox.Ok)
        if reply == QMessageBox.Ok:
            self.doShake()

选择模型保存路径

    def selectSaveDir(self):
        save_dir = QFileDialog.getExistingDirectory(self.centralwidget, "选择路径", self.cwd)

        self.m_modelSaveEd.setText(save_dir)

开始训练

初始化模型

    def trainer(self):
        self.m_modelTrainProcesssbar.setMaximum(self.train.epochs)
        open_dir = self.le_imageDir.text()
        if len(open_dir) == 0:
            return
        save_dir = self.m_modelSaveEd.text()
        self.logFile = open(save_dir + '/log.txt', 'a')
        self.t = Thread(open_dir,self.train, save_dir)
        self.t.valueChange.connect(self.m_modelTrainProcesssbar.setValue)
        self.t.textChange.connect(self.updateText)
        # self.t.start()
        self.m_initModelBtn.setEnabled(False)
        self.m_startTrainBtn.setEnabled(True)

开始训练

    def startTrainer(self):
        self.t.start()
        self.m_startTrainBtn.setEnabled(False)
        self.m_pauseTrainBtn.setEnabled(True)

中止训练

    def suspendTrainer(self):
        self.t.pause()
        self.m_pauseTrainBtn.setEnabled(False)
        self.m_resumTrainBtn.setEnabled(True)

继续训练

    def wakeTrainer(self):
        self.t.resume()
        self.m_pauseTrainBtn.setEnabled(True)
        self.m_resumTrainBtn.setEnabled(False)

停止训练

    def stopTrainer(self):
        reply = QMessageBox.question(self, "停止训练", "您确定要停止训练吗?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.t.stop()
            self.m_initModelBtn.setEnabled(True)
            self.logFile.close()
        else:
            return


实时显示训练loss

    # 多行文本展示框
    def updateText(self, val, text):
        message = "epoch:{0}".format(val)
        msg = message + " " + "loss:" + text
        self.logFile.write('\n{}'.format(msg))
        self.textBrowser.append(msg)
        self.textBrowser.moveCursor(self.textBrowser.textCursor().End)

点击按钮实现窗口抖动

    # 点击Ok 后窗口抖动一下
    def doShake(self):
        self.doShakeWindow(self)

    # 下面这个方法可以做成这样的封装给任何控件
    def doShakeWindow(self, target):
        """窗口抖动动画
        :param target:        目标控件
        """
        if hasattr(target, '_shake_animation'):  # 函数用于判断对象是否包含对应的属性
            # 如果已经有该对象则跳过
            return

        animation = QPropertyAnimation(target, b'pos', target)
        target._shake_animation = animation
        animation.finished.connect(lambda: delattr(target, '_shake_animation'))  #删除属性

        pos = target.pos()
        x, y = pos.x(), pos.y()

        animation.setDuration(200)
        animation.setLoopCount(2)
        animation.setKeyValueAt(0, QPoint(x, y))
        animation.setKeyValueAt(0.09, QPoint(x + 2, y - 2))
        animation.setKeyValueAt(0.18, QPoint(x + 4, y - 4))
        animation.setKeyValueAt(0.27, QPoint(x + 2, y - 6))
        animation.setKeyValueAt(0.36, QPoint(x + 0, y - 8))
        animation.setKeyValueAt(0.45, QPoint(x - 2, y - 10))
        animation.setKeyValueAt(0.54, QPoint(x - 4, y - 8))
        animation.setKeyValueAt(0.63, QPoint(x - 6, y - 6))
        animation.setKeyValueAt(0.72, QPoint(x - 8, y - 4))
        animation.setKeyValueAt(0.81, QPoint(x - 6, y - 2))
        animation.setKeyValueAt(0.90, QPoint(x - 4, y - 0))
        animation.setKeyValueAt(0.99, QPoint(x - 2, y + 2))
        animation.setEndValue(QPoint(x, y))

        animation.start(animation.DeleteWhenStopped)

信号和槽

    def initUi(self):
        self.showHomepage()
        self.tabWidget.setCurrentIndex(0)
        # 设置按钮一闪闪的
        aniButton = AnimationShadowEffect(Qt.blue, self.m_ImageDirBtn)
        self.m_ImageDirBtn.setGraphicsEffect(aniButton)
        aniButton.start()

        self.m_ImageDirBtn.clicked.connect(self.openfiledir)
        self.tableImgList.itemSelectionChanged.connect(self.drawImage)  # 这
        self.m_OkBtn.clicked.connect(self.finishSetting)  #
        self.m_modelSaveBtn.clicked.connect(self.selectSaveDir)
        self.m_initModelBtn.clicked.connect(self.trainer)

        self.m_startTrainBtn.clicked.connect(self.startTrainer)
        self.m_pauseTrainBtn.clicked.connect(self.suspendTrainer)
        self.m_resumTrainBtn.clicked.connect(self.wakeTrainer)
        self.m_stopTrainBtn.clicked.connect(self.stopTrainer)


        self.m_SetTrainPareBtn.clicked.connect(self.second)
        self.m_StartTrainBtn.clicked.connect(self.third)
        self.m_modelTrainProcesssbar.setValue(0)
        self.readConfig()
        self.statusShowTime()
        self.m_loadmodelBtn.clicked.connect(self.loadmodelPath)
        # keyboard.add_hotkey('alt+s', self.onShow, suppress=False)  # 显示界面
        # keyboard.add_hotkey('ctrl+s', self.onHide, suppress=False)  # 隐藏界面
        self.m_startTrainBtn.setEnabled(False)
        self.m_pauseTrainBtn.setEnabled(False)
        self.m_resumTrainBtn.setEnabled(False)

退出软件

    def closeEvent(self, event):

        """
        对MainWindow的函数closeEvent进行重构
        退出软件时结束所有进程
         """
        reply = QMessageBox.question(self,
                                       '本程序',
                                       "是否要退出程序?",
                                       QMessageBox.Yes | QMessageBox.No,
                                       QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
            os._exit(0)
        else:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/101639.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于云的文档管理软件/文档管理系统(DMS)

基于云的文档管理软件 由于违反法规而导致的安全漏洞、数据丢失、版本管理等难题和诉讼已经变得非常普遍,以至于这一切都感觉像是“正常”的现象。使用文档管理系统,可以让您避免这些麻烦。安全标准的执行、信息的合规性和维护都在控制之中,只…

【人脸识别】SVM和PCA人脸识别【含GUI Matlab源码 369期】

⛄一、简介 1 PCA-SVM原理 1.1 主成分分析PCA 本文处理的所有原始图片都是112x 92大小的pgm格式图片, 每幅图片包含10304个像素点, 每一行代表一个样本,维数就是10304维。维数过大使得数据处理工作十分复杂,同时,图片…

axios传参的语法

请求方式 POST 向服务器新增数据 GET 从服务器获取数据 DELETE 删除服务器上的数据 PUT 更新服务器上的数据(侧重于完整更新:例如更新用户的完整信息) PATCH 更新服务器上的数据(侧重于部分更新:例如只更新用户的手机号 ) get axios({url: 请求地址,m…

制作自已的屏保动态

制作自已的屏保动态我的环境第一步:编写自己的屏保程序1、代码准备2、编译第二步:有了可运行程序,使用RAR压缩工具将资源和程序打包成独立可执行exe第三步:将dist.exe配置成系统屏幕保护参考我的环境 win10 python3.X pycharm 第…

Linux学习08-认识与学习BASH

1 认识BASH 我们必须要通过Shell将我们输入的命令与内核沟通,好让内核可以控制硬件来正确无误地工作。 Bash shell的功能 历史命令:命令行按“上下键”就可以找到前/后一个输入的指令。 命令与文件补全功能: [Tab] 接在一串指令的第一个…

大学生学习网站哪里找?收好这15个网站

1.学堂在线 地址:https://www.xuetangx.com/ 这里面的课程都是精选,以北大清华为首的高校汇聚于此 2.中国大学生MOOC 地址:https://www.icourse163.org/ 不多说都是精品 3.网易公开课 地址:https://open.163.com/ 网易公开课汇集清华、北大、哈佛、耶鲁等世界名…

全景分割~

Hinton组提出基于大型全景掩码的实例分割框架,图像视频场景丝滑切换 全景分割是一项基本的视觉任务,该任务旨在为图像的每个像素指定语义标签和实例标签。语义标签描述每个像素的类别(例如天空、竖直物体等),实例标签…

408 | 考前知识拾遗

计网 二、物理层 各种编码图像 数据交换方式——怎么算时间 VLAN每个VLAN都是一个广播域 三、数据链路层 差错控制:检错、纠错 停等、GBN、SR差别 随机访问 VLAN的考点 交换机:转发、自学习 四、网错层 路由协议/算法 ☆☆☆IPV4分组 1、网关配置、路由…

JVM——常量池

目录一、常量池二、运行时常量池三、intern方法 1.8四、intern方法 1.6五、StringTable 垃圾回收六、StringTable调优通过解决以下问题可以更深入了解字符串创建过程中的原理 一、常量池 二进制字节码的组成:类的基本信息、常量池、类的方法定义(包含…

集合的框架体系和Collection接口

1.集合的理解和好处 前面我们保存多个数据使用的是数组,那么数组有不足的地方,我们分析一下 1.1数组 1)长度开始时必须指定,而且一旦指定,不能更改 2)保存的必须为同一类型的元素 3)使用数组进行增加/删除元素的示例代码-比较麻烦…

调试3D渲染和3D可视化的五个好处

建筑和建筑环境是我们日常生活中不可避免的一部分,直接影响我们和我们的福祉。它可以是我们的家、办公室、附近的教堂或城市的商业综合体;所有这一切的设计和规划都是建筑。然而,具有讽刺意味的是,建筑的交流往往并不具有包容性。例如&#x…

玩以太坊链上项目的必备技能(函数及其可见性和状态可变性-Solidity之旅十三)

状态变量可见性 在这之前的文章里,给出的例子中,声明的状态变量都修饰为public,因为我们将状态变量声明为public后,Solidity 编译器自动会为我们生成一个与状态变量同名的、且函数可见性为public的函数! 在 Solidity…

ASP.NET Core 3.1系列(19)——EFCore中的添加实体操作

1、前言 前面介绍了EFCore中关于查询和执行原生SQL的操作,这篇博客就来介绍一下EFCore中添加实体的相关操作。关于添加实体,EFCore提供了多种方法供开发者使用。但EFCore中针对实体的一系列操作最终都会被转换成SQL,因此这些方法之间也存在着…

设计模式之模版方法模式

Template method design pattern 模版方法模式的概念、模版方法模式的结构、模版方法模式的优缺点、模版方法模式的使用场景、模版方法模式的实现示例、模版方法模式的源码分析 1、模版方法模式的概念 模版方法模式,即定义一个算法骨架,而将一些步骤延迟…

ARM——指令集仿真环境搭建

目录 一、ARM指令集仿真环境搭建 1.1指令和指令集 指令 指令集 1.2汇编的本质 汇编 C语言 1.3为什么学习汇编 1.4仿真 硬件仿真 软件仿真 1.5Keil 1.6环境搭建 1.7汇编工程创建 二、汇编 2.1汇编中的符号 2.2ARM指令集 2.3简单的ARM程序 一、ARM指令集仿真环境搭…

Cyanine5 NHS ester |分子量:616.19|分子式:C36H42ClN3O4

Cyanine5 NHS ester |分子量:616.19|分子式:C36H42ClN3O4 外观:暗蓝色粉末 分子量:616.19 分子式:C36H42ClN3O4 溶解性:易溶于有机溶剂(DMF,DMSO和氯化物),难溶于水 …

Mob社会化分享集成ShareSDK

如何在项目已经集成 SMSSDK 的情况下集成 ShareSDk 到项目中,需要使用创建 module 的方式引入 ShareSDk,主要内容如下: 1.下载ShareSDK 2.引入 ShareSDK 3.创建 MainLibs Module 4.创建 OneKeyShare Module 5.在项目中引入 Module 6.配…

Unity Addressables资源管理 主设置面板

Addressables资源管理总目录 0.主设置菜单位置 位置1 位置2 1.Profiles 路径配置选项 这个是全局路径配置的选择 可以点击 Manager Profiles 打开路径配置面板 打包路径设置 2.Diagnostics 诊断设置 Send Profiler Events 打开这个选项,才能在Event Viewer窗口…

记录java枚举类在数据库、前后端交互时的序列化方式

实体类枚举属性持久化到数据库 1.EnumValue 2.配置 mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler 或 mybatis-plus:typeEnumsPackage: xxx 实体类中枚举属性自动转为EnumValue标记的属性值 从数据…

C++数学与算法系列之排列和组合

1. 前言 本文将聊聊排列和组合,排列组合是组合学最基本的概念,在程序运用中也至关重要。 排列问题:指从给定个数的元素中取出指定个数的元素进行排序。 组合问题:指从给定个数的元素中仅仅取出指定个数的元素,不排序…