版權聲明:本文爲博主原創文章,轉載 請註明出處:https://blog.csdn.net/sc2079/article/details/90454379python
本科畢業設計終於告一段落了。特寫博客記錄作畢業設計(路面裂紋識別)期間的踩過的坑和收穫。但願對你有用。
目前有:
1.Tensorflow&CNN:裂紋分類
2.Tensorflow&CNN:驗證集預測與模型評價
3.PyQt5多個GUI界面設計
本篇講GUI界面的設計。設計目標:實現用戶對路面裂紋快速檢測與識別,有三個界面:主界面、裂紋快速識別界面、圖像處理測試界面。mysql
運行環境:Python3.六、Spyder、Qt Designer
依賴的模塊:PyQt五、mysql等
值得注意的是:我安裝PyQt5模塊時,按照網上方法,以下:web
pip install PyQt5
pip install PyQt5-tools
打開Qt Designer:數據庫
Qt Designer設計的文件後綴爲.ui,須要將其轉換爲.py文件。打開剛纔下載的PyQt5合集中的WinPython Command Prompt,輸入:多線程
pyuic5 -o D:\WinPyQt5.9-32bit-3.5.3.1\test\XX.py D:\WinPyQt5.9-32bit-3.5.3.1\test\XX.ui
便可獲得界面的Python文件。app
主界面功能比較簡單,主要是用戶對功能的選擇以及對該系統的瞭解。
dom
from PyQt5.QtWidgets import QMainWindow,QMessageBox,QApplication from main_gui import Ui_MainWindow import sys import time from PyQt5.QtGui import QPixmap class MainWindow(QMainWindow): def __init__(self,parent = None): super(MainWindow,self).__init__(parent=parent)#調用父類的init global ui ui = Ui_MainWindow() ui.setupUi(self) def about_us(self): msgBox = QMessageBox(QMessageBox.NoIcon, '關於','XX的本科畢業設計') msgBox.setIconPixmap(QPixmap(".//icon//me3.jpg")) msgBox.exec() def function_exp(self): msgBox = QMessageBox(QMessageBox.NoIcon, '功能說明','') msgBox.exec() def operate_exp(self): msgBox = QMessageBox(QMessageBox.NoIcon, '操做說明','') msgBox.exec() def jump_to_1(self): pass def jump_to_2(self): pass def closeEvent(self, event): reply = QMessageBox.question(self, '提醒', "肯定退出?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore() if __name__ == '__main__': app = 0 app = QApplication(sys.argv) myMainWindow = MainWindow()#自定義的類例化 myMainWindow.show() time.sleep(10) sys.exit(app.exec_())
而對於轉換的主界面的py代碼(注意:本文將轉換成的.py文件命名爲xx_gui.py,而其對應的.py文件命名爲xx_win.py),找到以下語句:ide
self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
修改成:svg
self.retranslateUi(MainWindow) self.crack_info.triggered.connect(MainWindow.jump_to_1) self.img_processing.triggered.connect(MainWindow.jump_to_2) self.function_exp.triggered.connect(MainWindow.function_exp) self.operate_exp.triggered.connect(MainWindow.operate_exp) self.about_us.triggered.connect(MainWindow.about_us) QtCore.QMetaObject.connectSlotsByName(MainWindow)
這樣,主界面功能就實現了。
現已經利用CNN以及圖像處理技術實現了對裂紋的識別與檢測。這裏主要是怎麼將結果顯示在界面上。這裏參照了博客使用PyQt5建立帶文件對話框和文本對話框的ui窗口程序。
from PyQt5.QtWidgets import (QMainWindow,QApplication,QFileDialog) from PyQt5 import QtCore from crack_detect_gui import Ui_MainWindow2 from prediction import prediction import sys import threading import time from img_processing import img_processing import numpy as np from mysql_save import save_mysql class MainWindow2(QMainWindow): _signal=QtCore.pyqtSignal(str)#自定義信號 def __init__(self,parent = None): super(MainWindow2,self).__init__(parent=parent)#調用父類的init self.img_opened = False self.imgs_opened = False global ui ui = Ui_MainWindow2() ui.setupUi(self) self.mainWindow2=ui.MainWindow2 ui.output_info.clear() ui.file_name.clear() self._signal.connect(self.print_info) def back(self): pass def reset(self,parent = None): pass def open_file(self): self.img_name = QFileDialog.getOpenFileName(self,"打開","","圖片(*.jpg;*.png)") ui.file_name.setPlainText(self.img_name[0]) self.img_opened = True def open_files(self): self.imgs_name = QFileDialog.getOpenFileNames(self,"打開","","多個圖片(*.jpg;*.png)") imgs_name='' for img_name in self.imgs_name[0]: imgs_name=imgs_name+img_name+'\n' ui.file_name.setPlainText(imgs_name) self.imgs_opened = True def print_info(self,pri_str): ui.output_info.appendPlainText(pri_str) ui.output_info.show() def output_info_thread(myMainWindow): t1=time.time() Opened = False while(True): if myMainWindow.img_opened==True: imgs_path = myMainWindow.img_name[0].replace("/","//") break elif myMainWindow.imgs_opened==True: imgs_path=[] for path in myMainWindow.imgs_name[0]: imgs_path.append(path.replace("/","//")) break Opened = True myMainWindow._signal.emit("當前線程:%s" %threading.current_thread().name) timeArray = time.localtime(t1) now=time.strftime("%Y_%m_%d", timeArray) try: if(Opened): s1 = "正在進行裂紋識別評估" myMainWindow._signal.emit(s1) kinds=prediction(imgs_path) s2='裂紋圖片 裂紋類型 裂紋長度 裂紋面積 裂紋最大寬度 裂紋最小寬度 裂紋平均寬度' myMainWindow._signal.emit(s2) data= np.empty(shape=[0, 8]) for i in range(len(kinds)): if len(kinds)==1: name=imgs_path[::-1].split('//', 1)[0][::-1] else: name=imgs_path[i][::-1].split('//', 1)[0][::-1] if kinds[i]=='無裂紋': crack_info=[imgs_path[i],kinds[i],'','','',''] elif len(kinds)==1: crack_info=img_processing(imgs_path,kinds[i]) else: crack_info=img_processing(imgs_path[i],kinds[i]) s=name+' '+crack_info[0]+' '*5+crack_info[1]+' '*7+crack_info[2]+\ ' '*11+crack_info[3]+' '*12+crack_info[4]+' '*12+crack_info[5] myMainWindow._signal.emit(s) new_crack_info=[name,crack_info[0],crack_info[1],crack_info[2], crack_info[3],crack_info[4],crack_info[5],now] data=np.append(data, [new_crack_info], axis = 0) t2=time.time() database='crack_info' try: save_mysql(database,data) myMainWindow._signal.emit('數據已存入'+database+'數據庫中') except: myMainWindow._signal.emit('數據存儲失敗,請檢查數據庫是否打開!') time_comsume=round(t2-t1,2) myMainWindow._signal.emit('共耗時: '+str(time_comsume)+' s') myMainWindow._signal.emit("****************處理完畢****************") except BaseException as e1: print(e1) except EnvironmentError as e2: print(e2) except (OSError,WindowsError, MemoryError,NameError, UnboundLocalError,ReferenceError, RuntimeError,NotImplementedError, UnicodeDecodeError,UnicodeEncodeError, UnicodeError,UnicodeTranslateError, RuntimeWarning,UserWarning) as e3: print(e3) if __name__ == '__main__': app = 0 if not QApplication.instance(): app = QApplication(sys.argv) else: app = QApplication.instance() myMainWindow = MainWindow2()#自定義的類例化 myMainWindow.show() t1 = threading.Thread(target = output_info_thread, args = (myMainWindow,)) t1.start() time.sleep(10) sys.exit(app.exec_())
同理,將該界面的XX_gui.py修改成:
self.retranslateUi(MainWindow2) self.pushButton.clicked.connect(MainWindow2.open_file) self.pushButton_2.clicked.connect(MainWindow2.open_files) self.pushButton_3.clicked.connect(MainWindow2.reset) self.pushButton_4.clicked.connect(MainWindow2.back) QtCore.QMetaObject.connectSlotsByName(MainWindow2) self.MainWindow2=MainWindow2 mainWindow2=self.MainWindow2
import sys from PyQt5 import QtGui from PyQt5 import QtWidgets from PyQt5.QtWidgets import QFileDialog,QWidget #from img_pro_gui_code import Ui_Dialog from img_pro_gui import Ui_Dialog from img_processing_plot import img_processing #from main_win import MainWindow class Picture(QWidget): def __init__(self): super(Picture,self).__init__()#調用父類的init global ui ui = Ui_Dialog() ui.setupUi(self) self.imgs_data=ui.imgs_data self.dialog=ui.dialog def reset(self): pass def back(self): pass def open_file(self): imgName, imgType = QFileDialog.getOpenFileName(self, "打開圖片", "", "*.jpg;;*.png;;All Files(*)") self.path=imgName img_path=self.path.replace("/","//") imgs=img_processing(img_path) for i in range(len(imgs)): jpg = QtGui.QPixmap(imgs[i]).scaled(self.imgs_data[i].width(), self.imgs_data[i].height()) self.imgs_data[i].setPixmap(jpg) if __name__ == "__main__": app=0 app = QtWidgets.QApplication(sys.argv) my = Picture() my.show() sys.exit(app.exec_())
值得一提的是,這裏的多圖片顯示功能,我是先將圖像處理測試程序中產生的圖片保存到本地再使用QPixmap方法導入並顯示。
同理,該界面所對應的XX_gui.py文件中改寫爲:
self.retranslateUi(Dialog) self.choose.clicked.connect(Dialog.open_file) self.clear.clicked.connect(Dialog.reset) self.back.clicked.connect(Dialog.back) QtCore.QMetaObject.connectSlotsByName(Dialog) self.imgs_data=[self.img_source,self.img_blur,self.img_canny,self.img_cut, self.img_close,self.img_open,self.img_domain,self.img_skeleton] imgs_data=self.imgs_data self.dialog=Dialog dialog=self.dialog
主界面跳轉界面1修改成:
def jump_to_1(self): #myMainWindow.hide() #若是沒有這一句,關閉子界面後就會關閉程序 self.ui_1=MainWindow2() self.ui_1.show() crack_detect(self.ui_1)
裂紋快速識別界面上返回功能是直接關閉當前界面,重置功能是將界面數據清零並再次啓動多線程。
def back(self): self.mainWindow2.close() def reset(self,parent = None): self.img_opened = False self.imgs_opened = False ui.output_info.clear() ui.file_name.clear() t1 = threading.Thread(target = output_info_thread, args = (myMainWindow,)) t1.start()
主界面跳轉界面2修改成:
def jump_to_2(self): #myMainWindow.hide() #若是沒有這一句,關閉子界面後就會關閉程序 self.ui_2=Picture() self.ui_2.show()
圖像處理測試界面上返回功能的實現同上,重置功能是將界面數據清零。
def reset(self): for label in self.imgs_data: label.clear() def back(self): self.dialog.close()
在命令行運行主界面程序,結果以下(以Gif展現):
因爲時間有限且初次設計GUI界面(經驗不足),界面比較醜,請見諒。如有問題,歡迎留言。