炼丹软件
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: