【搞事情】利用PyQt为目标检测SSD300添加界面(二)
【原創(chuàng)文章】歡迎正常授權(quán)轉(zhuǎn)載(聯(lián)系作者)
【反對(duì)惡意復(fù)制粘貼,如有發(fā)現(xiàn)必維權(quán)】
【微信公眾號(hào)原文傳送門】
上篇詳細(xì)介紹實(shí)現(xiàn)利用PyQt給SSD加界面的三種方案(沒學(xué)的趕快點(diǎn)進(jìn)來學(xué)呀,哈哈)。這篇將詳細(xì)介紹方案1的實(shí)現(xiàn)代碼(代碼獲取見文章末尾)。
下載好的代碼中項(xiàng)目文件構(gòu)成如下:
其中 “ssd” 文件夾中是SSD檢測(cè)的關(guān)鍵文件,關(guān)于這部分之前寫文章了,里面詳細(xì)介紹了如何訓(xùn)練一個(gè)屬于自己的SSD300,有代碼、有預(yù)訓(xùn)練的權(quán)值文件,不清楚的請(qǐng)移步這里。
接下來詳細(xì)介紹實(shí)現(xiàn),先看看流程圖,實(shí)現(xiàn)的關(guān)鍵在于 檢測(cè)循環(huán) 和 顯示。
01 繪制界面
這里推薦一個(gè)非常方便的PyQt開發(fā)IDE—— eric,整體開發(fā)過程有點(diǎn)像MFC的感覺,可以直觀看見控件的動(dòng)作信號(hào),并直接創(chuàng)建對(duì)應(yīng)的槽函數(shù),開發(fā)非常有效率,可以節(jié)省大把時(shí)間。
創(chuàng)建一個(gè)對(duì)話框窗口或者主窗口,拖拽一個(gè)QLabel在主窗口中用于顯示,兩個(gè)QPushButton用于控制開始/停止,一個(gè)QTextEdit用于顯示檢測(cè)結(jié)果。當(dāng)然添加什么控件還是按照自己的需求來。為了講解下面的代碼,這里我把用到的控件和名稱列在下面。界面的布置如下圖。
界面控件
| QLabel | label_imgshow | 畫面顯示 |
| QPushButton | pushButton_start | 開始 |
| QPushButton | pushButton_end | 結(jié)束 |
| QTextEdit | textEdit | 顯示檢測(cè)結(jié)果 |
繪制好ui文件(對(duì)應(yīng)文件:MainWindow.ui)后將其轉(zhuǎn)為.py文件(Ui_MainWindow.py)。eric 可以十分方便的完成轉(zhuǎn)化,唯一麻煩的是,每次ui文件改變了都需要重新再“轉(zhuǎn)化更新”一次。
02 界面顯示
界面顯示主要是要將opencv的圖像數(shù)據(jù)(numpy.array)顯示在界面的QLabel(label_imgshow)中,項(xiàng)目中構(gòu)建了一個(gè)類成員函數(shù)實(shí)現(xiàn)。
def show_img(self, img):showImg = QImage(img.data, img.shape[1], img.shape[0],img.shape[1] * 3, # 每行數(shù)據(jù)個(gè)數(shù),3通道 所以width*3QImage.Format_RGB888)self.label_imgshow.setPixmap(QPixmap.fromImage(showImg)) # 展示圖片代碼非常簡(jiǎn)單,就是先將numpy.array的數(shù)據(jù)轉(zhuǎn)為QImage,再通過Qlabel控件的setPixmap將圖像顯示出來。每次更新顯示時(shí)將opencv的圖像數(shù)據(jù)作為參數(shù),調(diào)用一次函數(shù)就行。
03 幀循環(huán)實(shí)現(xiàn)
接下來就是最復(fù)雜(其實(shí)超簡(jiǎn)單)的幀循環(huán)了。在窗口實(shí)例化時(shí),將SSD300模型建立并導(dǎo)入訓(xùn)練好的權(quán)值,點(diǎn)擊‘開始’后時(shí)開始幀循環(huán)檢測(cè)(循環(huán)在點(diǎn)擊‘開始’的槽函數(shù)中),點(diǎn)擊‘結(jié)束’后結(jié)束幀循環(huán)(通過控制循環(huán)條件實(shí)現(xiàn))。
下面詳細(xì)介紹構(gòu)造函數(shù)及“開始/結(jié)束”按鈕點(diǎn)擊的槽函數(shù)。
構(gòu)造函數(shù)
功能:主要完成SSD的初始化以及一些依賴變量的初始化。
這里建議那些利用該方案來給自己搭建的網(wǎng)絡(luò)添加界面的同學(xué),建議將網(wǎng)絡(luò)單獨(dú)封裝成類,界面類中使用時(shí)會(huì)非常便利。
def __init__(self, parent=None):super(MainWindow, self).__init__(parent) # 父類初始化self.setupUi(self) # 窗口‘穿衣服’,變成我們?cè)O(shè)計(jì)的樣子# 初始化界面# 設(shè)置圖片自適應(yīng)顯示self.label_imgshow.setScaledContents(True)# 創(chuàng)建一幅白色圖片,在停止的時(shí)候顯示self.img_none = np.ones((420, 720, 3), dtype=np.uint8)*255self.show_img(self.img_none)# 初始化SSD# 目標(biāo)名稱,按順序self.obj_names = ['Aeroplane', 'Bicycle', 'Bird', 'Boat', 'Bottle','Bus', 'Car', 'Cat', 'Chair', 'Cow', 'Diningtable','Dog', 'Horse', 'Motorbike', 'Person', 'Pottedplant','Sheep', 'Sofa', 'Train', 'Tvmonitor']# 需要顯示的目標(biāo)list, 用于過濾self.include_class = self.obj_names# 導(dǎo)入權(quán)值文件,關(guān)聯(lián)檢測(cè)目標(biāo)類別名self.ssd = SSD_test(weight_path='./ssd/weights/weights_SSD300.hdf5', class_nam_list=self.obj_names)# 攝像頭索引號(hào)或者視頻文件路徑self.camera_index = 0 # 電腦連接的攝像頭默認(rèn)為0# opencv 支持 ip攝像頭# self.camera_index = './Voc_test.avi'# 主循環(huán)flg,控制循環(huán), False時(shí)循環(huán)停止self.video_flg = True‘開始’點(diǎn)擊槽函數(shù)
功能:獲取圖像數(shù)據(jù)流,之后開始幀循環(huán)檢測(cè)
幀循環(huán)基本流程:讀入圖片–>預(yù)處理–>SSD檢測(cè)–>處理檢測(cè)結(jié)果–>結(jié)果繪制在圖像上–>更新顯示
@pyqtSlot() def on_pushButton_start_clicked(self):# 獲取圖像數(shù)據(jù)流self.cap = cv2.VideoCapture(self.camera_index)# 判斷數(shù)據(jù)流是否打開if self.cap.isOpened():# ‘開始’按鈕設(shè)置為不可用# 以免二次誤點(diǎn)造成錯(cuò)誤self.pushButton_start.setEnabled(False)# 開始幀循環(huán)self.video_flg = Truewhile self.video_flg:# 按幀讀取圖像ret, self.img_scr = self.cap.read()# opencv中圖像為BGR,這里轉(zhuǎn)為RGB# 因?yàn)槲业腟SD訓(xùn)練時(shí)用的是RGB圖像,順序錯(cuò)誤會(huì)影響檢測(cè)準(zhǔn)確性self.img_scr = cv2.cvtColor(self.img_scr, cv2.COLOR_BGR2RGB)# SSD檢測(cè)self.preds = self.ssd.Predict(self.img_scr)# 對(duì)檢測(cè)結(jié)果過濾self.preds = self.filter(self.preds, inclued_class=self.include_class)# 將檢測(cè)結(jié)果繪制到圖像self.img_scr = self.draw_img(self.img_scr, self.preds)# 將檢測(cè)結(jié)果顯示在QTextEdit控件上h, w = self.img_scr.shape[:2]self.text = self.decode_preds(self.preds, w=w, h=h)self.textEdit.setText(self.text)# 更新顯示圖像self.show_img(self.img_scr)# 強(qiáng)制更新UI# 如果沒有,界面就‘假死’了,因?yàn)橐恢碧幱谘h(huán)里QApplication.processEvents()else:self.textEdit.setText('攝像頭未打開!!!\n請(qǐng)檢查')‘結(jié)束’點(diǎn)擊槽函數(shù)
功能:改變幀循環(huán)條件停止循環(huán);為下一次開始做準(zhǔn)備
@pyqtSlot()def on_pushButton_end_clicked(self):# 改變循環(huán)條件,停止循環(huán)self.video_flg = False# 顯示空白圖片self.show_img(self.img_none)# 清除TextEdit中的顯示self.textEdit.clear()# 釋放攝像頭/數(shù)據(jù)流# 先判斷是不是當(dāng)前實(shí)例是不是有‘cap’成員# 防止攝像頭已經(jīng)釋放完了,再次點(diǎn)擊時(shí)報(bào)錯(cuò)if hasattr(self, 'cap'):# 釋放攝像頭self.cap.release()# 刪除成員變量del self.cap# 將‘開始’設(shè)置為可以點(diǎn)擊,為再開始做準(zhǔn)備self.pushButton_start.setEnabled(True)關(guān)注下方公眾號(hào),回復(fù)關(guān)鍵字即可獲取下載地址。
-
方案1源代碼下載:
回復(fù)“SSD界面1”獲取。
如果你讀后有收獲,歡迎關(guān)注我的微信公眾號(hào)
上面有更多完全免費(fèi)教程,我也會(huì)不定期更新
? ? ? 打開微信掃描下方二維碼關(guān)注 ? ? ?
總結(jié)
以上是生活随笔為你收集整理的【搞事情】利用PyQt为目标检测SSD300添加界面(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python一键生成二维码/条形码并保存
- 下一篇: 2020年11月国产数据库排行:Gaus