1. 程式人生 > >PyQt5入門以及與OpenCV的簡單整合

PyQt5入門以及與OpenCV的簡單整合

PyQt5與OpenCV簡介

PyQt

PyQt是Python語言的GUI程式設計解決方案之一。可以用來代替Python內建的Tkinter。其它替代者還有PyGTK、wxPython等。與Qt一樣,PyQt是一個自由軟體。

PyQt的開發者是英國的“Riverbank Computing”公司。它提供了GPL與商業協議兩種授權方式,因此它可以免費地用於自由軟體的開發。PyQt可以運行於Microsoft Windows、Mac OS X、Linux以及Unix的多數變種上。

pyqt5是一套Python繫結QT5應用的框架。它可用於Python 2和3。pyqt5的官方網站
http://www.riverbankcomputing.co.uk/news

pyqt5做為Python的一個模組,它有620多個類和6000個函式和方法。
pyqt5的類別分為幾個模組,包括以下:

QtCore
QtGui
QtWidgets
QtMultimedia
QtBluetooth
QtNetwork
QtPositioning
Enginio
QtWebSockets
QtWebKit
QtWebKitWidgets
QtXml
QtSvg
QtSql
QtTest

QtCore:包含了核心的非GUI功能。此模組用於處理時間、檔案和目錄、各種資料型別、流、URL、MIME型別、執行緒或程序。
QtGui包含類視窗系統整合、事件處理、二維圖形、基本成像、字型和文字。
qtwidgets模組包含創造經典桌面風格的使用者介面提供了一套UI元素的類。
QtMultimedia包含的類來處理多媒體內容和API來訪問相機和收音機的功能。
Qtbluetooth模組包含類的掃描裝置和連線並與他們互動。描述模組包含了網路程式設計的類。這些類便於TCP和IP和UDP客戶端和伺服器的編碼,使網路程式設計更容易和更便攜。
Qtpositioning包含類的利用各種可能的來源,確定位置,包括衛星、Wi-Fi、或一個文字檔案。
Enginio模組實現了客戶端庫訪問Qt雲服務託管的應用程式執行時。
Qtwebsockets模組包含實現WebSocket協議類。
QtWebKit包含一個基於Webkit2圖書館Web瀏覽器實現類。
Qtwebkitwidgets包含的類的基礎webkit1一用於qtwidgets應用Web瀏覽器的實現。
QtXml包含與XML檔案的類。這個模組為SAX和DOM API提供了實現。
QtSvg模組提供了顯示SVG檔案內容的類。可伸縮向量圖形(SVG)是一種描述二維圖形和圖形應用的語言。
QtSql模組提供操作資料庫的類。
QtTest包含的功能,使pyqt5應用程式的單元測試

PyQt5不相容PyQt4。PyQt5有一些巨大的改進。但是,遷移並不是很難,兩者的區別如下:
重新組合模組,一些模組已經被廢棄(QtScript),有些被分為兩個子模組(QtGui, QtWebKit)。
添加了新的模組,比如QtBluetooth, QtPositioning,和Enginio。
廢棄了SINGAL()和SLOT()的呼叫方式,使用了新的訊號和xx處理方式。
不再支援所有被標記為廢棄的或不建議使用的Qt API

OpenCV的全稱是Open Source Computer Vision Library,是一個跨平臺的計算機視覺庫。OpenCV是由英特爾公司發起並參與開發,以BSD許可證授權發行,可以在商業和研究領域中免費使用。OpenCV可用於開發實時的影象處理、計算機視覺以及模式識別程式。該程式庫也可以使用英特爾公司的IPP進行加速處理。

PyQt5 demo 3個

demo1, 簡單的GUI

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
PyQt5 demo 1
"""

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton

# demo1繼承自QWidget
class demo1(QWidget):

    # 建構函式
    def __init__(self):
        # 父類初始化
        super().__init__()
        self.init_show()

    def init_show(self):
        btn = QPushButton('Hello, PyQt5', self)
        btn.move(300, 200)
        btn.resize(100, 40)

        self.setWindowTitle('demo1')
        self.resize(800, 600)

# 執行
if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = demo1()
    w.show()
    app.exec()

demo2, 簡單的signal與slot


#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
simple signal
"""
import sys
from PyQt5.QtWidgets import QApplication, QDialog, QPushButton

app = QApplication(sys.argv)
dlg = QDialog()
dlg.setWindowTitle('just close it')
dlg.resize(300, 200)

btn = QPushButton(dlg)
btn.resize(100, 50)
btn.setText('click it!')
btn.move(100, 100)

# 將btn的clicked訊號與dlg的close槽連線
btn.clicked.connect(dlg.close)

dlg.show()
sys.exit(app.exec())

demo3, 簡單的串列埠通訊


