OpenCV能夠處理圖像、視頻、深度圖像等各種類型的視覺(jué)數(shù)據(jù),在某些情況下,盡管OpenCV可以顯示窗口,但PyQt5可能更適合用于創(chuàng)建復(fù)雜的交互式應(yīng)用程序,而自帶GPU的H618就成為了這些圖像顯示的最佳載體。
本文將實(shí)現(xiàn)的功能是使用圖像處理庫(kù)OpenCV從攝像頭獲取數(shù)據(jù),縮放后從PyQt5的窗口中顯示出來(lái)。
創(chuàng)建pyqt5窗口
這里在電腦上使用designer軟件,創(chuàng)建一個(gè)Main Window類型窗體。從左邊組件欄中拖出一個(gè)label放到窗口中間。
點(diǎn)一下放在窗口中的label,在軟件右下角的屬性編輯器里可以設(shè)置很多東西,這里就不細(xì)介紹了。這里我是設(shè)置了QFrame啟用了邊框,QLabel中的texte屬性控制顯示的文本,QLabel中的alignment屬性控制文本對(duì)齊方式。
然后保存為.ui結(jié)尾的文件:
隨后將designer繪制的ui文件轉(zhuǎn)化為py文件
python3 -m PyQt5.uic.pyuic ui_main.ui -o ui_main.py
接下來(lái)編寫main.py程序,調(diào)用剛剛畫的窗口進(jìn)行顯示,先把剛剛的ui_main.py以及一些qt庫(kù)給import進(jìn)來(lái):
from ui_main import Ui_MainWindow import PyQt5 from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import * from PyQt5.QtGui import * # 修正qt的plugin路徑,因?yàn)槟承┏绦颍╟v2)會(huì)將其改到其他路徑 import os os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.dirname(PyQt5.__file__)
放入一點(diǎn)輔助代碼,一個(gè)是為了實(shí)現(xiàn)從遠(yuǎn)程命令行運(yùn)行qt程序顯示到桌面上,一個(gè)是為了在命令行下可以按ctrl+c快捷鍵來(lái)強(qiáng)制退出qt程序
#【可選代碼】允許遠(yuǎn)程運(yùn)行 import os os.environ["DISPLAY"] = ":0.0" #【建議代碼】允許終端通過(guò)ctrl+c中斷窗口,方便調(diào)試 import signal signal.signal(signal.SIGINT, signal.SIG_DFL) timer = QtCore.QTimer() timer.start(100) # You may change this if you wish. timer.timeout.connect(lambda: None) # Let the interpreter run each 100 ms
加上調(diào)用函數(shù)進(jìn)行顯示的部分,這個(gè)顯示pyqt5窗口的基本程序就完成了
# 初始化窗口 import sys app = QtWidgets.QApplication(sys.argv) window = WINDOW() ui = Ui_MainWindow() ui.setupUi(window) window.showFullScreen() #全屏顯示 # window.show() #按繪制時(shí)的尺寸顯示 sys.exit(app.exec_())
在核桃派lcd屏上的效果展示
OpenCV圖像讀取及顯示
調(diào)用頭文件,opencv的頭文件只需要這一個(gè)
import cv2
打開攝像頭,其中傳入的參數(shù)1是攝像頭編號(hào),一般是從0開始往后排
cap = cv2.VideoCapture(1)
從攝像頭讀取一幀圖像,ret是讀取狀態(tài),frame是圖像數(shù)據(jù)
ret, frame = cap.read()
cap.read函數(shù)讀到的是bgr格式的,為了把opencv的圖像數(shù)據(jù)顯示到qt的label,需要先轉(zhuǎn)為rgb格式,并將圖像轉(zhuǎn)為Qt中用來(lái)表示圖像的QImage。
rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgbImage.shape qtImage = QImage(rgbImage.data, h, w, ch*w, QtGui.QImage.Format_RGB888)
label的setPixmap方法可以圖像數(shù)據(jù)覆蓋label
label.setPixmap(QPixmap.fromImage(qtImage))
顯示效果
線程,信號(hào)與槽
原代碼為了簡(jiǎn)單,沒(méi)有使用信號(hào)槽機(jī)制,不夠線程安全,我們這里使用qt自帶的多線程功能,他的使用很簡(jiǎn)單,只需要?jiǎng)?chuàng)建一個(gè)類并繼承自QThread, 然后將要運(yùn)行的東西寫到類里的run方法下面。實(shí)例化一個(gè)對(duì)象后,調(diào)用start方法即可創(chuàng)建新線程
class Work(QThread): def run(self): pass work = Work() work.start()
直接在線程內(nèi)調(diào)用函數(shù)去修改qt窗口的內(nèi)容,不能滿足線程安全。
我們需要?jiǎng)?chuàng)建一個(gè)信號(hào),把修改qt窗口的語(yǔ)句寫到一個(gè)槽內(nèi),連接他們,在想修改窗口時(shí)發(fā)出信號(hào),讓qt內(nèi)部去調(diào)度,防止跟其他qt內(nèi)部的線程發(fā)生沖突。
因?yàn)槲覀冞@個(gè)線程類繼承自QThread,所以可以在類內(nèi)定義信號(hào)。只需要實(shí)例化一個(gè)pyqtSignal對(duì)象即可,調(diào)用時(shí)括號(hào)內(nèi)的參數(shù)決定了槽函數(shù)必須有什么類型的參數(shù),以及發(fā)送信號(hào)時(shí)需要傳入什么參數(shù)。
signal_update_label = pyqtSignal( QPixmap)
槽函數(shù)就是隨便定義一個(gè)函數(shù),只要函數(shù)參數(shù)跟信號(hào)一樣就行。
label:QLabel def sloat_update_label( self, pixmap:QPixmap): self.label.setPixmap(pixmap)
使用emit方法即可發(fā)送信號(hào),qt內(nèi)部會(huì)進(jìn)行調(diào)度,將所有連接到本信號(hào)的函數(shù)都調(diào)出來(lái)運(yùn)行,并將參數(shù)傳給他們。這是qt實(shí)現(xiàn)線程安全的重要機(jī)制。
self.signal_update_label.emit(QPixmap.fromImage(qtImage))
本文轉(zhuǎn)載自:https://forum.walnutpi.com/t/topic/84
審核編輯:劉清
-
RGB
+關(guān)注
關(guān)注
4文章
799瀏覽量
58563 -
OpenCV
+關(guān)注
關(guān)注
31文章
635瀏覽量
41380 -
pyqt5
+關(guān)注
關(guān)注
0文章
25瀏覽量
3403
原文標(biāo)題:可視可交互!H618上用OpenCV讀取圖像顯示到PyQt5窗口上
文章出處:【微信號(hào):gh_79acfa3aa3e3,微信公眾號(hào):全志在線】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論