Python PyQt5 QImage 用法與範例

本篇 ShengYu 介紹 Python PyQt5 QImage 用法與範例,QImage 是專門處理影像 pixel 像素的類別,在這篇我們將會介紹 PyQt5 何使用 QImage 來讀取圖片並顯示出來。

以下的 Python PyQt5 QImage 用法與範例將分為這幾部分,

  • PyQt5 QImage 讀取圖片並顯示在 QLabel 上
  • PyQt5 QImage 用某顏色填充/填滿
  • PyQt5 QImage 修改像素
  • PyQt5 從 numpy.ndarray 初始化 QImage
  • PyQt5 從 cv2.imread 讀取影像並轉換成 QImage

PyQt5 QImage 讀取圖片並顯示在 QLabel 上

QImage 跟之前介紹的 Widget 不一樣,之前都是使用 QtWidgets 裡的元件,而 QImage 是為 I/O 或圖片 pixel 像素存取而設計的。如果你想要存取圖片的像素或是修改圖片像素,就需要使用 QImage,實際上要使用 QImage 時要配合著 QLabel 與 QPixmap一起使用,

這邊示範 PyQt5 QImage 基本用法,這邊先示範一個 label 搭配 QImage 使用,self.myqimage = QImage('lena.jpg') 建構 QImage 同時讀取圖片,因為 QLabel 只支援 QPixmap 顯示,所以我們這邊要將 QImage 轉換成 QPixmap,使用的是 QPixmap.fromImage() 函式,接下來用 QLabel.setPixmap() 將該 QImage 透過 QPixmap.fromImage() 轉成 QPixmap 設定給 mylabel,如果目錄下沒有 lena.jpg 這張圖片的話則會顯示空白的 label,範例如下,

python-pyqt-qimage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel)
from PyQt5.QtGui import QImage, QPixmap

class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setWindowTitle('my window')
self.setGeometry(50, 50, 200, 150)

layout = QVBoxLayout()
self.setLayout(layout)

self.mylabel = QLabel('this is an image', self)
layout.addWidget(self.mylabel)

self.myqimage = QImage('lena.jpg')
self.mylabel.setPixmap(QPixmap.fromImage(self.myqimage))

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

結果圖如下,

PyQt5 QImage 用某顏色填充/填滿

PyQt5 要將 QImage 用某顏色填充的話,可以使用 QImage.fill() 函式,以下例子示範用紅色填充,一開始先初始化 320x240 大小的 QImage 並且格式為 Format_RGB888,之後再用 QImage.fill() 填充 qRgb,

python-pyqt-qimage2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel)
from PyQt5.QtGui import QImage, QPixmap, qRgb

class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setWindowTitle('my window')
self.setGeometry(50, 50, 200, 150)

layout = QVBoxLayout()
self.setLayout(layout)

self.mylabel = QLabel('this is an image', self)
layout.addWidget(self.mylabel)

self.myqimage = QImage(320, 240, QImage.Format_RGB888)
self.myqimage.fill(qRgb(255, 0, 0))
self.mylabel.setPixmap(QPixmap.fromImage(self.myqimage))

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

結果圖如下,

承上例,再 QImage.fill() 裡也可以先用 QColor 再轉 rgb,

1
2
3
self.myqimage = QImage(320, 240, QImage.Format_RGB888)
self.myqimage.fill(QColor(255, 0, 0).rgb())
self.mylabel.setPixmap(QPixmap.fromImage(self.myqimage))

PyQt5 QImage 修改像素

PyQt5 QImage 要修改像素的話可以使用 QImage.setPixel(),這邊示範用 for 迴圈遍歷每一個 pixel,將每個 pixel 都設為藍色,

python-pyqt-qimage3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel)
from PyQt5.QtGui import QImage, QPixmap, QColor

class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setWindowTitle('my window')
self.setGeometry(50, 50, 200, 150)

layout = QVBoxLayout()
self.setLayout(layout)

self.mylabel = QLabel('this is an image', self)
layout.addWidget(self.mylabel)

self.myqimage = QImage(320, 240, QImage.Format_RGB888)
for x in range(self.myqimage.width()):
for y in range(self.myqimage.height()):
self.myqimage.setPixel(x, y, QColor(0, 0, 255).rgb())

self.mylabel.setPixmap(QPixmap.fromImage(self.myqimage))

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

結果圖如下,

上述例子是使用 QColor 轉換成 rgb,也可以直接使用 qRgb,例如將每個 pixel 改成綠色可以這樣寫,

1
2
3
4
5
from PyQt5.QtGui import qRgb
...
for x in range(self.myqimage.width()):
for y in range(self.myqimage.height()):
self.myqimage.setPixel(x, y, qRgb(0, 255, 0))

如果要將每個 pixel 都加 10 的話可以這樣寫,pixel 值超過 255 需要進行邊界處理,這邊先省略了,

1
2
3
4
5
r, g, b, a = QColor(self.myqimage.pixel(x, y)).getRgb()
r += 10
g += 10
b += 10
self.myqimage.setPixel(x, y, QColor(r, g, b, a).rgb())

PyQt5 從 numpy.ndarray 初始化 QImage

如果 PyQt5 要從 numpy.ndarray 初始化 QImage 的話,可以在 QImage() 建構子的第一個引數放入 numpy.ndarray,詳細用法請看下面例子,np.zeros() 是初始化一個 numpy.ndarray 並且用 0 來填充初始化,

python-pyqt-qimage4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel)
from PyQt5.QtGui import QImage, QPixmap, QColor
import numpy as np

class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setWindowTitle('my window')
self.setGeometry(50, 50, 200, 150)

layout = QVBoxLayout()
self.setLayout(layout)

self.mylabel = QLabel('this is an image', self)
layout.addWidget(self.mylabel)

img_np = np.zeros((240, 320, 3), dtype=np.uint8)
print(type(img_np)) # numpy.ndarray
print(type(img_np.data)) # memoryview
height, width, channel = img_np.shape
bytesPerline = 3 * width
self.myqimage = QImage(img_np.data, width, height, bytesPerline, QImage.Format_RGB888)
self.mylabel.setPixmap(QPixmap.fromImage(self.myqimage))

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

結果圖如下,

PyQt5 從 cv2.imread 讀取影像並轉換成 QImage

如果 PyQt5 要從 cv2.imread() 讀取影像並轉換成 QImage 的話,範例如下,從 cv2.imread() 讀入影像後,後面的步驟基本上跟前述例子一樣了,需要注意的是 OpenCV 的 pixel 擺放順序為 bgr,所以這邊要透過 QImage.rgbSwapped() 函式將 rgb 轉換成 bgr,

python-pyqt-qimage5.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel)
from PyQt5.QtGui import QImage, QPixmap
import cv2

class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setWindowTitle('my window')
self.setGeometry(50, 50, 200, 150)

layout = QVBoxLayout()
self.setLayout(layout)

self.mylabel = QLabel('this is an image', self)
layout.addWidget(self.mylabel)

img = cv2.imread('lena.jpg')
print(type(img)) # numpy.ndarray
print(type(img.data)) # memoryview
height, width, channel = img.shape
bytesPerline = 3 * width
self.myqimage = QImage(img.data, width, height, bytesPerline, QImage.Format_RGB888)
self.mylabel.setPixmap(QPixmap.fromImage(self.myqimage.rgbSwapped()))

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

以上就是 Python PyQt5 QImage 用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
Python 新手入門教學懶人包
Python PyQt5 新手入門教學
Python OpenCV 使用 PyQt5 顯示影像圖片