#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""
PyQt5 demo 2
"""
# 匯入QSerialPort庫
from PyQt5.QtSerialPort import QSerialPort
from PyQt5.QtCore import QIODevice, QByteArray

port = QSerialPort('COM1')

# QSerialPort的一些通訊設定
port.setBaudRate(QSerialPort.Baud9600)
port.setFlowControl(QSerialPort.FlowControl(0))
port.setParity(QSerialPort.Parity(7))
port.setStopBits(QSerialPort.StopBits(1))

# 實際程式碼中應判斷是否開啟成功
port.open(QIODevice.ReadWrite)

byte = QByteArray()
byte.resize(6)
byte.fill('0')

port.write(byte)
port.flush()
port.close()

OpenCV demo

demo1, 簡單讀取一個image

import cv2

"""
simple opencv snippet
"""
# 讀取影象
img = cv2.imread('D:/wuhan.jpg')

# 顯示影象
cv2.imshow('wuhan', img)

# 等待鍵盤輸入事件
cv2.waitKey(0)

#銷燬所有window
cv2.destroyAllWindows()

demo2, 簡單的影象處理

import cv2

"""
simple opencv snippet 02
"""
# 讀取影象
img = cv2.imread('D:/lena.jpg', 0)

# 對影象做直方圖均衡處理
equ = cv2.equalizeHist(img)

# 採用cancy運算元進行邊緣檢測
edge = cv2.Canny(img, 50, 50)

# 顯示影象
cv2.imshow('img', img)
cv2.imshow('equ', equ)
cv2.imshow('edge', edge)

cv2.waitKey(0)
cv2.destroyAllWindows()

simple opencv snippet 02

PyQt5與OpenCV的簡單整合

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
import cv2 as cv
import numpy as np
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import (QApplication, QDialog, QFileDialog, QGridLayout,
                             QLabel, QPushButton)


class win(QDialog):
    def __init__(self):

        # 初始化一個img的ndarray, 用於儲存影象
        self.img = np.ndarray(())

        super().__init__()
        self.initUI()

    def initUI(self):
        self.resize(400, 300)
        self.btnOpen = QPushButton('Open', self)
        self.btnSave = QPushButton('Save', self)
        self.btnProcess = QPushButton('Process', self)
        self.btnQuit = QPushButton('Quit', self)
        self.label = QLabel()

        # 佈局設定
        layout = QGridLayout(self)
        layout.addWidget(self.label, 0, 1, 3, 4)
        layout.addWidget(self.btnOpen, 4, 1, 1, 1)
        layout.addWidget(self.btnSave, 4, 2, 1, 1)
        layout.addWidget(self.btnProcess, 4, 3, 1, 1)
        layout.addWidget(self.btnQuit, 4, 4, 1, 1)

        # 訊號與槽連線, PyQt5與Qt5相同, 訊號可繫結普通成員函式
        self.btnOpen.clicked.connect(self.openSlot)
        self.btnSave.clicked.connect(self.saveSlot)
        self.btnProcess.clicked.connect(self.processSlot)
        self.btnQuit.clicked.connect(self.close)

    def openSlot(self):
        # 呼叫開啟檔案diglog
        fileName, tmp = QFileDialog.getOpenFileName(
            self, 'Open Image', './__data', '*.png *.jpg *.bmp')

        if fileName is '':
            return

        # 採用opencv函式讀取資料
        self.img = cv.imread(fileName, -1)

        if self.img.size == 1:
            return

        self.refreshShow()

    def saveSlot(self):
        # 呼叫儲存檔案dialog
        fileName, tmp = QFileDialog.getSaveFileName(
            self, 'Save Image', './__data', '*.png *.jpg *.bmp', '*.png')

        if fileName is '':
            return
        if self.img.size == 1:
            return

        # 呼叫opencv寫入影象
        cv.imwrite(fileName, self.img)

    def processSlot(self):
        if self.img.size == 1:
            return

        # 對影象做模糊處理, 視窗設定為5x5
        self.img = cv.blur(self.img, (5, 5))

        self.refreshShow()

    def refreshShow(self):
        # 提取影象的尺寸和通道, 用於將opencv下的image轉換成Qimage
        height, width, channel = self.img.shape
        bytesPerLine = 3 * width
        self.qImg = QImage(self.img.data, width, height, bytesPerLine,
                           QImage.Format_RGB888).rgbSwapped()

        # 將Qimage顯示出來
        self.label.setPixmap(QPixmap.fromImage(self.qImg))


if __name__ == '__main__':
    a = QApplication(sys.argv)
    w = win()
    w.show()
    sys.exit(a.exec_())

PyQt5與OpenCV的簡單整合

結語

PyQt將Qt強大的介面開發功能帶入到Python語言中,結合Python語言的特性,可方便快捷地實現程式設計人員的想法,更可以結合OpenCV庫包含的種種演算法實現對影象和視訊的處理.

 

原文連結:

https://www.jianshu.com/p/4993f37b43e6